Version 1.12.0-dev.5.0

Merge commit '2ca0bc6d5a844c7e107e5502ec37669eabb35841' into dev
diff --git a/.gitattributes b/.gitattributes
index d77d09b..9dfc906 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -16,6 +16,9 @@
 tests/compiler/dart2js_extra/literal_string_juxtaposition_test.dart -text
 tests/language/raw_string_test.dart -text
 tests/language/multiline_strings_test.dart -text
+tests/language/multiline_newline_cr.dart -text
+tests/language/multiline_newline_crlf.dart -text
+tests/language/multiline_newline_lf.dart -text
 tests/lib/convert/json_pretty_test.dart -text
 tests/lib/mirrors/method_mirror_source_line_ending_test.dart -text
 tests/lib/mirrors/method_mirror_source_line_ending_cr.dart -text
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8383615..feb8c48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -68,6 +68,9 @@
     * A crashing bug involving transformers that only apply to non-public code
       has been fixed.
 
+    * A deadlock caused by declaring transformer followed by a lazy transformer
+      (such as the built-in `$dart2js` transformer) has been fixed.
+
     * A stack overflow caused by a transformer being run multiple times on the
       package that defines it has been fixed.
 
@@ -76,6 +79,29 @@
 
 [package spec proposal]: https://github.com/lrhn/dep-pkgspec
 
+* Formatter (`dartfmt`)
+
+  * Over 50 bugs fixed.
+
+  * Optimized line splitter is much faster and produces better output on
+    complex code.
+
+### VM Service Protocol Changes
+
+* **BREAKING** The service protocol now sends JSON-RPC 2.0-compatible
+  server-to-client events. To reflect this, the service protocol version is
+  now 2.0.
+
+* The service protocol now includes a `"jsonrpc"` property in its responses, as
+  opposed to `"json-rpc"`.
+
+* The service protocol now properly handles requests with non-string ids.
+  Numeric ids are no longer converted to strings, and null ids now don't produce
+  a response.
+
+* Some RPCs that didn't include a `"jsonrpc"` property in their responses now
+  include one.
+
 ## 1.11.2
 
 ### Core library changes
diff --git a/DEPS b/DEPS
index 50369e4..e6693ff 100644
--- a/DEPS
+++ b/DEPS
@@ -31,17 +31,17 @@
   "github_mirror":
       "https://chromium.googlesource.com/external/github.com/dart-lang/%s.git",
 
-  "gyp_rev": "@1752",
+  "gyp_rev": "@6ee91ad8659871916f9aa840d42e1513befdf638",
   "co19_rev": "@f95f109fea67127a220958794ef5200a63cb454c",
   "chromium_url": "http://src.chromium.org/svn",
   "chromium_git": "https://chromium.googlesource.com",
 
   # Revisions of /third_party/* dependencies.
   "7zip_rev" : "@19997",
-  "analyzer_cli_rev" : "@7436b45b160f99e806bef2aafd1e971e1aedfc4d",
+  "analyzer_cli_rev" : "@c4e628a8467f75ded563f029dfb2f1738856f471",
   "args_tag": "@0.13.0",
   "async_tag": "@1.2.0",
-  "barback_tag" : "@0.15.2+5",
+  "barback_tag" : "@0.15.2+6",
   "charcode_tag": "@1.1.0",
   "chrome_rev" : "@19997",
   "clang_rev" : "@28450",
@@ -51,8 +51,8 @@
   "csslib_tag" : "@0.12.0",
   "dartdoc_tag" : "@v0.1.0+5",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
-  "dart_style_tag": "@0.1.8+1",
-  "dev_compiler_rev": "@0.1.1",
+  "dart_style_tag": "@0.2.0",
+  "dev_compiler_rev": "@0.1.3",
   "fake_async_rev" : "@38614",
   "firefox_jsshell_rev" : "@45554",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
@@ -65,7 +65,7 @@
   "idl_parser_rev": "@6316d5982dc24b34d09dd8b10fbeaaff28d83a48",
   "intl_rev": "@32047558bd220a53c1f4d93a26d54b83533b1475",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
-  "json_rpc_2_rev": "@a38eefd116d910199de205f962af92fed87c164c",
+  "json_rpc_2_tag": "@1.1.1",
   "linter_tag": "@0.1.0",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@56b0fd6c018d6103862d07e8e27407b9ea3b963d",
@@ -100,7 +100,7 @@
   "stack_trace_tag": "@1.3.4",
   "string_scanner_rev": "@3e7617d6f74ba382e9b6130b1cc12091d89a9bc5",
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
-  "test_tag": "@0.12.3+4",
+  "test_tag": "@0.12.3+8",
   "test_reflective_loader_tag": "@0.0.3",
   "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "unittest_tag": "@0.11.6",
@@ -122,7 +122,7 @@
 deps = {
   # Stuff needed for GYP to run.
   Var("dart_root") + "/third_party/gyp":
-      (Var("googlecode_url") % "gyp") + "/trunk" + Var("gyp_rev"),
+      Var('chromium_git') + '/external/gyp.git' + Var("gyp_rev"),
 
   Var("dart_root") + "/tests/co19/src":
       (Var("github_mirror") % "co19") + Var("co19_rev"),
@@ -195,7 +195,7 @@
       (Var("github_mirror") % "csslib") + Var("csslib_tag"),
   Var("dart_root") + "/third_party/pkg_tested/dart_style":
       (Var("github_mirror") % "dart_style") + Var("dart_style_tag"),
-  Var("dart_root") + "/third_party/pkg/dartdoc":  
+  Var("dart_root") + "/third_party/pkg/dartdoc":
       "https://github.com/dart-lang/dartdoc.git" + Var("dartdoc_tag"),
   Var("dart_root") + "/third_party/pkg/dev_compiler":
       "https://github.com/dart-lang/dev_compiler.git" + Var("dev_compiler_rev"),
@@ -216,7 +216,7 @@
   Var("dart_root") + "/third_party/pkg/intl":
       (Var("github_mirror") % "intl") + Var("intl_rev"),
   Var("dart_root") + "/third_party/pkg/json_rpc_2":
-      (Var("github_mirror") % "json_rpc_2") + Var("json_rpc_2_rev"),
+      (Var("github_mirror") % "json_rpc_2") + Var("json_rpc_2_tag"),
   Var("dart_root") + "/third_party/pkg/linter":
       (Var("github_mirror") % "linter") + Var("linter_tag"),
   Var("dart_root") + "/third_party/pkg/logging":
@@ -230,16 +230,16 @@
       (Var("github_mirror") % "metatest") + Var("metatest_rev"),
   Var("dart_root") + "/third_party/pkg/mime":
       (Var("github_mirror") % "mime") + Var("mime_rev"),
-  Var("dart_root") + "/third_party/pkg/mustache4dart":  
-      Var("chromium_git")  
-      + "/external/github.com/valotas/mustache4dart.git"   
+  Var("dart_root") + "/third_party/pkg/mustache4dart":
+      Var("chromium_git")
+      + "/external/github.com/valotas/mustache4dart.git"
       + Var("mustache4dart_rev"),
   Var("dart_root") + "/third_party/pkg/oauth2":
       (Var("github_mirror") % "oauth2") + Var("oauth2_rev"),
   Var("dart_root") + "/third_party/pkg/observe":
       (Var("github_mirror") % "observe") + Var("observe_rev"),
   Var("dart_root") + "/third_party/observatory_pub_packages":
-     (Var("github_mirror") % "observatory_pub_packages") 
+     (Var("github_mirror") % "observatory_pub_packages")
       + Var("observatory_pub_packages_rev"),
   Var("dart_root") + "/third_party/pkg/package_config":
       (Var("github_mirror") % "package_config") +
@@ -254,11 +254,11 @@
       (Var("github_mirror") % "pub_semver") + Var("pub_semver_tag"),
   Var("dart_root") + "/third_party/pkg/pub":
       (Var("github_mirror") % "pub") + Var("pub_rev"),
-  Var("dart_root") + "/third_party/pkg/pub_cache":  
+  Var("dart_root") + "/third_party/pkg/pub_cache":
       (Var("github_mirror") % "pub_cache") + Var("pub_cache_tag"),
-  Var("dart_root") + "/third_party/pkg/quiver": 
-      Var("chromium_git")  
-      + "/external/github.com/google/quiver-dart.git"  
+  Var("dart_root") + "/third_party/pkg/quiver":
+      Var("chromium_git")
+      + "/external/github.com/google/quiver-dart.git"
       + Var("quiver_tag"),
   Var("dart_root") + "/third_party/pkg/scheduled_test":
       (Var("github_mirror") % "scheduled_test") +
@@ -266,7 +266,7 @@
   Var("dart_root") + "/third_party/pkg/shelf":
       (Var("github_mirror") % "shelf") + Var("shelf_rev"),
   Var("dart_root") + "/third_party/pkg/shelf_static":
-      "https://github.com/kevmoo/shelf_static.dart.git" +
+      "https://github.com/dart-lang/shelf_static.git" +
       Var("shelf_static_rev"),
   Var("dart_root") + "/third_party/pkg/shelf_web_socket":
       (Var("github_mirror") % "shelf_web_socket") +
diff --git a/pkg/analysis_server/benchmark/integration/README.md b/pkg/analysis_server/benchmark/integration/README.md
new file mode 100644
index 0000000..78431f9
--- /dev/null
+++ b/pkg/analysis_server/benchmark/integration/README.md
@@ -0,0 +1,72 @@
+# Running Benchmarks
+
+There are two entry points for running benchmarks:
+* **main.dart** - a general Dart application for running performance benchmarks
+* **local_runner.dart** - an example Dart application
+which sets up the local environment
+and then calls main.dart to run performance benchmarks
+
+## local_runner.dart
+
+This Dart application is one example for running performance benchmarks.
+When run, this application 1) extracts a branch from a git repository
+into a temporary directory, and 2) creates a symlink to the out or xcodebuild
+directory for proper package-root package resolution.
+Once setup is complete, this applications calls main.dart
+
+The required command line arguments are
+* **gitDir** = a path to the git repository containing the initial target source
+* **branch** = the branch containing the initial target source
+* **inputFile** = the instrumentation or log file
+
+Additional arguments are passed directly to main.dart.
+For example, you may want to specify --newTaskModel to measure performance
+with the new task model versus the old task model,
+or if the log was recorded on one machine and is played back on another,
+then you might need to specify -m<oldSrcPath>,<newSrcPath>
+to map the source paths for playback.
+When specifying additional arguments, any occurrences of @tmpSrcDir@
+will be replaced with the absolute path of the temporary directory
+into which the source was extracted.
+
+## main.dart
+
+This Dart application reads an instrumentation or local log file produced by
+analysis server, "replays" that interaction with the analysis server,
+compares the notifications and responses with what was recorded in the log,
+and produces a report. It assumes that the environment for playback has
+already been setup.
+The required command line arguments are
+*  **-i, --input             <filePath>**
+The input file specifying how this client should interact with the server.
+If the input file name is "stdin", then the instructions are read from stdin.
+*  **-m, --map               <oldSrcPath>,<newSrcPath>**
+This option defines a mapping from the original source directory <oldSrcPath>
+when the instrumentation or log file was generated
+to the target source directory <newSrcPath> used during performance testing.
+Multiple mappings can be specified.
+WARNING: The contents of the target directory will be modified
+*  **-t, --tmpSrcDir         <dirPath>**
+The temporary directory containing source used during performance measurement.
+WARNING: The contents of the target directory will be modified
+*  **--newTaskModel**       enable the use of the new task model
+*  **-d, --diagnosticPort** localhost port on which server
+                            will provide diagnostic web pages
+*  **-v, --verbose**        Verbose logging
+*  **--vv**                 Extra verbose logging
+*  **-h, --help**           Print this help information
+
+For each request recorded in the input file,
+the application sends a corresponding request to the analysis server
+and waits up to 60 seconds for a response to that request.
+If a response in not received in that time, then the application exits.
+Any responses that are received are compared with the recorded response.
+
+For each analysis-complete notification recorded in the input file,
+the application waits for the corresponding analysis-complete notification
+from the running analysis server.
+While it is waiting for an analysis-complete notification,
+the application monitors the stream of notifications.
+If there is a period of more than 60 seconds during which no communication
+is received from the server, the application assumes that the server is hung
+and exits.
diff --git a/pkg/analysis_server/benchmark/integration/driver.dart b/pkg/analysis_server/benchmark/integration/driver.dart
index 19243ea..a3167810 100644
--- a/pkg/analysis_server/benchmark/integration/driver.dart
+++ b/pkg/analysis_server/benchmark/integration/driver.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:math' show max, sqrt;
 
-import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:logging/logging.dart';
 
 import '../../test/integration/integration_test_methods.dart';
@@ -44,7 +43,14 @@
    */
   static const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 5);
 
-  final Logger logger;
+  final Logger logger = new Logger('Driver');
+
+  final bool newTaskModel;
+
+  /**
+   * The diagnostic port for Analysis Server or `null` if none.
+   */
+  final int diagnosticPort;
 
   /**
    * A flag indicating whether the server is running.
@@ -64,7 +70,7 @@
    */
   Completer<Results> _runCompleter = new Completer<Results>();
 
-  Driver(this.logger);
+  Driver({this.newTaskModel, this.diagnosticPort});
 
   /**
    * Return a [Future] that completes with the [Results] of running
@@ -97,7 +103,7 @@
    * Launch the analysis server.
    * Return a [Future] that completes when analysis server has started.
    */
-  Future startServer({int diagnosticPort}) async {
+  Future startServer() async {
     logger.log(Level.FINE, 'starting server');
     initializeInttestMixin();
     server = new Server();
@@ -108,7 +114,9 @@
     });
     running = true;
     return server
-        .start(diagnosticPort: diagnosticPort /*profileServer: true*/)
+        .start(
+            diagnosticPort: diagnosticPort,
+            newTaskModel: newTaskModel /*profileServer: true*/)
         .then((params) {
       server.listenToOutput(dispatchNotification);
       server.exitCode.then((_) {
@@ -193,7 +201,7 @@
     _printDuration(sb, new Duration(microseconds: meanTime));
     _printDuration(sb, time90th);
     _printDuration(sb, time99th);
-    _printColumn(sb, standardDeviation.toString(), 15, rightJustified: true);
+    _printDuration(sb, new Duration(microseconds: standardDeviation));
     _printDuration(sb, minTime);
     _printDuration(sb, maxTime);
     _printDuration(sb, new Duration(microseconds: totalTimeMicros));
@@ -212,9 +220,8 @@
   }
 
   void _printDuration(StringBuffer sb, Duration duration) {
-    sb.write('  ');
-    sb.write(duration);
-    sb.write(',');
+    _printColumn(sb, duration.inMilliseconds.toString(), 15,
+        rightJustified: true);
   }
 }
 
@@ -231,11 +238,6 @@
   void printResults() {
     print('');
     print('==================================================================');
-    if (engine.AnalysisEngine.instance.useTaskModel) {
-      print('New task model');
-    } else {
-      print('Old task model');
-    }
     print('');
     List<String> keys = measurements.keys.toList()..sort();
     int keyLen = keys.fold(0, (int len, String key) => max(len, key.length));
@@ -263,11 +265,11 @@
       }
     }
     /// TODO(danrubel) *** print warnings if driver caches are not empty ****
-    print('');
-    print(
-        '(1) uxr = UneXpected Results, or responses received from the server');
-    print(
-        '          that do not match the recorded response for that request.');
+    print('''
+
+(1) uxr = UneXpected Results or responses received from the server
+          that do not match the recorded response for that request.
+(2) all times in milliseconds''');
   }
 
   /**
@@ -294,7 +296,7 @@
     _printColumn(sb, 'error', 6, rightJustified: true);
     _printColumn(sb, 'uxr(1)', 6, rightJustified: true);
     sb.write('  ');
-    _printColumn(sb, 'mean', 15);
+    _printColumn(sb, 'mean(2)', 15);
     _printColumn(sb, '90th', 15);
     _printColumn(sb, '99th', 15);
     _printColumn(sb, 'std-dev', 15);
diff --git a/pkg/analysis_server/benchmark/integration/input_converter.dart b/pkg/analysis_server/benchmark/integration/input_converter.dart
index ef90131..3d9fd5a 100644
--- a/pkg/analysis_server/benchmark/integration/input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/input_converter.dart
@@ -62,7 +62,7 @@
    * from location where instrumentation or log file was generated
    * to the target location of the source using during performance measurement.
    */
-  final Map<String, String> srcPathMap;
+  final PathMap srcPathMap;
 
   /**
    * The root directory for all source being modified
@@ -70,13 +70,7 @@
    */
   final String tmpSrcDirPath;
 
-  /**
-   * The diagnostic port for Analysis Server or `null` if none.
-   */
-  final int diagnosticPort;
-
-  CommonInputConverter(this.tmpSrcDirPath, this.srcPathMap,
-      {this.diagnosticPort});
+  CommonInputConverter(this.tmpSrcDirPath, this.srcPathMap);
 
   /**
    * Return an operation for the notification or `null` if none.
@@ -95,7 +89,7 @@
     }
     if (event == SERVER_CONNECTED) {
       // {"event":"server.connected","params":{"version":"1.7.0"}}
-      return new StartServerOperation(diagnosticPort: diagnosticPort);
+      return new StartServerOperation();
     }
     if (eventsSeen.add(event)) {
       logger.log(Level.INFO, 'Ignored notification: $event\n  $json');
@@ -182,6 +176,14 @@
         this, requestMap.remove(json['id']), translateSrcPaths(json));
   }
 
+  void logOverlayContent() {
+    logger.log(Level.WARNING, '${overlays.length} overlays');
+    List<String> allPaths = overlays.keys.toList()..sort();
+    for (String filePath in allPaths) {
+      logger.log(Level.WARNING, 'overlay $filePath\n${overlays[filePath]}');
+    }
+  }
+
   /**
    * Process an error response from the server by either
    * completing the associated completer in the [responseCompleters]
@@ -242,13 +244,7 @@
    */
   translateSrcPaths(json) {
     if (json is String) {
-      String result = json;
-      srcPathMap.forEach((String oldPrefix, String newPrefix) {
-        if (json.startsWith(oldPrefix)) {
-          result = '$newPrefix${json.substring(oldPrefix.length)}';
-        }
-      });
-      return result;
+      return srcPathMap.translate(json);
     }
     if (json is List) {
       List result = [];
@@ -281,7 +277,7 @@
    * from location where instrumentation or log file was generated
    * to the target location of the source using during performance measurement.
    */
-  final Map<String, String> srcPathMap;
+  final PathMap srcPathMap;
 
   /**
    * The root directory for all source being modified
@@ -290,11 +286,6 @@
   final String tmpSrcDirPath;
 
   /**
-   * The diagnostic port for Analysis Server or `null` if none.
-   */
-  final int diagnosticPort;
-
-  /**
    * The number of lines read before the underlying converter was determined
    * or the end of file was reached.
    */
@@ -312,7 +303,7 @@
    */
   bool active = true;
 
-  InputConverter(this.tmpSrcDirPath, this.srcPathMap, {this.diagnosticPort});
+  InputConverter(this.tmpSrcDirPath, this.srcPathMap);
 
   @override
   Operation convert(String line) {
@@ -331,11 +322,9 @@
       throw 'Failed to determine input file format';
     }
     if (InstrumentationInputConverter.isFormat(line)) {
-      converter = new InstrumentationInputConverter(tmpSrcDirPath, srcPathMap,
-          diagnosticPort: diagnosticPort);
+      converter = new InstrumentationInputConverter(tmpSrcDirPath, srcPathMap);
     } else if (LogFileInputConverter.isFormat(line)) {
-      converter = new LogFileInputConverter(tmpSrcDirPath, srcPathMap,
-          diagnosticPort: diagnosticPort);
+      converter = new LogFileInputConverter(tmpSrcDirPath, srcPathMap);
     }
     if (converter != null) {
       return converter.convert(line);
@@ -350,6 +339,43 @@
   }
 }
 
+/**
+ * A container of [PathMapEntry]s used to translate a source path in the log
+ * before it is sent to the analysis server.
+ */
+class PathMap {
+  final List<PathMapEntry> entries = [];
+
+  void add(String oldSrcPrefix, String newSrcPrefix) {
+    entries.add(new PathMapEntry(oldSrcPrefix, newSrcPrefix));
+  }
+
+  String translate(String original) {
+    String result = original;
+    for (PathMapEntry entry in entries) {
+      result = entry.translate(result);
+    }
+    return result;
+  }
+}
+
+/**
+ * An entry in [PathMap] used to translate a source path in the log
+ * before it is sent to the analysis server.
+ */
+class PathMapEntry {
+  final String oldSrcPrefix;
+  final String newSrcPrefix;
+
+  PathMapEntry(this.oldSrcPrefix, this.newSrcPrefix);
+
+  String translate(String original) {
+    return original.startsWith(oldSrcPrefix)
+        ? '$newSrcPrefix${original.substring(oldSrcPrefix.length)}'
+        : original;
+  }
+}
+
 class _InputSink extends ChunkedConversionSink<String> {
   final Converter<String, Operation> converter;
   final outSink;
diff --git a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
index 11e2f9a..790da05 100644
--- a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
@@ -30,9 +30,8 @@
   StringBuffer readBuffer = null;
 
   InstrumentationInputConverter(
-      String tmpSrcDirPath, Map<String, String> srcPathMap,
-      {int diagnosticPort})
-      : super(tmpSrcDirPath, srcPathMap, diagnosticPort: diagnosticPort);
+      String tmpSrcDirPath, PathMap srcPathMap)
+      : super(tmpSrcDirPath, srcPathMap);
 
   @override
   Operation convert(String line) {
diff --git a/pkg/analysis_server/benchmark/integration/local_runner.dart b/pkg/analysis_server/benchmark/integration/local_runner.dart
index 1d8d245..78d8c2a 100644
--- a/pkg/analysis_server/benchmark/integration/local_runner.dart
+++ b/pkg/analysis_server/benchmark/integration/local_runner.dart
@@ -12,7 +12,7 @@
   /*
    * Parse arguments
    */
-  if (args.length != 3) printHelp('Expected 3 arguments');
+  if (args.length < 3) printHelp('Expected 3 arguments');
   var gitDir = new Directory(args[0]);
   if (!gitDir.existsSync()) printHelp('${gitDir.path} does not exist');
   if (!new Directory(join(gitDir.path, '.git')).existsSync()) printHelp(
@@ -58,15 +58,17 @@
   ]);
   if (result.exitCode != 0) throw 'failed to link out or xcodebuild: $result';
   /*
+   * Collect arguments
+   */
+  var perfArgs = ['-i${inputFile.path}', '-t$tmpSrcDirPath',];
+  for (int index = 3; index < args.length; ++index) {
+    perfArgs.add(args[index].replaceAll('@tmpSrcDir@', tmpSrcDirPath));
+  }
+  perfArgs.add('-m${gitDir.path},$tmpSrcDirPath');
+  /*
    * Launch the performance analysis tool
    */
-  performance.main([
-    //'-vv', // very verbose
-    //'-d8081', // analysis server localhost diagnostic port
-    '-i${inputFile.path}',
-    '-t$tmpSrcDirPath',
-    '-m${gitDir.path},$tmpSrcDirPath',
-  ]);
+  performance.main(perfArgs);
 }
 
 /// Print help and exit
@@ -76,9 +78,12 @@
     print('Error: $errMsg');
     print('');
   }
-  print('Arguments: <gitDir> <branch> <inputFile>');
-  print('gitDir = git repository containing the initial target source');
-  print('branch = the branch containing the initial target source');
-  print('inputFile = the instrumentation or log file');
+  print('''Required arguments: <gitDir> <branch> <inputFile>
+gitDir = a path to the git repository containing the initial target source
+branch = the branch containing the initial target source
+inputFile = the instrumentation or log file
+
+Optional arguments:''');
+  print(performance.argParser.usage);
   exit(1);
 }
diff --git a/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart b/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart
index dd6c35c..0781bae 100644
--- a/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart
@@ -23,9 +23,8 @@
  * into a series of operations to be sent to the analysis server.
  */
 class LogFileInputConverter extends CommonInputConverter {
-  LogFileInputConverter(String tmpSrcDirPath, Map<String, String> srcPathMap,
-      {int diagnosticPort})
-      : super(tmpSrcDirPath, srcPathMap, diagnosticPort: diagnosticPort);
+  LogFileInputConverter(String tmpSrcDirPath, PathMap srcPathMap)
+      : super(tmpSrcDirPath, srcPathMap);
 
   @override
   Operation convert(String line) {
diff --git a/pkg/analysis_server/benchmark/integration/main.dart b/pkg/analysis_server/benchmark/integration/main.dart
index 793110d..7cfb299 100644
--- a/pkg/analysis_server/benchmark/integration/main.dart
+++ b/pkg/analysis_server/benchmark/integration/main.dart
@@ -26,7 +26,8 @@
   });
   PerfArgs args = parseArgs(rawArgs);
 
-  Driver driver = new Driver(logger);
+  Driver driver = new Driver(
+      diagnosticPort: args.diagnosticPort, newTaskModel: args.newTaskModel);
   Stream<Operation> stream = openInput(args);
   StreamSubscription<Operation> subscription;
   subscription = stream.listen((Operation op) {
@@ -56,6 +57,7 @@
 const HELP_CMDLINE_OPTION = 'help';
 const INPUT_CMDLINE_OPTION = 'input';
 const MAP_OPTION = 'map';
+const NEW_TASK_MODEL_OPTION = 'newTaskModel';
 
 /**
  * The amount of time to give the server to respond to a shutdown request
@@ -67,6 +69,43 @@
 const VERBOSE_CMDLINE_OPTION = 'verbose';
 const VERY_VERBOSE_CMDLINE_OPTION = 'vv';
 
+ArgParser _argParser;
+
+ArgParser get argParser {
+  _argParser = new ArgParser();
+
+  _argParser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n'
+      'The input file specifying how this client should interact with the server.\n'
+      'If the input file name is "stdin", then the instructions are read from standard input.');
+  _argParser.addOption(MAP_OPTION,
+      abbr: 'm',
+      allowMultiple: true,
+      splitCommas: false,
+      help: '<oldSrcPath>,<newSrcPath>\n'
+          'This option defines a mapping from the original source directory <oldSrcPath>\n'
+          'when the instrumentation or log file was generated\n'
+          'to the target source directory <newSrcPath> used during performance testing.\n'
+          'Multiple mappings can be specified.\n'
+          'WARNING: The contents of the target directory will be modified');
+  _argParser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n'
+      'The temporary directory containing source used during performance measurement.\n'
+      'WARNING: The contents of the target directory will be modified');
+  _argParser.addFlag(NEW_TASK_MODEL_OPTION,
+      help: "enable the use of the new task model",
+      defaultsTo: false,
+      negatable: false);
+  _argParser.addOption(DIAGNOSTIC_PORT_OPTION,
+      abbr: 'd',
+      help: 'localhost port on which server will provide diagnostic web pages');
+  _argParser.addFlag(VERBOSE_CMDLINE_OPTION,
+      abbr: 'v', help: 'Verbose logging', negatable: false);
+  _argParser.addFlag(VERY_VERBOSE_CMDLINE_OPTION,
+      help: 'Extra verbose logging', negatable: false);
+  _argParser.addFlag(HELP_CMDLINE_OPTION,
+      abbr: 'h', help: 'Print this help information', negatable: false);
+  return _argParser;
+}
+
 /**
  * Open and return the input stream specifying how this client
  * should interact with the analysis server.
@@ -79,57 +118,28 @@
   } else {
     inputRaw = new File(args.inputPath).openRead();
   }
-  args.srcPathMap.forEach((oldPath, newPath) {
-    logger.log(
-        Level.INFO, 'mapping source path\n  from $oldPath\n  to   $newPath');
-  });
+  for (PathMapEntry entry in args.srcPathMap.entries) {
+    logger.log(Level.INFO, 'mapping source path\n'
+        '  from ${entry.oldSrcPrefix}\n  to   ${entry.newSrcPrefix}');
+  }
   logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}');
   return inputRaw
       .transform(SYSTEM_ENCODING.decoder)
       .transform(new LineSplitter())
-      .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap,
-          diagnosticPort: args.diagnosticPort));
+      .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap));
 }
 
 /**
  * Parse the command line arguments.
  */
 PerfArgs parseArgs(List<String> rawArgs) {
-  ArgParser parser = new ArgParser();
-
-  parser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n'
-      'The input file specifying how this client should interact with the server.\n'
-      'If the input file name is "stdin", then the instructions are read from standard input.');
-  parser.addOption(MAP_OPTION,
-      abbr: 'm',
-      allowMultiple: true,
-      splitCommas: false,
-      help: '<oldSrcPath>,<newSrcPath>\n'
-      'This option defines a mapping from the original source directory <oldSrcPath>\n'
-      'when the instrumentation or log file was generated\n'
-      'to the target source directory <newSrcPath> used during performance testing.\n'
-      'Multiple mappings can be specified.\n'
-      'WARNING: The contents of the target directory will be modified');
-  parser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n'
-      'The temporary directory containing source used during performance measurement.\n'
-      'WARNING: The contents of the target directory will be modified');
-  parser.addOption(DIAGNOSTIC_PORT_OPTION,
-      abbr: 'd',
-      help: 'localhost port on which server will provide diagnostic web pages');
-  parser.addFlag(VERBOSE_CMDLINE_OPTION,
-      abbr: 'v', help: 'Verbose logging', negatable: false);
-  parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION,
-      help: 'Extra verbose logging', negatable: false);
-  parser.addFlag(HELP_CMDLINE_OPTION,
-      abbr: 'h', help: 'Print this help information', negatable: false);
-
   ArgResults args;
   PerfArgs perfArgs = new PerfArgs();
   try {
-    args = parser.parse(rawArgs);
+    args = argParser.parse(rawArgs);
   } on Exception catch (e) {
     print(e);
-    printHelp(parser);
+    printHelp();
     exit(1);
   }
 
@@ -143,15 +153,14 @@
     showHelp = true;
   }
 
-  perfArgs.srcPathMap = <String, String>{};
   for (String pair in args[MAP_OPTION]) {
     if (pair is String) {
       int index = pair.indexOf(',');
       if (index != -1 && pair.indexOf(',', index + 1) == -1) {
-        String oldSrcPath = _withTrailingSeparator(pair.substring(0, index));
-        String newSrcPath = _withTrailingSeparator(pair.substring(index + 1));
-        if (new Directory(newSrcPath).existsSync()) {
-          perfArgs.srcPathMap[oldSrcPath] = newSrcPath;
+        String oldSrcPrefix = _withTrailingSeparator(pair.substring(0, index));
+        String newSrcPrefix = _withTrailingSeparator(pair.substring(index + 1));
+        if (new Directory(newSrcPrefix).existsSync()) {
+          perfArgs.srcPathMap.add(oldSrcPrefix, newSrcPrefix);
           continue;
         }
       }
@@ -166,6 +175,8 @@
     showHelp = true;
   }
 
+  perfArgs.newTaskModel = args[NEW_TASK_MODEL_OPTION];
+
   String portText = args[DIAGNOSTIC_PORT_OPTION];
   if (portText != null) {
     perfArgs.diagnosticPort = int.parse(portText, onError: (s) {
@@ -183,18 +194,18 @@
   }
 
   if (showHelp) {
-    printHelp(parser);
+    printHelp();
     exit(1);
   }
 
   return perfArgs;
 }
 
-void printHelp(ArgParser parser) {
+void printHelp() {
   print('');
   print('Launch and interact with the AnalysisServer');
   print('');
-  print(parser.usage);
+  print(argParser.usage);
 }
 
 /**
@@ -226,7 +237,7 @@
    * when the instrumentation or log file was generated
    * to the target source directory used during performance testing.
    */
-  Map<String, String> srcPathMap;
+  final PathMap srcPathMap = new PathMap();
 
   /**
    * The temporary directory containing source used during performance measurement.
@@ -237,4 +248,9 @@
    * The diagnostic port for Analysis Server or `null` if none.
    */
   int diagnosticPort;
+
+  /**
+   * `true` if the server should run using the new task model.
+   */
+  bool newTaskModel;
 }
diff --git a/pkg/analysis_server/benchmark/integration/operation.dart b/pkg/analysis_server/benchmark/integration/operation.dart
index f9ee62a..9e408d8 100644
--- a/pkg/analysis_server/benchmark/integration/operation.dart
+++ b/pkg/analysis_server/benchmark/integration/operation.dart
@@ -111,7 +111,7 @@
  * A [ResponseOperation] waits for a [JSON] response from the server.
  */
 class ResponseOperation extends Operation {
-  static final Duration responseTimeout = new Duration(seconds: 5);
+  static final Duration responseTimeout = new Duration(seconds: 60);
   final CommonInputConverter converter;
   final Map<String, dynamic> requestJson;
   final Map<String, dynamic> responseJson;
@@ -169,6 +169,7 @@
           'expected error:${format(expectedError)}\n'
           'but received:${format(actualResult)}';
       driver.results.recordUnexpectedResults(requestJson['method']);
+      converter.logOverlayContent();
       if (expectedError == null) {
         converter.logger.log(Level.SEVERE, message);
       } else {
@@ -179,13 +180,9 @@
 }
 
 class StartServerOperation extends Operation {
-  final int diagnosticPort;
-
-  StartServerOperation({this.diagnosticPort});
-
   @override
   Future perform(Driver driver) {
-    return driver.startServer(diagnosticPort: diagnosticPort);
+    return driver.startServer();
   }
 }
 
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 8d2995c..815a2d3 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -1575,6 +1575,7 @@
       
       
       
+      
     <h3>Requests</h3><dl><dt class="request"><a name="request_edit.format">edit.format</a> (<a href="#request_edit.format">#</a>)</dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "edit.format"
@@ -1940,6 +1941,48 @@
               The file edit that is to be applied to the given file to effect
               the sorting.
             </p>
+          </dd></dl></dd><dt class="request"><a name="request_edit.organizeDirectives">edit.organizeDirectives</a> (<a href="#request_edit.organizeDirectives">#</a>)</dt><dd><div class="box"><pre>request: {
+  "id": String
+  "method": "edit.organizeDirectives"
+  "params": {
+    "<b>file</b>": <a href="#type_FilePath">FilePath</a>
+  }
+}</pre><br><pre>response: {
+  "id": String
+  "error": <span style="color:#999999">optional</span> <a href="#type_RequestError">RequestError</a>
+  "result": {
+    "<b>edit</b>": <a href="#type_SourceFileEdit">SourceFileEdit</a>
+  }
+}</pre></div>
+        <p>
+          Organizes all of the directives - removes unused imports and sorts
+          directives of the given Dart file according to the
+          <a href="https://www.dartlang.org/articles/style-guide/">Dart Style Guide</a>.
+        </p>
+        <p>
+          If a request is made for a file that does not exist, does not belong
+          to an analysis root or is not a Dart file,
+          <tt>FILE_NOT_ANALYZED</tt> will be generated.
+        </p>
+        <p>
+          If directives of the Dart file cannot be organized, for example
+          because it has scan or parse errors, or by other reasons,
+          <tt>ORGANIZE_DIRECTIVES_ERROR</tt> will be generated. The message
+          will provide datails about the reason.
+        </p>
+        
+        
+      <h4>Parameters</h4><dl><dt class="field"><b><i>file ( <a href="#type_FilePath">FilePath</a> )</i></b></dt><dd>
+            
+            <p>
+              The Dart file to organize directives in.
+            </p>
+          </dd></dl><h4>Returns</h4><dl><dt class="field"><b><i>edit ( <a href="#type_SourceFileEdit">SourceFileEdit</a> )</i></b></dt><dd>
+            
+            <p>
+              The file edit that is to be applied to the given file to effect
+              the organizing.
+            </p>
           </dd></dl></dd></dl>
     <h2 class="domain"><a name="domain_execution">Domain: execution</a></h2>
       <p>
@@ -2289,27 +2332,28 @@
         
       <dl><dt class="field"><b><i>enableAsync ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
-            <p><b><i>Deprecated</i></b></p>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed async feature.
             </p>
           </dd><dt class="field"><b><i>enableDeferredLoading ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
-            <p><b><i>Deprecated</i></b></p>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed deferred loading feature.
             </p>
           </dd><dt class="field"><b><i>enableEnums ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
-            <p><b><i>Deprecated</i></b></p>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed enum feature.
             </p>
           </dd><dt class="field"><b><i>enableNullAwareOperators ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed "null aware operators" feature.
@@ -3359,6 +3403,13 @@
               not be satisfied because the content of the file changed before
               the requested results could be computed.
             </p>
+          </dd><dt class="value">FILE_NOT_ANALYZED</dt><dd>
+            
+            <p>
+              A request specified a FilePath which does not match a file in
+              an analysis root, or the requested operation is not available
+              for the file.
+            </p>
           </dd><dt class="value">FORMAT_INVALID_FILE</dt><dd>
             
             <p>
@@ -3381,7 +3432,7 @@
           </dd><dt class="value">GET_NAVIGATION_INVALID_FILE</dt><dd>
             
             <p>
-              An "analysis.getErrors" request specified a FilePath
+              An "analysis.getNavigation" request specified a FilePath
               which does not match a file currently subject to
               analysis.
             </p>
@@ -3421,6 +3472,12 @@
               The "--no-index" flag was passed when the analysis server created,
               but this API call requires an index to have been generated.
             </p>
+          </dd><dt class="value">ORGANIZE_DIRECTIVES_ERROR</dt><dd>
+            
+            <p>
+              An "edit.organizeDirectives" request specified a Dart file that
+              cannot be analyzed. The reason is described in the message.
+            </p>
           </dd><dt class="value">REFACTORING_REQUEST_CANCELLED</dt><dd>
             
             <p>
diff --git a/pkg/analysis_server/lib/edit/fix/fix_core.dart b/pkg/analysis_server/lib/edit/fix/fix_core.dart
index f546198..f38d59a 100644
--- a/pkg/analysis_server/lib/edit/fix/fix_core.dart
+++ b/pkg/analysis_server/lib/edit/fix/fix_core.dart
@@ -5,6 +5,7 @@
 library analysis_server.edit.fix.fix_core;
 
 import 'package:analysis_server/src/protocol.dart' show SourceChange;
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 
@@ -24,7 +25,8 @@
    * relevant fixes will be sorted before fixes with a lower relevance.
    */
   static final Comparator<Fix> SORT_BY_RELEVANCE = (Fix firstFix,
-      Fix secondFix) => firstFix.kind.relevance - secondFix.kind.relevance;
+          Fix secondFix) =>
+      firstFix.kind.relevance - secondFix.kind.relevance;
 
   /**
    * A description of the fix being proposed.
@@ -59,7 +61,8 @@
    * Return a list of fixes for the given [error]. The error was reported
    * after it's source was analyzed in the given [context].
    */
-  List<Fix> computeFixes(AnalysisContext context, AnalysisError error);
+  List<Fix> computeFixes(ResourceProvider resourceProvider,
+      AnalysisContext context, AnalysisError error);
 }
 
 /**
diff --git a/pkg/analysis_server/lib/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/edit/fix/fix_dart.dart
index 0e559e4..c009e68 100644
--- a/pkg/analysis_server/lib/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/edit/fix/fix_dart.dart
@@ -5,6 +5,7 @@
 library analysis_server.edit.fix.fix_dart;
 
 import 'package:analysis_server/edit/fix/fix_core.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -18,7 +19,8 @@
  */
 abstract class DartFixContributor extends FixContributor {
   @override
-  List<Fix> computeFixes(AnalysisContext context, AnalysisError error) {
+  List<Fix> computeFixes(ResourceProvider resourceProvider,
+      AnalysisContext context, AnalysisError error) {
     Source source = error.source;
     if (!AnalysisEngine.isDartFileName(source.fullName)) {
       return Fix.EMPTY_LIST;
@@ -32,12 +34,13 @@
     if (unit == null) {
       return Fix.EMPTY_LIST;
     }
-    return internalComputeFixes(unit, error);
+    return internalComputeFixes(resourceProvider, unit, error);
   }
 
   /**
    * Return a list of fixes for the given [error]. The error was reported
    * against the given compilation [unit].
    */
-  List<Fix> internalComputeFixes(CompilationUnit unit, AnalysisError error);
+  List<Fix> internalComputeFixes(ResourceProvider resourceProvider,
+      CompilationUnit unit, AnalysisError error);
 }
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 57fd203..21a0f7e 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -21,12 +21,10 @@
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
 import 'package:analysis_server/uri/resolver_provider.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
-import 'package:analyzer/source/sdk_ext.dart';
+import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -35,7 +33,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:package_config/packages.dart';
 import 'package:plugin/plugin.dart';
 
 typedef void OptionUpdater(AnalysisOptionsImpl options);
@@ -117,7 +114,7 @@
    * The [ContextManager] that handles the mapping from analysis roots to
    * context directories.
    */
-  ServerContextManager contextManager;
+  ContextManager contextManager;
 
   /**
    * A flag indicating whether the server is running.  When false, contexts
@@ -272,6 +269,17 @@
   Set<String> prevAnalyzedFiles;
 
   /**
+   * The default options used to create new analysis contexts.
+   */
+  AnalysisOptionsImpl defaultContextOptions = new AnalysisOptionsImpl();
+
+  /**
+   * The controller for sending [ContextsChangedEvent]s.
+   */
+  StreamController<ContextsChangedEvent> _onContextsChangedController =
+      new StreamController<ContextsChangedEvent>.broadcast();
+
+  /**
    * Initialize a newly created server to receive requests from and send
    * responses to the given [channel].
    *
@@ -284,9 +292,9 @@
    * running a full analysis server.
    */
   AnalysisServer(this.channel, this.resourceProvider,
-      OptimizingPubPackageMapProvider packageMapProvider, Index _index,
-      this.serverPlugin, this.options, this.defaultSdk,
-      this.instrumentationService, {ContextManager contextManager: null,
+      PubPackageMapProvider packageMapProvider, Index _index, this.serverPlugin,
+      this.options, this.defaultSdk, this.instrumentationService,
+      {ContextManager contextManager: null,
       ResolverProvider packageResolverProvider: null,
       this.rethrowExceptions: true})
       : index = _index,
@@ -294,20 +302,18 @@
     _performance = performanceDuringStartup;
     operationQueue = new ServerOperationQueue();
     if (contextManager == null) {
-      contextManager = new ServerContextManager(this, resourceProvider,
+      contextManager = new ContextManagerImpl(resourceProvider,
           packageResolverProvider, packageMapProvider, instrumentationService);
-      AnalysisOptionsImpl analysisOptions =
-          (contextManager as ServerContextManager).defaultOptions;
-      analysisOptions.incremental = true;
-      analysisOptions.incrementalApi = options.enableIncrementalResolutionApi;
-      analysisOptions.incrementalValidation =
-          options.enableIncrementalResolutionValidation;
-      analysisOptions.generateImplicitErrors = false;
-    } else if (contextManager is! ServerContextManager) {
-      // TODO(brianwilkerson) Remove this when the interface is complete.
-      throw new StateError(
-          'The contextManager must be an instance of ServerContextManager');
     }
+    ServerContextManagerCallbacks contextManagerCallbacks =
+        new ServerContextManagerCallbacks(this, resourceProvider);
+    contextManager.callbacks = contextManagerCallbacks;
+    defaultContextOptions.incremental = true;
+    defaultContextOptions.incrementalApi =
+        options.enableIncrementalResolutionApi;
+    defaultContextOptions.incrementalValidation =
+        options.enableIncrementalResolutionValidation;
+    defaultContextOptions.generateImplicitErrors = false;
     this.contextManager = contextManager;
     _noErrorNotification = options.noErrorNotification;
     AnalysisEngine.instance.logger = new AnalysisLogger();
@@ -353,7 +359,7 @@
    * The stream that is notified when contexts are added or removed.
    */
   Stream<ContextsChangedEvent> get onContextsChanged =>
-      contextManager.onContextsChanged;
+      _onContextsChangedController.stream;
 
   /**
    * The stream that is notified when a single file has been analyzed.
@@ -497,15 +503,14 @@
     {
       AnalysisContext containingContext = getContainingContext(path);
       if (containingContext != null) {
-        Source source = AbstractContextManager.createSourceInContext(
-            containingContext, file);
+        Source source =
+            ContextManagerImpl.createSourceInContext(containingContext, file);
         return new ContextSourcePair(containingContext, source);
       }
     }
     // try to find a context that analysed the file
     for (AnalysisContext context in folderMap.values) {
-      Source source =
-          AbstractContextManager.createSourceInContext(context, file);
+      Source source = ContextManagerImpl.createSourceInContext(context, file);
       SourceKind kind = context.getKindOf(source);
       if (kind != SourceKind.UNKNOWN) {
         return new ContextSourcePair(context, source);
@@ -1025,8 +1030,8 @@
             Uri uri = context.sourceFactory.restoreUri(source);
             if (uri.scheme != 'file') {
               preferredContext = context;
-              source = AbstractContextManager.createSourceInContext(
-                  context, resource);
+              source =
+                  ContextManagerImpl.createSourceInContext(context, resource);
               break;
             }
           }
@@ -1226,15 +1231,14 @@
     //
     // Update the defaults used to create new contexts.
     //
-    AnalysisOptionsImpl options = contextManager.defaultOptions;
     optionUpdaters.forEach((OptionUpdater optionUpdater) {
-      optionUpdater(options);
+      optionUpdater(defaultContextOptions);
     });
   }
 
   /**
-   * Return a set of contexts containing all of the resources in the given list
-   * of [resources].
+   * Return a set of all contexts whose associated folder is contained within,
+   * or equal to, one of the resources in the given list of [resources].
    */
   Set<AnalysisContext> _getContexts(List<Resource> resources) {
     Set<AnalysisContext> contexts = new HashSet<AnalysisContext>();
@@ -1337,45 +1341,26 @@
   PriorityChangeEvent(this.firstSource);
 }
 
-class ServerContextManager extends AbstractContextManager {
+class ServerContextManagerCallbacks extends ContextManagerCallbacks {
   final AnalysisServer analysisServer;
 
   /**
-   * The default options used to create new analysis contexts.
+   * The [ResourceProvider] by which paths are converted into [Resource]s.
    */
-  AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl();
+  final ResourceProvider resourceProvider;
 
-  /**
-   * The controller for sending [ContextsChangedEvent]s.
-   */
-  StreamController<ContextsChangedEvent> _onContextsChangedController;
-
-  ServerContextManager(this.analysisServer, ResourceProvider resourceProvider,
-      ResolverProvider packageResolverProvider,
-      OptimizingPubPackageMapProvider packageMapProvider,
-      InstrumentationService service)
-      : super(resourceProvider, packageResolverProvider, packageMapProvider,
-          service) {
-    _onContextsChangedController =
-        new StreamController<ContextsChangedEvent>.broadcast();
-  }
-
-  /**
-   * The stream that is notified when contexts are added or removed.
-   */
-  Stream<ContextsChangedEvent> get onContextsChanged =>
-      _onContextsChangedController.stream;
+  ServerContextManagerCallbacks(this.analysisServer, this.resourceProvider);
 
   @override
-  AnalysisContext addContext(
-      Folder folder, UriResolver packageUriResolver, Packages packages) {
+  AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
     InternalAnalysisContext context =
         AnalysisEngine.instance.createAnalysisContext();
     context.contentCache = analysisServer.overlayState;
     analysisServer.folderMap[folder] = context;
-    context.sourceFactory = _createSourceFactory(packageUriResolver, packages);
-    context.analysisOptions = new AnalysisOptionsImpl.from(defaultOptions);
-    _onContextsChangedController
+    context.sourceFactory = _createSourceFactory(disposition);
+    context.analysisOptions =
+        new AnalysisOptionsImpl.from(analysisServer.defaultContextOptions);
+    analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(added: [context]));
     analysisServer.schedulePerformAnalysisOperation(context);
     return context;
@@ -1406,20 +1391,15 @@
   }
 
   @override
-  void removeContext(Folder folder) {
+  void removeContext(Folder folder, List<String> flushedFiles) {
     AnalysisContext context = analysisServer.folderMap.remove(folder);
-
-    // See dartbug.com/22689, the AnalysisContext is computed in
-    // computeFlushedFiles instead of using the referenced context above, this
-    // is an attempt to be careful concerning the referenced issue.
-    List<String> flushedFiles = computeFlushedFiles(folder);
     sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
 
     if (analysisServer.index != null) {
       analysisServer.index.removeContext(context);
     }
     analysisServer.operationQueue.contextRemoved(context);
-    _onContextsChangedController
+    analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(removed: [context]));
     analysisServer.sendContextAnalysisDoneNotifications(
         context, AnalysisDoneReason.CONTEXT_REMOVED);
@@ -1446,10 +1426,10 @@
 
   @override
   void updateContextPackageUriResolver(
-      Folder contextFolder, UriResolver packageUriResolver, Packages packages) {
+      Folder contextFolder, FolderDisposition disposition) {
     AnalysisContext context = analysisServer.folderMap[contextFolder];
-    context.sourceFactory = _createSourceFactory(packageUriResolver, packages);
-    _onContextsChangedController
+    context.sourceFactory = _createSourceFactory(disposition);
+    analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(changed: [context]));
     analysisServer.schedulePerformAnalysisOperation(context);
   }
@@ -1463,25 +1443,17 @@
   }
 
   /**
-   * Set up a [SourceFactory] that resolves packages using the given
-   * [packageUriResolver] and [packages] resolution strategy.
+   * Set up a [SourceFactory] that resolves packages as appropriate for the
+   * given [disposition].
    */
-  SourceFactory _createSourceFactory(
-      UriResolver packageUriResolver, Packages packages) {
+  SourceFactory _createSourceFactory(FolderDisposition disposition) {
     UriResolver dartResolver = new DartUriResolver(analysisServer.defaultSdk);
     UriResolver resourceResolver = new ResourceUriResolver(resourceProvider);
     List<UriResolver> resolvers = [];
     resolvers.add(dartResolver);
-    if (packageUriResolver is PackageMapUriResolver) {
-      UriResolver sdkExtResolver =
-          new SdkExtUriResolver(packageUriResolver.packageMap);
-      resolvers.add(sdkExtResolver);
-    }
-    if (packageUriResolver != null) {
-      resolvers.add(packageUriResolver);
-    }
+    resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
     resolvers.add(resourceResolver);
-    return new SourceFactory(resolvers, packages);
+    return new SourceFactory(resolvers, disposition.packages);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/constants.dart b/pkg/analysis_server/lib/src/constants.dart
index b4acd97..f37446b 100644
--- a/pkg/analysis_server/lib/src/constants.dart
+++ b/pkg/analysis_server/lib/src/constants.dart
@@ -79,6 +79,7 @@
 const String EDIT_GET_AVAILABLE_REFACTORINGS = 'edit.getAvailableRefactorings';
 const String EDIT_GET_FIXES = 'edit.getFixes';
 const String EDIT_GET_REFACTORING = 'edit.getRefactoring';
+const String EDIT_ORGANIZE_DIRECTIVES = 'edit.organizeDirectives';
 const String EDIT_SORT_MEMBERS = 'edit.sortMembers';
 
 //
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index fb1c3b4..41fb266 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -10,13 +10,15 @@
 import 'dart:core' hide Resource;
 
 import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
+import 'package:analysis_server/src/server_options.dart';
 import 'package:analysis_server/uri/resolver_provider.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
+import 'package:analyzer/source/package_map_provider.dart';
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/source/path_filter.dart';
+import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -29,15 +31,287 @@
 import 'package:yaml/yaml.dart';
 
 /**
+ * Information tracked by the [ContextManager] for each context.
+ */
+class ContextInfo {
+  /**
+   * The [ContextManager] which is tracking this information.
+   */
+  final ContextManagerImpl contextManager;
+
+  /**
+   * The [Folder] for which this information object is created.
+   */
+  final Folder folder;
+
+  /// The [PathFilter] used to filter sources from being analyzed.
+  final PathFilter pathFilter;
+
+  /**
+   * The enclosed pubspec-based contexts.
+   */
+  final List<ContextInfo> children = <ContextInfo>[];
+
+  /**
+   * The package root for this context, or null if there is no package root.
+   */
+  String packageRoot;
+
+  /**
+   * The [ContextInfo] that encloses this one, or `null` if this is the virtual
+   * [ContextInfo] object that acts as the ancestor of all other [ContextInfo]
+   * objects.
+   */
+  ContextInfo parent;
+
+  /**
+   * The package description file path for this context.
+   */
+  String packageDescriptionPath;
+
+  /**
+   * Paths to files which determine the folder disposition and package map.
+   *
+   * TODO(paulberry): if any of these files are outside of [folder], they won't
+   * be watched for changes.  I believe the use case for watching these files
+   * is no longer relevant.
+   */
+  Set<String> _dependencies = new Set<String>();
+
+  /**
+   * The analysis context that was created for the [folder].
+   */
+  AnalysisContext context;
+
+  /**
+   * Map from full path to the [Source] object, for each source that has been
+   * added to the context.
+   */
+  Map<String, Source> sources = new HashMap<String, Source>();
+
+  ContextInfo(ContextManagerImpl contextManager, this.parent, Folder folder,
+      File packagespecFile, this.packageRoot)
+      : contextManager = contextManager,
+        folder = folder,
+        pathFilter = new PathFilter(
+            contextManager.resourceProvider.pathContext, folder.path, null) {
+    packageDescriptionPath = packagespecFile.path;
+    parent.children.add(this);
+  }
+
+  /**
+   * Create the virtual [ContextInfo] which acts as an ancestor to all other
+   * [ContextInfo]s.
+   */
+  ContextInfo._root()
+      : contextManager = null,
+        folder = null,
+        pathFilter = null;
+
+  /**
+   * Iterate through all [children] and their children, recursively.
+   */
+  Iterable<ContextInfo> get descendants sync* {
+    for (ContextInfo child in children) {
+      yield child;
+      yield* child.descendants;
+    }
+  }
+
+  /**
+   * Returns `true` if this is a "top level" context, meaning that the folder
+   * associated with it is not contained within any other folders that have an
+   * associated context.
+   */
+  bool get isTopLevel => parent.parent == null;
+
+  /**
+   * Returns `true` if [path] is excluded, as it is in one of the children.
+   */
+  bool excludes(String path) {
+    return children.any((child) {
+      return child.folder.contains(path);
+    });
+  }
+
+  /**
+   * Returns `true` if [resource] is excluded, as it is in one of the children.
+   */
+  bool excludesResource(Resource resource) => excludes(resource.path);
+
+  /**
+   * Return the first [ContextInfo] in [children] whose associated folder is or
+   * contains [path].  If there is no such [ContextInfo], return `null`.
+   */
+  ContextInfo findChildInfoFor(String path) {
+    for (ContextInfo info in children) {
+      if (info.folder.isOrContains(path)) {
+        return info;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Determine if the given [path] is one of the dependencies most recently
+   * passed to [setDependencies].
+   */
+  bool hasDependency(String path) => _dependencies.contains(path);
+
+  /// Returns `true` if  [path] should be ignored.
+  bool ignored(String path) => pathFilter.ignored(path);
+
+  /**
+   * Returns `true` if [path] is the package description file for this context
+   * (pubspec.yaml or .packages).
+   */
+  bool isPathToPackageDescription(String path) =>
+      path == packageDescriptionPath;
+
+  /**
+   * Update the set of dependencies for this context.
+   */
+  void setDependencies(Iterable<String> newDependencies) {
+    _dependencies = newDependencies.toSet();
+  }
+}
+
+/**
  * Class that maintains a mapping from included/excluded paths to a set of
  * folders that should correspond to analysis contexts.
  */
-abstract class AbstractContextManager implements ContextManager {
+abstract class ContextManager {
+  // TODO(brianwilkerson) Support:
+  //   setting the default analysis options
+  //   setting the default content cache
+  //   setting the default SDK
+  //   maintaining AnalysisContext.folderMap (or remove it)
+  //   telling server when a context has been added or removed (see onContextsChanged)
+  //   telling server when a context needs to be re-analyzed
+  //   notifying the client when results should be flushed
+  //   using analyzeFileFunctions to determine which files to analyze
+  //
+  // TODO(brianwilkerson) Move this class to a public library.
 
   /**
+   * Get the callback interface used to create, destroy, and update contexts.
+   */
+  ContextManagerCallbacks get callbacks;
+
+  /**
+   * Set the callback interface used to create, destroy, and update contexts.
+   */
+  void set callbacks(ContextManagerCallbacks value);
+
+  /**
+   * Return the list of excluded paths (folders and files) most recently passed
+   * to [setRoots].
+   */
+  List<String> get excludedPaths;
+
+  /**
+   * Return the list of included paths (folders and files) most recently passed
+   * to [setRoots].
+   */
+  List<String> get includedPaths;
+
+  /**
+   * Return a list of all of the contexts reachable from the given
+   * [analysisRoot] (the context associated with [analysisRoot] and all of its
+   * descendants).
+   */
+  List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot);
+
+  /**
+   * Return `true` if the given absolute [path] is in one of the current
+   * root folders and is not excluded.
+   */
+  bool isInAnalysisRoot(String path);
+
+  /**
+   * Rebuild the set of contexts from scratch based on the data last sent to
+   * [setRoots]. Only contexts contained in the given list of analysis [roots]
+   * will be rebuilt, unless the list is `null`, in which case every context
+   * will be rebuilt.
+   */
+  void refresh(List<Resource> roots);
+
+  /**
+   * Change the set of paths which should be used as starting points to
+   * determine the context directories.
+   */
+  void setRoots(List<String> includedPaths, List<String> excludedPaths,
+      Map<String, String> packageRoots);
+}
+
+/**
+ * Callback interface used by [ContextManager] to (a) request that contexts be
+ * created, destroyed or updated, (b) inform the client when "pub list"
+ * operations are in progress, and (c) determine which files should be
+ * analyzed.
+ *
+ * TODO(paulberry): eliminate this interface, and instead have [ContextManager]
+ * operations return data structures describing how context state should be
+ * modified.
+ */
+abstract class ContextManagerCallbacks {
+  /**
+   * Create and return a new analysis context, allowing [disposition] to govern
+   * details of how the context is to be created.
+   */
+  AnalysisContext addContext(Folder folder, FolderDisposition disposition);
+
+  /**
+   * Called when the set of files associated with a context have changed (or
+   * some of those files have been modified).  [changeSet] is the set of
+   * changes that need to be applied to the context.
+   */
+  void applyChangesToContext(Folder contextFolder, ChangeSet changeSet);
+
+  /**
+   * Called when the ContextManager is about to start computing the package
+   * map.
+   */
+  void beginComputePackageMap() {
+    // By default, do nothing.
+  }
+
+  /**
+   * Called when the ContextManager has finished computing the package map.
+   */
+  void endComputePackageMap() {
+    // By default, do nothing.
+  }
+
+  /**
+   * Remove the context associated with the given [folder].  [flushedFiles] is
+   * a list of the files which will be "orphaned" by removing this context
+   * (they will no longer be analyzed by any context).
+   */
+  void removeContext(Folder folder, List<String> flushedFiles);
+
+  /**
+   * Return `true` if the given [file] should be analyzed.
+   */
+  bool shouldFileBeAnalyzed(File file);
+
+  /**
+   * Called when the disposition for a context has changed.
+   */
+  void updateContextPackageUriResolver(
+      Folder contextFolder, FolderDisposition disposition);
+}
+
+/**
+ * Class that maintains a mapping from included/excluded paths to a set of
+ * folders that should correspond to analysis contexts.
+ */
+class ContextManagerImpl implements ContextManager {
+  /**
    * Temporary flag to hide WIP .packages support (DEP 5).
    */
-  static bool ENABLE_PACKAGESPEC_SUPPORT = false;
+  static bool ENABLE_PACKAGESPEC_SUPPORT = serverOptions.isSet(
+      'ContextManagerImpl.ENABLE_PACKAGESPEC_SUPPORT', defaultValue: true);
 
   /**
    * The name of the `lib` directory.
@@ -60,12 +334,6 @@
   static const String PACKAGE_SPEC_NAME = '.packages';
 
   /**
-   * [_ContextInfo] object for each included directory in the most
-   * recent successful call to [setRoots].
-   */
-  Map<Folder, _ContextInfo> _contexts = new HashMap<Folder, _ContextInfo>();
-
-  /**
    * The [ResourceProvider] using which paths are converted into [Resource]s.
    */
   final ResourceProvider resourceProvider;
@@ -109,7 +377,7 @@
    * Provider which is used to determine the mapping from package name to
    * package folder.
    */
-  final OptimizingPubPackageMapProvider _packageMapProvider;
+  final PubPackageMapProvider _packageMapProvider;
 
   /// Provider of analysis options.
   AnalysisOptionsProvider analysisOptionsProvider =
@@ -120,70 +388,59 @@
    */
   final InstrumentationService _instrumentationService;
 
-  AbstractContextManager(this.resourceProvider, this.packageResolverProvider,
+  @override
+  ContextManagerCallbacks callbacks;
+
+  /**
+   * Virtual [ContextInfo] which acts as the ancestor of all other
+   * [ContextInfo]s.
+   */
+  final ContextInfo _rootInfo = new ContextInfo._root();
+
+  /**
+   * Stream subscription we are using to watch each analysis root directory for
+   * changes.
+   */
+  final Map<Folder, StreamSubscription<WatchEvent>> _changeSubscriptions =
+      <Folder, StreamSubscription<WatchEvent>>{};
+
+  ContextManagerImpl(this.resourceProvider, this.packageResolverProvider,
       this._packageMapProvider, this._instrumentationService) {
     pathContext = resourceProvider.pathContext;
   }
 
-  /**
-   * Create and return a new analysis context.
-   */
-  AnalysisContext addContext(
-      Folder folder, UriResolver packageUriResolver, Packages packages);
-
-  /**
-   * Called when the set of files associated with a context have changed (or
-   * some of those files have been modified).  [changeSet] is the set of
-   * changes that need to be applied to the context.
-   */
-  void applyChangesToContext(Folder contextFolder, ChangeSet changeSet);
-
-  /**
-   * We are about to start computing the package map.
-   */
-  void beginComputePackageMap() {
-    // Do nothing.
-  }
-
-  /**
-   * Compute the set of files that are being flushed, this is defined as
-   * the set of sources in the removed context (context.sources), that are
-   * orphaned by this context being removed (no other context includes this
-   * file.)
-   */
-  List<String> computeFlushedFiles(Folder folder) {
-    AnalysisContext context = _contexts[folder].context;
-    HashSet<String> flushedFiles = new HashSet<String>();
-    for (Source source in context.sources) {
-      flushedFiles.add(source.fullName);
-    }
-    for (_ContextInfo contextInfo in _contexts.values) {
-      AnalysisContext contextN = contextInfo.context;
-      if (context != contextN) {
-        for (Source source in contextN.sources) {
-          flushedFiles.remove(source.fullName);
-        }
-      }
-    }
-    return flushedFiles.toList(growable: false);
-  }
-
   @override
   List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
     List<AnalysisContext> contexts = <AnalysisContext>[];
-    _contexts.forEach((Folder contextFolder, _ContextInfo info) {
-      if (analysisRoot.isOrContains(contextFolder.path)) {
-        contexts.add(info.context);
+    ContextInfo innermostContainingInfo =
+        _getInnermostContextInfoFor(analysisRoot.path);
+    void addContextAndDescendants(ContextInfo info) {
+      contexts.add(info.context);
+      info.children.forEach(addContextAndDescendants);
+    }
+    if (innermostContainingInfo != null) {
+      if (analysisRoot == innermostContainingInfo.folder) {
+        addContextAndDescendants(innermostContainingInfo);
+      } else {
+        for (ContextInfo info in innermostContainingInfo.children) {
+          if (analysisRoot.isOrContains(info.folder.path)) {
+            addContextAndDescendants(info);
+          }
+        }
       }
-    });
+    }
     return contexts;
   }
 
   /**
-   * We have finished computing the package map.
+   * For testing: get the [ContextInfo] object for the given [folder], if any.
    */
-  void endComputePackageMap() {
-    // Do nothing.
+  ContextInfo getContextInfoFor(Folder folder) {
+    ContextInfo info = _getInnermostContextInfoFor(folder.path);
+    if (folder == info.folder) {
+      return info;
+    }
+    return null;
   }
 
   @override
@@ -192,9 +449,9 @@
     if (_isExcluded(path)) {
       return false;
     }
-    // check if in of the roots
-    for (Folder root in _contexts.keys) {
-      if (root.contains(path)) {
+    // check if in one of the roots
+    for (ContextInfo info in _rootInfo.children) {
+      if (info.folder.contains(path)) {
         return true;
       }
     }
@@ -202,12 +459,11 @@
     return false;
   }
 
-  /// Process [options] for the context [folder].
-  void processOptionsForContext(Folder folder, Map<String, YamlNode> options) {
-    _ContextInfo info = _contexts[folder];
-    if (info == null) {
-      return;
-    }
+  /**
+   * Process [options] for the context having info [info].
+   */
+  void processOptionsForContext(
+      ContextInfo info, Map<String, YamlNode> options) {
     YamlMap analyzer = options['analyzer'];
     if (analyzer == null) {
       // No options for analyzer.
@@ -217,21 +473,22 @@
     // Set ignore patterns.
     YamlList exclude = analyzer['exclude'];
     if (exclude != null) {
-      setIgnorePatternsForContext(folder, exclude);
+      setIgnorePatternsForContext(info, exclude);
     }
   }
 
   @override
   void refresh(List<Resource> roots) {
     // Destroy old contexts
-    List<Folder> contextFolders = _contexts.keys.toList();
+    List<ContextInfo> contextInfos = _rootInfo.descendants.toList();
     if (roots == null) {
-      contextFolders.forEach(_destroyContext);
+      contextInfos.forEach(_destroyContext);
     } else {
       roots.forEach((Resource resource) {
-        contextFolders.forEach((Folder contextFolder) {
-          if (resource is Folder && resource.isOrContains(contextFolder.path)) {
-            _destroyContext(contextFolder);
+        contextInfos.forEach((ContextInfo contextInfo) {
+          if (resource is Folder &&
+              resource.isOrContains(contextInfo.folder.path)) {
+            _destroyContext(contextInfo);
           }
         });
       });
@@ -242,18 +499,11 @@
   }
 
   /**
-   * Remove the context associated with the given [folder].
+   * Sets the [ignorePatterns] for the context having info [info].
    */
-  void removeContext(Folder folder);
-
-  /// Sets the [ignorePatterns] for the context [folder].
-  void setIgnorePatternsForContext(Folder folder, List<String> ignorePatterns) {
-    _ContextInfo info = _contexts[folder];
-    if (info == null) {
-      return;
-    }
-    var pathFilter = info.pathFilter;
-    pathFilter.setIgnorePatterns(ignorePatterns);
+  void setIgnorePatternsForContext(
+      ContextInfo info, List<String> ignorePatterns) {
+    info.pathFilter.setIgnorePatterns(ignorePatterns);
   }
 
   @override
@@ -271,7 +521,7 @@
       }
     });
 
-    List<Folder> contextFolders = _contexts.keys.toList();
+    List<ContextInfo> contextInfos = _rootInfo.descendants.toList();
     // included
     Set<Folder> includedFolders = new HashSet<Folder>();
     for (int i = 0; i < includedPaths.length; i++) {
@@ -290,33 +540,35 @@
     List<String> oldExcludedPaths = this.excludedPaths;
     this.excludedPaths = excludedPaths;
     // destroy old contexts
-    for (Folder contextFolder in contextFolders) {
+    for (ContextInfo contextInfo in contextInfos) {
       bool isIncluded = includedFolders.any((folder) {
-        return folder.isOrContains(contextFolder.path);
+        return folder.isOrContains(contextInfo.folder.path);
       });
       if (!isIncluded) {
-        _destroyContext(contextFolder);
+        _destroyContext(contextInfo);
       }
     }
     // Update package roots for existing contexts
-    _contexts.forEach((Folder folder, _ContextInfo info) {
-      String newPackageRoot = normalizedPackageRoots[folder.path];
+    for (ContextInfo info in _rootInfo.descendants) {
+      String newPackageRoot = normalizedPackageRoots[info.folder.path];
       if (info.packageRoot != newPackageRoot) {
         info.packageRoot = newPackageRoot;
-        _recomputePackageUriResolver(info);
+        _recomputeFolderDisposition(info);
       }
-    });
+    }
     // create new contexts
     for (Folder includedFolder in includedFolders) {
-      bool wasIncluded = contextFolders.any((folder) {
-        return folder.isOrContains(includedFolder.path);
+      bool wasIncluded = contextInfos.any((info) {
+        return info.folder.isOrContains(includedFolder.path);
       });
       if (!wasIncluded) {
-        _createContexts(includedFolder, false);
+        _changeSubscriptions[includedFolder] =
+            includedFolder.changes.listen(_handleWatchEvent);
+        _createContexts(_rootInfo, includedFolder, false);
       }
     }
     // remove newly excluded sources
-    _contexts.forEach((folder, info) {
+    for (ContextInfo info in _rootInfo.descendants) {
       // prepare excluded sources
       Map<String, Source> excludedSources = new HashMap<String, Source>();
       info.sources.forEach((String path, Source source) {
@@ -331,31 +583,21 @@
         info.sources.remove(path);
         changeSet.removedSource(source);
       });
-      applyChangesToContext(folder, changeSet);
-    });
+      callbacks.applyChangesToContext(info.folder, changeSet);
+    }
     // add previously excluded sources
-    _contexts.forEach((folder, info) {
+    for (ContextInfo info in _rootInfo.descendants) {
       ChangeSet changeSet = new ChangeSet();
-      _addPreviouslyExcludedSources(info, changeSet, folder, oldExcludedPaths);
-      applyChangesToContext(folder, changeSet);
-    });
+      _addPreviouslyExcludedSources(
+          info, changeSet, info.folder, oldExcludedPaths);
+      callbacks.applyChangesToContext(info.folder, changeSet);
+    }
   }
 
   /**
-   * Return `true` if the given [file] should be analyzed.
-   */
-  bool shouldFileBeAnalyzed(File file);
-
-  /**
-   * Called when the package map for a context has changed.
-   */
-  void updateContextPackageUriResolver(
-      Folder contextFolder, UriResolver packageUriResolver, Packages packages);
-
-  /**
    * Resursively adds all Dart and HTML files to the [changeSet].
    */
-  void _addPreviouslyExcludedSources(_ContextInfo info, ChangeSet changeSet,
+  void _addPreviouslyExcludedSources(ContextInfo info, ChangeSet changeSet,
       Folder folder, List<String> oldExcludedPaths) {
     if (info.excludesResource(folder)) {
       return;
@@ -377,7 +619,7 @@
       // add files, recurse into folders
       if (child is File) {
         // ignore if should not be analyzed at all
-        if (!shouldFileBeAnalyzed(child)) {
+        if (!callbacks.shouldFileBeAnalyzed(child)) {
           continue;
         }
         // ignore if was not excluded
@@ -402,7 +644,7 @@
   /**
    * Resursively adds all Dart and HTML files to the [changeSet].
    */
-  void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextInfo info) {
+  void _addSourceFiles(ChangeSet changeSet, Folder folder, ContextInfo info) {
     if (info.excludesResource(folder) || folder.shortName.startsWith('.')) {
       return;
     }
@@ -422,7 +664,7 @@
       }
       // add files, recurse into folders
       if (child is File) {
-        if (shouldFileBeAnalyzed(child)) {
+        if (callbacks.shouldFileBeAnalyzed(child)) {
           Source source = createSourceInContext(info.context, child);
           changeSet.addedSource(source);
           info.sources[path] = source;
@@ -437,18 +679,8 @@
     }
   }
 
-  /**
-   * Cancel all dependency subscriptions for the given context.
-   */
-  void _cancelDependencySubscriptions(_ContextInfo info) {
-    for (StreamSubscription<WatchEvent> s in info.dependencySubscriptions) {
-      s.cancel();
-    }
-    info.dependencySubscriptions.clear();
-  }
-
   void _checkForPackagespecUpdate(
-      String path, _ContextInfo info, Folder folder) {
+      String path, ContextInfo info, Folder folder) {
     // Check to see if this is the .packages file for this context and if so,
     // update the context's source factory.
     if (pathContext.basename(path) == PACKAGE_SPEC_NAME &&
@@ -457,22 +689,52 @@
       if (packagespec.exists) {
         Packages packages = _readPackagespec(packagespec);
         if (packages != null) {
-          updateContextPackageUriResolver(folder, null, packages);
+          callbacks.updateContextPackageUriResolver(
+              folder, new PackagesFileDisposition(packages));
         }
       }
     }
   }
 
   /**
-   * Compute the appropriate package URI resolver for [folder], and store
-   * dependency information in [info]. Return `null` if no package map can
-   * be computed.
+   * Compute the set of files that are being flushed, this is defined as
+   * the set of sources in the removed context (context.sources), that are
+   * orphaned by this context being removed (no other context includes this
+   * file.)
    */
-  UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) {
-    _cancelDependencySubscriptions(info);
-    if (info.packageRoot != null) {
-      info.packageMapInfo = null;
-      JavaFile packagesDir = new JavaFile(info.packageRoot);
+  List<String> _computeFlushedFiles(ContextInfo info) {
+    AnalysisContext context = info.context;
+    HashSet<String> flushedFiles = new HashSet<String>();
+    for (Source source in context.sources) {
+      flushedFiles.add(source.fullName);
+    }
+    for (ContextInfo contextInfo in _rootInfo.descendants) {
+      AnalysisContext contextN = contextInfo.context;
+      if (context != contextN) {
+        for (Source source in contextN.sources) {
+          flushedFiles.remove(source.fullName);
+        }
+      }
+    }
+    return flushedFiles.toList(growable: false);
+  }
+
+  /**
+   * Compute the appropriate [FolderDisposition] for [folder].  Use
+   * [addDependency] to indicate which files needed to be consulted in order to
+   * figure out the [FolderDisposition]; these dependencies will be watched in
+   * order to determine when it is necessary to call this function again.
+   *
+   * TODO(paulberry): use [addDependency] for tracking all folder disposition
+   * dependencies (currently we only use it to track "pub list" dependencies).
+   */
+  FolderDisposition _computeFolderDisposition(
+      Folder folder, void addDependency(String path)) {
+    String packageRoot = normalizedPackageRoots[folder.path];
+    if (packageRoot != null) {
+      // TODO(paulberry): We shouldn't be using JavaFile here because it
+      // makes the code untestable (see dartbug.com/23909).
+      JavaFile packagesDir = new JavaFile(packageRoot);
       Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>();
       if (packagesDir.isDirectory()) {
         for (JavaFile file in packagesDir.listFiles()) {
@@ -491,89 +753,66 @@
             packageMap[file.getName()] = <Folder>[res];
           }
         }
-        return new PackageMapUriResolver(resourceProvider, packageMap);
+        return new PackageMapDisposition(packageMap, packageRoot: packageRoot);
       }
-      //TODO(danrubel) remove this if it will never be called
-      return new PackageUriResolver([packagesDir]);
+      // The package root does not exist (or is not a folder).  Since
+      // [setRoots] ignores any package roots that don't exist (or aren't
+      // folders), the only way we should be able to get here is due to a race
+      // condition.  In any case, the package root folder is gone, so we can't
+      // resolve packages.
+      return new NoPackageFolderDisposition(packageRoot: packageRoot);
     } else {
-      beginComputePackageMap();
+      callbacks.beginComputePackageMap();
       if (packageResolverProvider != null) {
         UriResolver resolver = packageResolverProvider(folder);
         if (resolver != null) {
-          return resolver;
+          return new CustomPackageResolverDisposition(resolver);
         }
       }
-      OptimizingPubPackageMapInfo packageMapInfo;
+      PackageMapInfo packageMapInfo;
       ServerPerformanceStatistics.pub.makeCurrentWhile(() {
-        packageMapInfo =
-            _packageMapProvider.computePackageMap(folder, info.packageMapInfo);
+        packageMapInfo = _packageMapProvider.computePackageMap(folder);
       });
-      endComputePackageMap();
+      callbacks.endComputePackageMap();
       for (String dependencyPath in packageMapInfo.dependencies) {
-        Resource resource = resourceProvider.getResource(dependencyPath);
-        if (resource is File) {
-          StreamSubscription<WatchEvent> subscription;
-          subscription = resource.changes.listen((WatchEvent event) {
-            if (info.packageMapInfo != null &&
-                info.packageMapInfo.isChangedDependency(
-                    dependencyPath, resourceProvider)) {
-              _recomputePackageUriResolver(info);
-            }
-          }, onError: (error, StackTrace stackTrace) {
-            // Gracefully degrade if file is or becomes unwatchable
-            _instrumentationService.logException(error, stackTrace);
-            subscription.cancel();
-            info.dependencySubscriptions.remove(subscription);
-          });
-          info.dependencySubscriptions.add(subscription);
-        }
+        addDependency(dependencyPath);
       }
-      info.packageMapInfo = packageMapInfo;
       if (packageMapInfo.packageMap == null) {
-        return null;
+        return new NoPackageFolderDisposition();
       }
-      return new PackageMapUriResolver(
-          resourceProvider, packageMapInfo.packageMap);
-      // TODO(paulberry): if any of the dependencies is outside of [folder],
-      // we'll need to watch their parent folders as well.
+      return new PackageMapDisposition(packageMapInfo.packageMap);
     }
   }
 
   /**
-   * Create a new empty context associated with [folder].
+   * Create a new empty context associated with [folder], having parent
+   * [parent] and using [packagespecFile] to resolve package URI's.
    */
-  _ContextInfo _createContext(
-      Folder folder, File packagespecFile, List<_ContextInfo> children) {
-    _ContextInfo info = new _ContextInfo(
-        folder, packagespecFile, children, normalizedPackageRoots[folder.path]);
-    _contexts[folder] = info;
-    var options = analysisOptionsProvider.getOptions(folder);
-    processOptionsForContext(folder, options);
-    info.changeSubscription = folder.changes.listen((WatchEvent event) {
-      _handleWatchEvent(folder, info, event);
-    });
-    try {
-      Packages packages;
-      UriResolver packageUriResolver;
+  ContextInfo _createContext(
+      ContextInfo parent, Folder folder, File packagespecFile) {
+    ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
+        normalizedPackageRoots[folder.path]);
+    Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder);
+    processOptionsForContext(info, options);
+    FolderDisposition disposition;
+    List<String> dependencies = <String>[];
 
-      if (ENABLE_PACKAGESPEC_SUPPORT) {
-        // Try .packages first.
-        if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) {
-          packages = _readPackagespec(packagespecFile);
-        }
+    if (ENABLE_PACKAGESPEC_SUPPORT) {
+      // Try .packages first.
+      if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) {
+        Packages packages = _readPackagespec(packagespecFile);
+        disposition = new PackagesFileDisposition(packages);
       }
-
-      // Next resort to a package uri resolver.
-      if (packages == null) {
-        packageUriResolver = _computePackageUriResolver(folder, info);
-      }
-
-      info.context = addContext(folder, packageUriResolver, packages);
-      info.context.name = folder.path;
-    } catch (_) {
-      info.changeSubscription.cancel();
-      rethrow;
     }
+
+    // Next resort to a package uri resolver.
+    if (disposition == null) {
+      disposition = _computeFolderDisposition(folder, dependencies.add);
+    }
+
+    info.setDependencies(dependencies);
+    info.context = callbacks.addContext(folder, disposition);
+    info.context.name = folder.path;
     return info;
   }
 
@@ -587,22 +826,12 @@
    * If [withPackageSpecOnly] is `true`, a context will be created only if there
    * is a 'pubspec.yaml' or '.packages' file in the [folder].
    *
-   * Returns created contexts.
+   * [parent] should be the parent of any contexts that are created.
    */
-  List<_ContextInfo> _createContexts(Folder folder, bool withPackageSpecOnly) {
-    // Try to find subfolders with pubspecs or .packages files.
-    List<_ContextInfo> children = <_ContextInfo>[];
-    try {
-      for (Resource child in folder.getChildren()) {
-        if (child is Folder) {
-          children.addAll(_createContexts(child, true));
-        }
-      }
-    } on FileSystemException {
-      // The directory either doesn't exist or cannot be read. Either way, there
-      // are no subfolders that need to be added.
-    }
-
+  void _createContexts(
+      ContextInfo parent, Folder folder, bool withPackageSpecOnly) {
+    // Decide whether a context needs to be created for [folder] here, and if
+    // so, create it.
     File packageSpec;
 
     if (ENABLE_PACKAGESPEC_SUPPORT) {
@@ -615,53 +844,59 @@
       packageSpec = folder.getChild(PUBSPEC_NAME);
     }
 
-    if (packageSpec.exists) {
-      return <_ContextInfo>[
-        _createContextWithSources(folder, packageSpec, children)
-      ];
+    bool createContext = packageSpec.exists || !withPackageSpecOnly;
+    if (withPackageSpecOnly &&
+        packageSpec.exists &&
+        (parent != null) &&
+        parent.ignored(packageSpec.path)) {
+      // Don't create a context if the package spec is required and ignored.
+      createContext = false;
     }
-    // No packagespec? Done.
-    if (withPackageSpecOnly) {
-      return children;
+    if (createContext) {
+      parent = _createContext(parent, folder, packageSpec);
     }
-    // OK, create a context without a packagespec.
-    return <_ContextInfo>[
-      _createContextWithSources(folder, packageSpec, children)
-    ];
-  }
 
-  /**
-   * Create a new context associated with the given [folder]. The [pubspecFile]
-   * is the `pubspec.yaml` file contained in the folder. Add any sources that
-   * are not included in one of the [children] to the context.
-   */
-  _ContextInfo _createContextWithSources(
-      Folder folder, File pubspecFile, List<_ContextInfo> children) {
-    _ContextInfo info = _createContext(folder, pubspecFile, children);
-    ChangeSet changeSet = new ChangeSet();
-    _addSourceFiles(changeSet, folder, info);
-    applyChangesToContext(folder, changeSet);
-    return info;
+    // Try to find subfolders with pubspecs or .packages files.
+    try {
+      for (Resource child in folder.getChildren()) {
+        if (child is Folder) {
+          if (!parent.ignored(child.path)) {
+            _createContexts(parent, child, true);
+          }
+        }
+      }
+    } on FileSystemException {
+      // The directory either doesn't exist or cannot be read. Either way, there
+      // are no subfolders that need to be added.
+    }
+
+    if (createContext) {
+      // Now that the child contexts have been created, add the sources that
+      // don't belong to the children.
+      ChangeSet changeSet = new ChangeSet();
+      _addSourceFiles(changeSet, folder, parent);
+      callbacks.applyChangesToContext(folder, changeSet);
+    }
   }
 
   /**
    * Clean up and destroy the context associated with the given folder.
    */
-  void _destroyContext(Folder folder) {
-    _ContextInfo info = _contexts[folder];
-    info.changeSubscription.cancel();
-    _cancelDependencySubscriptions(info);
-    removeContext(folder);
-    _contexts.remove(folder);
+  void _destroyContext(ContextInfo info) {
+    if (_changeSubscriptions.containsKey(info.folder)) {
+      _changeSubscriptions[info.folder].cancel();
+    }
+    callbacks.removeContext(info.folder, _computeFlushedFiles(info));
+    bool wasRemoved = info.parent.children.remove(info);
+    assert(wasRemoved);
   }
 
   /**
    * Extract a new [packagespecFile]-based context from [oldInfo].
    */
-  void _extractContext(_ContextInfo oldInfo, File packagespecFile) {
+  void _extractContext(ContextInfo oldInfo, File packagespecFile) {
     Folder newFolder = packagespecFile.parent;
-    _ContextInfo newInfo = _createContext(newFolder, packagespecFile, []);
-    newInfo.parent = oldInfo;
+    ContextInfo newInfo = _createContext(oldInfo, newFolder, packagespecFile);
     // prepare sources to extract
     Map<String, Source> extractedSources = new HashMap<String, Source>();
     oldInfo.sources.forEach((path, source) {
@@ -676,7 +911,7 @@
         newInfo.sources[path] = source;
         changeSet.addedSource(source);
       });
-      applyChangesToContext(newFolder, changeSet);
+      callbacks.applyChangesToContext(newFolder, changeSet);
     }
     // update old context
     {
@@ -685,18 +920,58 @@
         oldInfo.sources.remove(path);
         changeSet.removedSource(source);
       });
-      applyChangesToContext(oldInfo.folder, changeSet);
+      callbacks.applyChangesToContext(oldInfo.folder, changeSet);
+    }
+    // TODO(paulberry): every context that was previously a child of oldInfo is
+    // is still a child of oldInfo.  This is wrong--some of them ought to be
+    // adopted by newInfo now.
+  }
+
+  /**
+   * Return the [ContextInfo] for the "innermost" context whose associated
+   * folder is or contains the given path.  ("innermost" refers to the nesting
+   * of contexts, so if there is a context for path /foo and a context for
+   * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is
+   * the context for /foo/bar.)
+   *
+   * If no context contains the given path, `null` is returned.
+   */
+  ContextInfo _getInnermostContextInfoFor(String path) {
+    ContextInfo info = _rootInfo.findChildInfoFor(path);
+    if (info == null) {
+      return null;
+    }
+    while (true) {
+      ContextInfo childInfo = info.findChildInfoFor(path);
+      if (childInfo == null) {
+        return info;
+      }
+      info = childInfo;
     }
   }
 
-  void _handleWatchEvent(Folder folder, _ContextInfo info, WatchEvent event) {
+  void _handleWatchEvent(WatchEvent event) {
+    // Figure out which context this event applies to.
     // TODO(brianwilkerson) If a file is explicitly included in one context
     // but implicitly referenced in another context, we will only send a
     // changeSet to the context that explicitly includes the file (because
     // that's the only context that's watching the file).
+    ContextInfo info = _getInnermostContextInfoFor(event.path);
+    if (info == null) {
+      // This event doesn't apply to any context.  This could happen due to a
+      // race condition (e.g. a context was removed while one of its events was
+      // in the event loop).  The event is inapplicable now, so just ignore it.
+      return;
+    }
     _instrumentationService.logWatchEvent(
-        folder.path, event.path, event.type.toString());
+        info.folder.path, event.path, event.type.toString());
     String path = event.path;
+    // First handle changes that affect folderDisposition (since these need to
+    // be processed regardless of whether they are part of an excluded/ignored
+    // path).
+    if (info.hasDependency(path)) {
+      _recomputeFolderDisposition(info);
+    }
     // maybe excluded globally
     if (_isExcluded(path)) {
       return;
@@ -711,7 +986,7 @@
     // handle the change
     switch (event.type) {
       case ChangeType.ADD:
-        if (_isInPackagesDir(path, folder)) {
+        if (_isInPackagesDir(path, info.folder)) {
           return;
         }
 
@@ -721,7 +996,7 @@
           String directoryPath = pathContext.dirname(path);
 
           // Check to see if we need to create a new context.
-          if (info.isRoot) {
+          if (info.isTopLevel) {
 
             // Only create a new context if this is not the same directory
             // described by our info object.
@@ -747,7 +1022,7 @@
         } else {
           // pubspec was added in a sub-folder, extract a new context
           if (_isPubspec(path) &&
-              info.isRoot &&
+              info.isTopLevel &&
               !info.isPathToPackageDescription(path)) {
             _extractContext(info, resource);
             return;
@@ -759,11 +1034,11 @@
         // that case don't add it.
         if (resource is File) {
           File file = resource;
-          if (shouldFileBeAnalyzed(file)) {
+          if (callbacks.shouldFileBeAnalyzed(file)) {
             ChangeSet changeSet = new ChangeSet();
             Source source = createSourceInContext(info.context, file);
             changeSet.addedSource(source);
-            applyChangesToContext(folder, changeSet);
+            callbacks.applyChangesToContext(info.folder, changeSet);
             info.sources[path] = source;
           }
         }
@@ -773,7 +1048,7 @@
         // If package spec info is removed, check to see if we can merge contexts.
         // Note that it's important to verify that there is NEITHER a .packages nor a
         // lingering pubspec.yaml before merging.
-        if (!info.isRoot) {
+        if (!info.isTopLevel) {
           if (ENABLE_PACKAGESPEC_SUPPORT) {
             String directoryPath = pathContext.dirname(path);
 
@@ -810,7 +1085,7 @@
           sources.forEach((Source source) {
             changeSet.removedSource(source);
           });
-          applyChangesToContext(folder, changeSet);
+          callbacks.applyChangesToContext(info.folder, changeSet);
           info.sources.remove(path);
         }
         break;
@@ -821,18 +1096,13 @@
           sources.forEach((Source source) {
             changeSet.changedSource(source);
           });
-          applyChangesToContext(folder, changeSet);
+          callbacks.applyChangesToContext(info.folder, changeSet);
         }
         break;
     }
 
     //TODO(pquitslund): find the right place for this
-    _checkForPackagespecUpdate(path, info, folder);
-
-    if (info.packageMapInfo != null &&
-        info.packageMapInfo.isChangedDependency(path, resourceProvider)) {
-      _recomputePackageUriResolver(info);
-    }
+    _checkForPackagespecUpdate(path, info, info.folder);
   }
 
   /**
@@ -870,11 +1140,11 @@
   /**
    * Merges [info] context into its parent.
    */
-  void _mergeContext(_ContextInfo info) {
+  void _mergeContext(ContextInfo info) {
     // destroy the context
-    _destroyContext(info.folder);
+    _destroyContext(info);
     // add files to the parent context
-    _ContextInfo parentInfo = info.parent;
+    ContextInfo parentInfo = info.parent;
     if (parentInfo != null) {
       parentInfo.children.remove(info);
       ChangeSet changeSet = new ChangeSet();
@@ -882,7 +1152,7 @@
         parentInfo.sources[path] = source;
         changeSet.addedSource(source);
       });
-      applyChangesToContext(parentInfo.folder, changeSet);
+      callbacks.applyChangesToContext(parentInfo.folder, changeSet);
     }
   }
 
@@ -899,17 +1169,19 @@
   }
 
   /**
-   * Recompute the package URI resolver for the context described by [info],
+   * Recompute the [FolderDisposition] for the context described by [info],
    * and update the client appropriately.
    */
-  void _recomputePackageUriResolver(_ContextInfo info) {
+  void _recomputeFolderDisposition(ContextInfo info) {
     // TODO(paulberry): when computePackageMap is changed into an
     // asynchronous API call, we'll want to suspend analysis for this context
     // while we're rerunning "pub list", since any analysis we complete while
     // "pub list" is in progress is just going to get thrown away anyhow.
-    UriResolver packageUriResolver =
-        _computePackageUriResolver(info.folder, info);
-    updateContextPackageUriResolver(info.folder, packageUriResolver, null);
+    List<String> dependencies = <String>[];
+    FolderDisposition disposition =
+        _computeFolderDisposition(info.folder, dependencies.add);
+    info.setDependencies(dependencies);
+    callbacks.updateContextPackageUriResolver(info.folder, disposition);
   }
 
   /**
@@ -929,73 +1201,6 @@
 }
 
 /**
- * Class that maintains a mapping from included/excluded paths to a set of
- * folders that should correspond to analysis contexts.
- */
-abstract class ContextManager {
-  // TODO(brianwilkerson) Support:
-  //   setting the default analysis options
-  //   setting the default content cache
-  //   setting the default SDK
-  //   maintaining AnalysisContext.folderMap (or remove it)
-  //   telling server when a context has been added or removed (see onContextsChanged)
-  //   telling server when a context needs to be re-analyzed
-  //   notifying the client when results should be flushed
-  //   using analyzeFileFunctions to determine which files to analyze
-  //
-  // TODO(brianwilkerson) Move this class to a public library.
-
-//  /**
-//   * The default options used to create new analysis contexts.
-//   */
-//  AnalysisOptionsImpl get defaultOptions;
-
-  /**
-   * Return the list of excluded paths (folders and files) most recently passed
-   * to [setRoots].
-   */
-  List<String> get excludedPaths;
-
-  /**
-   * Return the list of included paths (folders and files) most recently passed
-   * to [setRoots].
-   */
-  List<String> get includedPaths;
-
-//  /**
-//   * A stream that is notified when contexts are added or removed.
-//   */
-//  Stream<ContextsChangedEvent> get onContextsChanged;
-
-  /**
-   * Return a list containing all of the contexts contained in the given
-   * [analysisRoot].
-   */
-  List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot);
-
-  /**
-   * Return `true` if the given absolute [path] is in one of the current
-   * root folders and is not excluded.
-   */
-  bool isInAnalysisRoot(String path);
-
-  /**
-   * Rebuild the set of contexts from scratch based on the data last sent to
-   * [setRoots]. Only contexts contained in the given list of analysis [roots]
-   * will be rebuilt, unless the list is `null`, in which case every context
-   * will be rebuilt.
-   */
-  void refresh(List<Resource> roots);
-
-  /**
-   * Change the set of paths which should be used as starting points to
-   * determine the context directories.
-   */
-  void setRoots(List<String> includedPaths, List<String> excludedPaths,
-      Map<String, String> packageRoots);
-}
-
-/**
  * An indication that one or more contexts were added, changed, or removed.
  *
  * The lists of [added], [changed] and [removed] contexts will not contain
@@ -1028,104 +1233,121 @@
 }
 
 /**
- * Information tracked by the [ContextManager] for each context.
+ * Concrete [FolderDisposition] object indicating that the context for a given
+ * folder should resolve package URIs using a custom URI resolver.
  */
-class _ContextInfo {
+class CustomPackageResolverDisposition extends FolderDisposition {
   /**
-   * The [Folder] for which this information object is created.
+   * The [UriResolver] that should be used to resolve package URIs.
    */
-  final Folder folder;
+  UriResolver resolver;
 
-  /// The [PathFilter] used to filter sources from being analyzed.
-  final PathFilter pathFilter;
+  CustomPackageResolverDisposition(this.resolver);
+
+  @override
+  String get packageRoot => null;
+
+  @override
+  Packages get packages => null;
+
+  @override
+  Iterable<UriResolver> createPackageUriResolvers(
+      ResourceProvider resourceProvider) => <UriResolver>[resolver];
+}
+
+/**
+ * An instance of the class [FolderDisposition] represents the information
+ * gathered by the [ContextManagerImpl] to determine how to create an
+ * [AnalysisContext] for a given folder.
+ *
+ * Note: [ContextManagerImpl] may use equality testing and hash codes to
+ * determine when two folders should share the same context, so derived classes
+ * may need to override operator== and hashCode() if object identity is
+ * insufficient.
+ *
+ * TODO(paulberry): consider adding a flag to indicate that it is not necessary
+ * to recurse into the given folder looking for additional contexts to create
+ * or files to analyze (this could help avoid unnecessarily weighing down the
+ * system with file watchers).
+ */
+abstract class FolderDisposition {
+  /**
+   * If this [FolderDisposition] was created based on a package root
+   * folder, the absolute path to that folder.  Otherwise `null`.
+   */
+  String get packageRoot;
 
   /**
-   * The enclosed pubspec-based contexts.
+   * If contexts governed by this [FolderDisposition] should resolve packages
+   * using the ".packages" file mechanism (DEP 5), retrieve the [Packages]
+   * object that resulted from parsing the ".packages" file.
    */
-  final List<_ContextInfo> children;
+  Packages get packages;
 
   /**
-   * The package root for this context, or null if there is no package root.
+   * Create all the [UriResolver]s which should be used to resolve packages in
+   * contexts governed by this [FolderDisposition].
+   *
+   * [resourceProvider] is provided since it is needed to construct most
+   * [UriResolver]s.
    */
-  String packageRoot;
+  Iterable<UriResolver> createPackageUriResolvers(
+      ResourceProvider resourceProvider);
+}
 
-  /**
-   * The [_ContextInfo] that encloses this one.
-   */
-  _ContextInfo parent;
+/**
+ * Concrete [FolderDisposition] object indicating that the context for a given
+ * folder should not resolve "package:" URIs at all.
+ */
+class NoPackageFolderDisposition extends FolderDisposition {
+  @override
+  final String packageRoot;
 
-  /**
-   * The package description file path for this context.
-   */
-  String packageDescriptionPath;
+  NoPackageFolderDisposition({this.packageRoot});
 
-  /**
-   * Stream subscription we are using to watch the context's directory for
-   * changes.
-   */
-  StreamSubscription<WatchEvent> changeSubscription;
+  @override
+  Packages get packages => null;
 
-  /**
-   * Stream subscriptions we are using to watch the files
-   * used to determine the package map.
-   */
-  final List<StreamSubscription<WatchEvent>> dependencySubscriptions =
-      <StreamSubscription<WatchEvent>>[];
+  @override
+  Iterable<UriResolver> createPackageUriResolvers(
+      ResourceProvider resourceProvider) => const <UriResolver>[];
+}
 
-  /**
-   * The analysis context that was created for the [folder].
-   */
-  AnalysisContext context;
+/**
+ * Concrete [FolderDisposition] object indicating that the context for a given
+ * folder should resolve packages using a package map.
+ */
+class PackageMapDisposition extends FolderDisposition {
+  final Map<String, List<Folder>> packageMap;
 
-  /**
-   * Map from full path to the [Source] object, for each source that has been
-   * added to the context.
-   */
-  Map<String, Source> sources = new HashMap<String, Source>();
+  @override
+  final String packageRoot;
 
-  /**
-   * Info returned by the last call to
-   * [OptimizingPubPackageMapProvider.computePackageMap], or `null` if the
-   * package map hasn't been computed for this context yet.
-   */
-  OptimizingPubPackageMapInfo packageMapInfo;
+  PackageMapDisposition(this.packageMap, {this.packageRoot});
 
-  _ContextInfo(
-      Folder folder, File packagespecFile, this.children, this.packageRoot)
-      : folder = folder,
-        pathFilter = new PathFilter(folder.path, null) {
-    packageDescriptionPath = packagespecFile.path;
-    for (_ContextInfo child in children) {
-      child.parent = this;
-    }
-  }
+  @override
+  Packages get packages => null;
 
-  /**
-   * Returns `true` if this context is root folder based.
-   */
-  bool get isRoot => parent == null;
+  @override
+  Iterable<UriResolver> createPackageUriResolvers(
+          ResourceProvider resourceProvider) =>
+      <UriResolver>[new PackageMapUriResolver(resourceProvider, packageMap)];
+}
 
-  /**
-   * Returns `true` if [path] is excluded, as it is in one of the children.
-   */
-  bool excludes(String path) {
-    return children.any((child) {
-      return child.folder.contains(path);
-    });
-  }
+/**
+ * Concrete [FolderDisposition] object indicating that the context for a given
+ * folder should resolve packages using a ".packages" file.
+ */
+class PackagesFileDisposition extends FolderDisposition {
+  @override
+  final Packages packages;
 
-  /**
-   * Returns `true` if [resource] is excluded, as it is in one of the children.
-   */
-  bool excludesResource(Resource resource) => excludes(resource.path);
+  PackagesFileDisposition(this.packages) {}
 
-  /// Returns `true` if  [path] should be ignored.
-  bool ignored(String path) => pathFilter.ignored(path);
+  @override
+  String get packageRoot => null;
 
-  /**
-   * Returns `true` if [path] is the package description file for this context 
-   * (pubspec.yaml or .packages).
-   */
-  bool isPathToPackageDescription(String path) =>
-      path == packageDescriptionPath;
+  @override
+  Iterable<UriResolver> createPackageUriResolvers(
+      ResourceProvider resourceProvider) => const <UriResolver>[];
 }
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 42afae3..483f532 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -112,13 +112,12 @@
   Response getNavigation(Request request) {
     var params = new AnalysisGetNavigationParams.fromRequest(request);
     String file = params.file;
-    int offset = params.offset;
-    Future<AnalysisDoneReason> completionFuture =
+    Future<AnalysisDoneReason> analysisFuture =
         server.onFileAnalysisComplete(file);
-    if (completionFuture == null) {
+    if (analysisFuture == null) {
       return new Response.getNavigationInvalidFile(request);
     }
-    completionFuture.then((AnalysisDoneReason reason) {
+    analysisFuture.then((AnalysisDoneReason reason) {
       switch (reason) {
         case AnalysisDoneReason.COMPLETE:
           List<CompilationUnit> units =
@@ -128,11 +127,10 @@
           } else {
             DartUnitNavigationComputer computer =
                 new DartUnitNavigationComputer();
+            _GetNavigationAstVisitor visitor = new _GetNavigationAstVisitor(
+                params.offset, params.offset + params.length, computer);
             for (CompilationUnit unit in units) {
-              AstNode node = new NodeLocator(offset).searchWithin(unit);
-              if (node != null) {
-                computer.compute(node);
-              }
+              unit.accept(visitor);
             }
             server.sendResponse(new AnalysisGetNavigationResult(
                     computer.files, computer.targets, computer.regions)
@@ -268,11 +266,6 @@
     var params = new AnalysisUpdateOptionsParams.fromRequest(request);
     AnalysisOptions newOptions = params.options;
     List<OptionUpdater> updaters = new List<OptionUpdater>();
-    if (newOptions.enableNullAwareOperators != null) {
-      updaters.add((engine.AnalysisOptionsImpl options) {
-        options.enableNullAwareOperators = newOptions.enableNullAwareOperators;
-      });
-    }
     if (newOptions.generateDart2jsHints != null) {
       updaters.add((engine.AnalysisOptionsImpl options) {
         options.dart2jsHint = newOptions.generateDart2jsHints;
@@ -292,3 +285,36 @@
     return new AnalysisUpdateOptionsResult().toResponse(request.id);
   }
 }
+
+/**
+ * An AST visitor that computer navigation regions in the givne region.
+ */
+class _GetNavigationAstVisitor extends UnifyingAstVisitor {
+  final int rangeStart;
+  final int rangeEnd;
+  final DartUnitNavigationComputer computer;
+
+  _GetNavigationAstVisitor(this.rangeStart, this.rangeEnd, this.computer);
+
+  bool isInRange(int offset) {
+    return rangeStart <= offset && offset <= rangeEnd;
+  }
+
+  @override
+  visitNode(AstNode node) {
+    // The node ends before the range starts.
+    if (node.end < rangeStart) {
+      return;
+    }
+    // The node starts after the range ends.
+    if (node.offset > rangeEnd) {
+      return;
+    }
+    // The node starts or ends in the range.
+    if (isInRange(node.offset) || isInRange(node.end)) {
+      computer.compute(node);
+      return;
+    }
+    super.visitNode(node);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index ee26dd8..3213537 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/organize_directives.dart';
 import 'package:analysis_server/src/services/correction/sort_members.dart';
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
@@ -156,8 +157,8 @@
         for (engine.AnalysisError error in errorInfo.errors) {
           int errorLine = lineInfo.getLocation(error.offset).lineNumber;
           if (errorLine == requestLine) {
-            List<Fix> fixes =
-                computeFixes(server.serverPlugin, unit.element.context, error);
+            List<Fix> fixes = computeFixes(server.serverPlugin,
+                server.resourceProvider, unit.element.context, error);
             if (fixes.isNotEmpty) {
               AnalysisError serverError =
                   newAnalysisError_fromEngine(lineInfo, error);
@@ -190,6 +191,8 @@
         return getFixes(request);
       } else if (requestName == EDIT_GET_REFACTORING) {
         return _getRefactoring(request);
+      } else if (requestName == EDIT_ORGANIZE_DIRECTIVES) {
+        return organizeDirectives(request);
       } else if (requestName == EDIT_SORT_MEMBERS) {
         return sortMembers(request);
       }
@@ -199,6 +202,38 @@
     return null;
   }
 
+  Response organizeDirectives(Request request) {
+    var params = new EditOrganizeDirectivesParams.fromRequest(request);
+    // prepare file
+    String file = params.file;
+    if (!engine.AnalysisEngine.isDartFileName(file)) {
+      return new Response.fileNotAnalyzed(request, file);
+    }
+    // prepare resolved units
+    List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
+    if (units.isEmpty) {
+      return new Response.fileNotAnalyzed(request, file);
+    }
+    // prepare context
+    CompilationUnit unit = units.first;
+    engine.AnalysisContext context = unit.element.context;
+    Source source = unit.element.source;
+    List<engine.AnalysisError> errors = context.computeErrors(source);
+    // check if there are scan/parse errors in the file
+    int numScanParseErrors = _getNumberOfScanParseErrors(errors);
+    if (numScanParseErrors != 0) {
+      return new Response.organizeDirectivesError(
+          request, 'File has $numScanParseErrors scan/parse errors.');
+    }
+    // do organize
+    int fileStamp = context.getModificationStamp(source);
+    String code = context.getContents(source).data;
+    DirectiveOrganizer sorter = new DirectiveOrganizer(code, unit, errors);
+    List<SourceEdit> edits = sorter.organize();
+    SourceFileEdit fileEdit = new SourceFileEdit(file, fileStamp, edits: edits);
+    return new EditOrganizeDirectivesResult(fileEdit).toResponse(request.id);
+  }
+
   Response sortMembers(Request request) {
     var params = new EditSortMembersParams.fromRequest(request);
     // prepare file
@@ -215,15 +250,9 @@
     CompilationUnit unit = units.first;
     engine.AnalysisContext context = unit.element.context;
     Source source = unit.element.source;
-    // check if there are no scan/parse errors in the file
+    // check if there are scan/parse errors in the file
     engine.AnalysisErrorInfo errors = context.getErrors(source);
-    int numScanParseErrors = 0;
-    errors.errors.forEach((engine.AnalysisError error) {
-      if (error.errorCode is engine.ScannerErrorCode ||
-          error.errorCode is engine.ParserErrorCode) {
-        numScanParseErrors++;
-      }
-    });
+    int numScanParseErrors = _getNumberOfScanParseErrors(errors.errors);
     if (numScanParseErrors != 0) {
       return new Response.sortMembersParseErrors(request, numScanParseErrors);
     }
@@ -304,6 +333,17 @@
   void _newRefactoringManager() {
     refactoringManager = new _RefactoringManager(server, searchEngine);
   }
+
+  static int _getNumberOfScanParseErrors(List<engine.AnalysisError> errors) {
+    int numScanParseErrors = 0;
+    for (engine.AnalysisError error in errors) {
+      if (error.errorCode is engine.ScannerErrorCode ||
+          error.errorCode is engine.ParserErrorCode) {
+        numScanParseErrors++;
+      }
+    }
+    return numScanParseErrors;
+  }
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart
index 5ecfe20..f92288f 100644
--- a/pkg/analysis_server/lib/src/generated_protocol.dart
+++ b/pkg/analysis_server/lib/src/generated_protocol.dart
@@ -6166,6 +6166,164 @@
 }
 
 /**
+ * edit.organizeDirectives params
+ *
+ * {
+ *   "file": FilePath
+ * }
+ */
+class EditOrganizeDirectivesParams implements HasToJson {
+  String _file;
+
+  /**
+   * The Dart file to organize directives in.
+   */
+  String get file => _file;
+
+  /**
+   * The Dart file to organize directives in.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  EditOrganizeDirectivesParams(String file) {
+    this.file = file;
+  }
+
+  factory EditOrganizeDirectivesParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder._decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.missingKey(jsonPath, "file");
+      }
+      return new EditOrganizeDirectivesParams(file);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "edit.organizeDirectives params", json);
+    }
+  }
+
+  factory EditOrganizeDirectivesParams.fromRequest(Request request) {
+    return new EditOrganizeDirectivesParams.fromJson(
+        new RequestDecoder(request), "params", request._params);
+  }
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    return result;
+  }
+
+  Request toRequest(String id) {
+    return new Request(id, "edit.organizeDirectives", toJson());
+  }
+
+  @override
+  String toString() => JSON.encode(toJson());
+
+  @override
+  bool operator==(other) {
+    if (other is EditOrganizeDirectivesParams) {
+      return file == other.file;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = _JenkinsSmiHash.combine(hash, file.hashCode);
+    return _JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * edit.organizeDirectives result
+ *
+ * {
+ *   "edit": SourceFileEdit
+ * }
+ */
+class EditOrganizeDirectivesResult implements HasToJson {
+  SourceFileEdit _edit;
+
+  /**
+   * The file edit that is to be applied to the given file to effect the
+   * organizing.
+   */
+  SourceFileEdit get edit => _edit;
+
+  /**
+   * The file edit that is to be applied to the given file to effect the
+   * organizing.
+   */
+  void set edit(SourceFileEdit value) {
+    assert(value != null);
+    this._edit = value;
+  }
+
+  EditOrganizeDirectivesResult(SourceFileEdit edit) {
+    this.edit = edit;
+  }
+
+  factory EditOrganizeDirectivesResult.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      SourceFileEdit edit;
+      if (json.containsKey("edit")) {
+        edit = new SourceFileEdit.fromJson(jsonDecoder, jsonPath + ".edit", json["edit"]);
+      } else {
+        throw jsonDecoder.missingKey(jsonPath, "edit");
+      }
+      return new EditOrganizeDirectivesResult(edit);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "edit.organizeDirectives result", json);
+    }
+  }
+
+  factory EditOrganizeDirectivesResult.fromResponse(Response response) {
+    return new EditOrganizeDirectivesResult.fromJson(
+        new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)), "result", response._result);
+  }
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["edit"] = edit.toJson();
+    return result;
+  }
+
+  Response toResponse(String id) {
+    return new Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => JSON.encode(toJson());
+
+  @override
+  bool operator==(other) {
+    if (other is EditOrganizeDirectivesResult) {
+      return edit == other.edit;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = _JenkinsSmiHash.combine(hash, edit.hashCode);
+    return _JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * execution.createContext params
  *
  * {
@@ -7403,14 +7561,14 @@
   bool _generateLints;
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed async feature.
    */
   bool get enableAsync => _enableAsync;
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed async feature.
    */
@@ -7419,7 +7577,7 @@
   }
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed deferred
    * loading feature.
@@ -7427,7 +7585,7 @@
   bool get enableDeferredLoading => _enableDeferredLoading;
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed deferred
    * loading feature.
@@ -7437,14 +7595,14 @@
   }
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed enum feature.
    */
   bool get enableEnums => _enableEnums;
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed enum feature.
    */
@@ -7453,12 +7611,16 @@
   }
 
   /**
+   * Deprecated: this feature is always enabled.
+   *
    * True if the client wants to enable support for the proposed "null aware
    * operators" feature.
    */
   bool get enableNullAwareOperators => _enableNullAwareOperators;
 
   /**
+   * Deprecated: this feature is always enabled.
+   *
    * True if the client wants to enable support for the proposed "null aware
    * operators" feature.
    */
@@ -12665,6 +12827,7 @@
  *
  * enum {
  *   CONTENT_MODIFIED
+ *   FILE_NOT_ANALYZED
  *   FORMAT_INVALID_FILE
  *   FORMAT_WITH_ERRORS
  *   GET_ERRORS_INVALID_FILE
@@ -12675,6 +12838,7 @@
  *   INVALID_PARAMETER
  *   INVALID_REQUEST
  *   NO_INDEX_GENERATED
+ *   ORGANIZE_DIRECTIVES_ERROR
  *   REFACTORING_REQUEST_CANCELLED
  *   SERVER_ALREADY_STARTED
  *   SERVER_ERROR
@@ -12695,6 +12859,12 @@
   static const CONTENT_MODIFIED = const RequestErrorCode._("CONTENT_MODIFIED");
 
   /**
+   * A request specified a FilePath which does not match a file in an analysis
+   * root, or the requested operation is not available for the file.
+   */
+  static const FILE_NOT_ANALYZED = const RequestErrorCode._("FILE_NOT_ANALYZED");
+
+  /**
    * An "edit.format" request specified a FilePath which does not match a Dart
    * file in an analysis root.
    */
@@ -12712,8 +12882,8 @@
   static const GET_ERRORS_INVALID_FILE = const RequestErrorCode._("GET_ERRORS_INVALID_FILE");
 
   /**
-   * An "analysis.getErrors" request specified a FilePath which does not match
-   * a file currently subject to analysis.
+   * An "analysis.getNavigation" request specified a FilePath which does not
+   * match a file currently subject to analysis.
    */
   static const GET_NAVIGATION_INVALID_FILE = const RequestErrorCode._("GET_NAVIGATION_INVALID_FILE");
 
@@ -12752,6 +12922,12 @@
   static const NO_INDEX_GENERATED = const RequestErrorCode._("NO_INDEX_GENERATED");
 
   /**
+   * An "edit.organizeDirectives" request specified a Dart file that cannot be
+   * analyzed. The reason is described in the message.
+   */
+  static const ORGANIZE_DIRECTIVES_ERROR = const RequestErrorCode._("ORGANIZE_DIRECTIVES_ERROR");
+
+  /**
    * Another refactoring request was received during processing of this one.
    */
   static const REFACTORING_REQUEST_CANCELLED = const RequestErrorCode._("REFACTORING_REQUEST_CANCELLED");
@@ -12817,7 +12993,7 @@
   /**
    * A list containing all of the enum values that are defined.
    */
-  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, FORMAT_WITH_ERRORS, GET_ERRORS_INVALID_FILE, GET_NAVIGATION_INVALID_FILE, INVALID_ANALYSIS_ROOT, INVALID_EXECUTION_CONTEXT, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, NO_INDEX_GENERATED, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNKNOWN_SOURCE, UNSUPPORTED_FEATURE];
+  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FILE_NOT_ANALYZED, FORMAT_INVALID_FILE, FORMAT_WITH_ERRORS, GET_ERRORS_INVALID_FILE, GET_NAVIGATION_INVALID_FILE, INVALID_ANALYSIS_ROOT, INVALID_EXECUTION_CONTEXT, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, NO_INDEX_GENERATED, ORGANIZE_DIRECTIVES_ERROR, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNKNOWN_SOURCE, UNSUPPORTED_FEATURE];
 
   final String name;
 
@@ -12827,6 +13003,8 @@
     switch (name) {
       case "CONTENT_MODIFIED":
         return CONTENT_MODIFIED;
+      case "FILE_NOT_ANALYZED":
+        return FILE_NOT_ANALYZED;
       case "FORMAT_INVALID_FILE":
         return FORMAT_INVALID_FILE;
       case "FORMAT_WITH_ERRORS":
@@ -12847,6 +13025,8 @@
         return INVALID_REQUEST;
       case "NO_INDEX_GENERATED":
         return NO_INDEX_GENERATED;
+      case "ORGANIZE_DIRECTIVES_ERROR":
+        return ORGANIZE_DIRECTIVES_ERROR;
       case "REFACTORING_REQUEST_CANCELLED":
         return REFACTORING_REQUEST_CANCELLED;
       case "SERVER_ALREADY_STARTED":
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index 7068b9d..360b5da 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -1010,7 +1010,7 @@
     List<Folder> folders = folderMap.keys.toList();
     folders.sort((Folder first, Folder second) =>
         first.shortName.compareTo(second.shortName));
-    AnalysisOptionsImpl options = analysisServer.contextManager.defaultOptions;
+    AnalysisOptionsImpl options = analysisServer.defaultContextOptions;
     ServerOperationQueue operationQueue = analysisServer.operationQueue;
 
     buffer.write('<h3>Analysis Domain</h3>');
@@ -1052,8 +1052,6 @@
       _writeOption(
           buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
       _writeOption(buffer, 'Cache size', options.cacheSize);
-      _writeOption(buffer, 'Enable null-aware operators',
-          options.enableNullAwareOperators);
       _writeOption(
           buffer, 'Enable strict call checks', options.enableStrictCallChecks);
       _writeOption(buffer, 'Generate hints', options.hint);
diff --git a/pkg/analysis_server/lib/src/protocol.dart b/pkg/analysis_server/lib/src/protocol.dart
index aec8d71..ef960f0 100644
--- a/pkg/analysis_server/lib/src/protocol.dart
+++ b/pkg/analysis_server/lib/src/protocol.dart
@@ -392,7 +392,8 @@
       var disambiguatorPath = '$jsonPath[${JSON.encode(field)}]';
       String disambiguator = _decodeString(disambiguatorPath, json[field]);
       if (!decoders.containsKey(disambiguator)) {
-        throw mismatch(disambiguatorPath, 'One of: ${decoders.keys.toList()}', json);
+        throw mismatch(
+            disambiguatorPath, 'One of: ${decoders.keys.toList()}', json);
       }
       return decoders[disambiguator](jsonPath, json);
     } else {
@@ -625,8 +626,8 @@
       buffer.write(JSON.encode(actual));
       buffer.write('"');
     }
-    return new RequestFailure(new Response.invalidParameter(
-        _request, jsonPath, buffer.toString()));
+    return new RequestFailure(
+        new Response.invalidParameter(_request, jsonPath, buffer.toString()));
   }
 
   @override
@@ -721,20 +722,31 @@
       : _result = result;
 
   /**
+   * Initialize a newly created instance to represent the
+   * FILE_NOT_ANALYZED error condition.
+   */
+  Response.fileNotAnalyzed(Request request, String file)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.FILE_NOT_ANALYZED,
+                'File is not analyzed: $file.'));
+
+  /**
    * Initialize a newly created instance to represent the FORMAT_INVALID_FILE
    * error condition.
    */
-  Response.formatInvalidFile(Request request) : this(request.id,
-          error: new RequestError(RequestErrorCode.FORMAT_INVALID_FILE,
-              'Error during `edit.format`: invalid file.'));
+  Response.formatInvalidFile(Request request)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.FORMAT_INVALID_FILE,
+                'Error during `edit.format`: invalid file.'));
 
   /**
    * Initialize a newly created instance to represent the FORMAT_WITH_ERROR
    * error condition.
    */
-  Response.formatWithErrors(Request request) : this(request.id,
-          error: new RequestError(RequestErrorCode.FORMAT_WITH_ERRORS,
-              'Error during `edit.format`: source contains syntax errors.'));
+  Response.formatWithErrors(Request request)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.FORMAT_WITH_ERRORS,
+                'Error during `edit.format`: source contains syntax errors.'));
 
   /**
    * Initialize a newly created instance based upon the given JSON data
@@ -766,37 +778,40 @@
    * Initialize a newly created instance to represent the
    * GET_ERRORS_INVALID_FILE error condition.
    */
-  Response.getErrorsInvalidFile(Request request) : this(request.id,
-          error: new RequestError(RequestErrorCode.GET_ERRORS_INVALID_FILE,
-              'Error during `analysis.getErrors`: invalid file.'));
+  Response.getErrorsInvalidFile(Request request)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.GET_ERRORS_INVALID_FILE,
+                'Error during `analysis.getErrors`: invalid file.'));
 
   /**
    * Initialize a newly created instance to represent the
    * GET_NAVIGATION_INVALID_FILE error condition.
    */
-  Response.getNavigationInvalidFile(Request request) : this(request.id,
-          error: new RequestError(RequestErrorCode.GET_NAVIGATION_INVALID_FILE,
-              'Error during `analysis.getNavigation`: invalid file.'));
+  Response.getNavigationInvalidFile(Request request)
+      : this(request.id,
+            error: new RequestError(
+                RequestErrorCode.GET_NAVIGATION_INVALID_FILE,
+                'Error during `analysis.getNavigation`: invalid file.'));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by an analysis.reanalyze [request] that specifies an analysis root that is
    * not in the current list of analysis roots.
    */
-  Response.invalidAnalysisRoot(Request request, String rootPath) : this(
-          request.id,
-          error: new RequestError(RequestErrorCode.INVALID_ANALYSIS_ROOT,
-              "Invalid analysis root: $rootPath"));
+  Response.invalidAnalysisRoot(Request request, String rootPath)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.INVALID_ANALYSIS_ROOT,
+                "Invalid analysis root: $rootPath"));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by a [request] that specifies an execution context whose context root does
    * not exist.
    */
-  Response.invalidExecutionContext(Request request, String contextId) : this(
-          request.id,
-          error: new RequestError(RequestErrorCode.INVALID_EXECUTION_CONTEXT,
-              "Invalid execution context: $contextId"));
+  Response.invalidExecutionContext(Request request, String contextId)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.INVALID_EXECUTION_CONTEXT,
+                "Invalid execution context: $contextId"));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
@@ -807,33 +822,45 @@
    */
   Response.invalidParameter(Request request, String path, String expectation)
       : this(request.id,
-          error: new RequestError(RequestErrorCode.INVALID_PARAMETER,
-              "Invalid parameter '$path'. $expectation."));
+            error: new RequestError(RequestErrorCode.INVALID_PARAMETER,
+                "Invalid parameter '$path'. $expectation."));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by a malformed request.
    */
-  Response.invalidRequestFormat() : this('',
-          error: new RequestError(
-              RequestErrorCode.INVALID_REQUEST, 'Invalid request'));
+  Response.invalidRequestFormat()
+      : this('',
+            error: new RequestError(
+                RequestErrorCode.INVALID_REQUEST, 'Invalid request'));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by a request that requires an index, but indexing is disabled.
    */
-  Response.noIndexGenerated(Request request) : this(request.id,
-          error: new RequestError(
-              RequestErrorCode.NO_INDEX_GENERATED, 'Indexing is disabled'));
+  Response.noIndexGenerated(Request request)
+      : this(request.id,
+            error: new RequestError(
+                RequestErrorCode.NO_INDEX_GENERATED, 'Indexing is disabled'));
+
+  /**
+   * Initialize a newly created instance to represent the
+   * ORGANIZE_DIRECTIVES_ERROR error condition.
+   */
+  Response.organizeDirectivesError(Request request, String message)
+      : this(request.id,
+            error: new RequestError(
+                RequestErrorCode.ORGANIZE_DIRECTIVES_ERROR, message));
 
   /**
    * Initialize a newly created instance to represent the
    * REFACTORING_REQUEST_CANCELLED error condition.
    */
-  Response.refactoringRequestCancelled(Request request) : this(request.id,
-          error: new RequestError(
-              RequestErrorCode.REFACTORING_REQUEST_CANCELLED,
-              'The `edit.getRefactoring` request was cancelled.'));
+  Response.refactoringRequestCancelled(Request request)
+      : this(request.id,
+            error: new RequestError(
+                RequestErrorCode.REFACTORING_REQUEST_CANCELLED,
+                'The `edit.getRefactoring` request was cancelled.'));
 
   /**
    * Initialize a newly created instance to represent the SERVER_ERROR error
@@ -852,49 +879,52 @@
    * Initialize a newly created instance to represent the
    * SORT_MEMBERS_INVALID_FILE error condition.
    */
-  Response.sortMembersInvalidFile(Request request) : this(request.id,
-          error: new RequestError(RequestErrorCode.SORT_MEMBERS_INVALID_FILE,
-              'Error during `edit.sortMembers`: invalid file.'));
+  Response.sortMembersInvalidFile(Request request)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.SORT_MEMBERS_INVALID_FILE,
+                'Error during `edit.sortMembers`: invalid file.'));
 
   /**
    * Initialize a newly created instance to represent the
    * SORT_MEMBERS_PARSE_ERRORS error condition.
    */
-  Response.sortMembersParseErrors(Request request, int numErrors) : this(
-          request.id,
-          error: new RequestError(RequestErrorCode.SORT_MEMBERS_PARSE_ERRORS,
-              'Error during `edit.sortMembers`: file has $numErrors scan/parse errors.'));
+  Response.sortMembersParseErrors(Request request, int numErrors)
+      : this(request.id,
+            error: new RequestError(RequestErrorCode.SORT_MEMBERS_PARSE_ERRORS,
+                'Error during `edit.sortMembers`: file has $numErrors scan/parse errors.'));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by a `analysis.setPriorityFiles` [request] that includes one or more files
    * that are not being analyzed.
    */
-  Response.unanalyzedPriorityFiles(String requestId, String fileNames) : this(
-          requestId,
-          error: new RequestError(RequestErrorCode.UNANALYZED_PRIORITY_FILES,
-              "Unanalyzed files cannot be a priority: '$fileNames'"));
+  Response.unanalyzedPriorityFiles(String requestId, String fileNames)
+      : this(requestId,
+            error: new RequestError(RequestErrorCode.UNANALYZED_PRIORITY_FILES,
+                "Unanalyzed files cannot be a priority: '$fileNames'"));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by a [request] that cannot be handled by any known handlers.
    */
-  Response.unknownRequest(Request request) : this(request.id,
-          error: new RequestError(
-              RequestErrorCode.UNKNOWN_REQUEST, 'Unknown request'));
+  Response.unknownRequest(Request request)
+      : this(request.id,
+            error: new RequestError(
+                RequestErrorCode.UNKNOWN_REQUEST, 'Unknown request'));
 
   /**
    * Initialize a newly created instance to represent an error condition caused
    * by a [request] referencing a source that does not exist.
    */
-  Response.unknownSource(Request request) : this(request.id,
-          error: new RequestError(
-              RequestErrorCode.UNKNOWN_SOURCE, 'Unknown source'));
+  Response.unknownSource(Request request)
+      : this(request.id,
+            error: new RequestError(
+                RequestErrorCode.UNKNOWN_SOURCE, 'Unknown source'));
 
-  Response.unsupportedFeature(String requestId, String message) : this(
-          requestId,
-          error: new RequestError(
-              RequestErrorCode.UNSUPPORTED_FEATURE, message));
+  Response.unsupportedFeature(String requestId, String message)
+      : this(requestId,
+            error: new RequestError(
+                RequestErrorCode.UNSUPPORTED_FEATURE, message));
 
   /**
    * Return a table representing the structure of the Json object that will be
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index f9e48c58..4f0b490 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -47,6 +47,23 @@
   change.addEdit(file, fileStamp, edit);
 }
 
+String getReturnTypeString(engine.Element element) {
+  if (element is engine.ExecutableElement) {
+    if (element.kind == engine.ElementKind.SETTER) {
+      return null;
+    } else {
+      return element.returnType.toString();
+    }
+  } else if (element is engine.VariableElement) {
+    engine.DartType type = element.type;
+    return type != null ? type.displayName : 'dynamic';
+  } else if (element is engine.FunctionTypeAliasElement) {
+    return element.returnType.toString();
+  } else {
+    return null;
+  }
+}
+
 /**
  * Construct based on error information from the analyzer engine.
  */
@@ -86,7 +103,7 @@
   String name = element.displayName;
   String elementTypeParameters = _getTypeParametersString(element);
   String elementParameters = _getParametersString(element);
-  String elementReturnType = _getReturnTypeString(element);
+  String elementReturnType = getReturnTypeString(element);
   ElementKind kind = newElementKind_fromEngineElement(element);
   return new Element(kind, name, Element.makeFlags(
           isPrivate: element.isPrivate,
@@ -103,7 +120,7 @@
 
 /**
  * Construct based on a value from the analyzer engine.
- * This does not take into account that 
+ * This does not take into account that
  * instances of ClassElement can be an enum and
  * instances of FieldElement can be an enum constant.
  * Use [newElementKind_fromEngineElement] where possible.
@@ -351,23 +368,6 @@
   return '(' + sb.toString() + ')';
 }
 
-String _getReturnTypeString(engine.Element element) {
-  if (element is engine.ExecutableElement) {
-    if (element.kind == engine.ElementKind.SETTER) {
-      return null;
-    } else {
-      return element.returnType.toString();
-    }
-  } else if (element is engine.VariableElement) {
-    engine.DartType type = element.type;
-    return type != null ? type.displayName : 'dynamic';
-  } else if (element is engine.FunctionTypeAliasElement) {
-    return element.returnType.toString();
-  } else {
-    return null;
-  }
-}
-
 String _getTypeParametersString(engine.Element element) {
   List<engine.TypeParameterElement> typeParameters;
   if (element is engine.ClassElement) {
diff --git a/pkg/analysis_server/lib/src/server_options.dart b/pkg/analysis_server/lib/src/server_options.dart
new file mode 100644
index 0000000..2eff6d9
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server_options.dart
@@ -0,0 +1,118 @@
+// 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 analysis_server.src.server_options;
+
+import 'dart:collection';
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+import 'package:yaml/yaml.dart';
+
+//TODO: consider renaming (https://github.com/dart-lang/sdk/issues/23927)
+const _optionsFileName = '.dart_analysis_server.yaml';
+
+/// The shared options instance.
+ServerOptions _serverOptions;
+
+/// Server options.
+ServerOptions get serverOptions {
+  if (_serverOptions == null) {
+    _serverOptions = _loadOptions();
+  }
+  return _serverOptions;
+}
+
+/// Find the options file relative to the user's home directory.
+/// Returns `null` if there is none or the user's homedir cannot
+/// be derived from the platform's environment (e.g., `HOME` and
+/// `UserProfile` for mac/Linux and Windows respectively).
+File _findOptionsFile() {
+  String home;
+  Map<String, String> envVars = Platform.environment;
+  if (Platform.isMacOS || Platform.isLinux) {
+    home = envVars['HOME'];
+  } else if (Platform.isWindows) {
+    home = envVars['UserProfile'];
+  }
+
+  if (home == null) {
+    return null;
+  }
+
+  return new File(path.context.join(home, _optionsFileName));
+}
+
+ServerOptions _loadOptions() {
+  File optionsFile = _findOptionsFile();
+  try {
+    if (optionsFile != null && optionsFile.existsSync()) {
+      return new ServerOptions.fromFile(optionsFile);
+    }
+  } catch (e) {
+    // Fall through.
+  }
+  return new ServerOptions._empty();
+}
+
+/// Describes options captured in an external options file.
+/// `ServerOptions` are described in a file `dart_analysis_server.options`
+/// located in the user's home directory. Options are defined in YAML and
+/// read once and cached. In order for changes to be picked up, server needs
+/// to be restarted.
+class ServerOptions {
+  final Map<String, dynamic> _options = new HashMap<String, dynamic>();
+
+  /// Load options from the given [contents].
+  ServerOptions.fromContents(String contents) {
+    _readOptions(contents);
+  }
+
+  /// Load options from the given [options] file.
+  factory ServerOptions.fromFile(File options) =>
+      new ServerOptions.fromContents(options.readAsStringSync());
+
+  /// Create an empty options object.
+  ServerOptions._empty();
+
+  /// Get the value for `key` from the options file.
+  dynamic operator [](String key) => _options[key];
+
+  /// Get a String value for this `key` or [defaultValue] if undefined
+  /// or not a String.
+  String getStringValue(String key, {String defaultValue: null}) {
+    var value = _options[key];
+    if (value is String) {
+      return value;
+    }
+    return defaultValue;
+  }
+
+  /// Test whether the given [booleanPropertyKey] is set to the value `true`,
+  /// falling back to [defaultValue] if undefined.
+  /// For example:
+  ///     myDebugOption1:true
+  ///     myDebugOption2:TRUE # Also true (case and trailing whitespace are ignored).
+  ///     myDebugOption3:false
+  ///     myDebugOption4:off  # Treated as `false`.
+  ///     myDebugOption5:on   # Also read as `false`.
+  bool isSet(String booleanPropertyKey, {bool defaultValue: false}) {
+    var value = _options[booleanPropertyKey];
+    if (value == null) {
+      return defaultValue;
+    }
+    return value == true;
+  }
+
+  void _readOptions(String contents) {
+    var doc = loadYaml(contents);
+    if (doc is YamlMap) {
+      doc.forEach((k, v) {
+        if (k is String) {
+          _options[k] = v;
+        }
+      });
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
index 9fb70ba..b3a78e6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
@@ -127,6 +127,9 @@
    */
   List<DartCompletionContributor> computeFast(
       DartCompletionRequest request, CompletionPerformance performance) {
+    bool isKeywordOrIdentifier(Token token) =>
+        token.type == TokenType.KEYWORD || token.type == TokenType.IDENTIFIER;
+
     return performance.logElapseTime('computeFast', () {
       CompilationUnit unit = context.parseCompilationUnit(source);
       request.unit = unit;
@@ -140,12 +143,22 @@
 
       var entity = request.target.entity;
       Token token = entity is AstNode ? entity.beginToken : entity;
-      if (token != null &&
-          token.offset <= request.offset &&
-          (token.type == TokenType.KEYWORD ||
-              token.type == TokenType.IDENTIFIER)) {
-        request.replacementOffset = token.offset;
-        request.replacementLength = token.length;
+      if (token != null && request.offset < token.offset) {
+        token = token.previous;
+      }
+      if (token != null) {
+        if (request.offset == token.offset && !isKeywordOrIdentifier(token)) {
+          // If the insertion point is at the beginning of the current token
+          // and the current token is not an identifier
+          // then check the previous token to see if it should be replaced
+          token = token.previous;
+        }
+        if (token != null && isKeywordOrIdentifier(token)) {
+          if (token.offset <= request.offset && request.offset <= token.end) {
+            request.replacementOffset = token.offset;
+            request.replacementLength = token.length;
+          }
+        }
       }
 
       List<DartCompletionContributor> todo = new List.from(contributors);
diff --git a/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
index 7eca2b5..9cfbb0d 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/services/completion/local_suggestion_builder.dart';
 import 'package:analysis_server/src/services/completion/optype.dart';
 import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -182,7 +183,7 @@
     }
     paramBuf.write(')');
     protocol.Element element = createElement(
-        protocol.ElementKind.CONSTRUCTOR, elemId,
+        request.source, protocol.ElementKind.CONSTRUCTOR, elemId,
         parameters: paramBuf.toString());
     element.returnType = classDecl.name.name;
     CompletionSuggestion suggestion = new CompletionSuggestion(
@@ -277,8 +278,9 @@
     if (isCaseLabel ? includeCaseLabels : includeStatementLabels) {
       CompletionSuggestion suggestion = _addSuggestion(label.label);
       if (suggestion != null) {
-        suggestion.element =
-            _createElement(protocol.ElementKind.LABEL, label.label);
+        suggestion.element = createElement(
+            request.source, protocol.ElementKind.LABEL, label.label,
+            returnType: NO_RETURN_TYPE);
       }
     }
   }
@@ -331,17 +333,6 @@
     }
     return null;
   }
-
-  /**
-   * Create a new protocol Element for inclusion in a completion suggestion.
-   */
-  protocol.Element _createElement(
-      protocol.ElementKind kind, SimpleIdentifier id) {
-    String name = id.name;
-    int flags =
-        protocol.Element.makeFlags(isPrivate: Identifier.isPrivateName(name));
-    return new protocol.Element(kind, name, flags);
-  }
 }
 
 /**
@@ -386,7 +377,7 @@
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
     if (optype.includeReturnValueSuggestions) {
       CompletionSuggestion suggestion =
-          createFieldSuggestion(fieldDecl, varDecl);
+          createFieldSuggestion(request.source, fieldDecl, varDecl);
       if (suggestion != null) {
         request.addSuggestion(suggestion);
       }
@@ -547,7 +538,7 @@
         id, isDeprecated, relevance, typeName, classDecl: classDecl);
     if (suggestion != null) {
       request.addSuggestion(suggestion);
-      suggestion.element = createElement(elemKind, id,
+      suggestion.element = createElement(request.source, elemKind, id,
           isAbstract: isAbstract,
           isDeprecated: isDeprecated,
           parameters: param != null ? param.toSource() : null,
diff --git a/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart
index 8014dd4..324e1a7 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
 
 const DYNAMIC = 'dynamic';
 
@@ -19,16 +20,28 @@
 /**
  * Create a new protocol Element for inclusion in a completion suggestion.
  */
-protocol.Element createElement(protocol.ElementKind kind, SimpleIdentifier id,
+protocol.Element createElement(
+    Source source, protocol.ElementKind kind, SimpleIdentifier id,
     {String parameters, TypeName returnType, bool isAbstract: false,
     bool isDeprecated: false}) {
-  String name = id != null ? id.name : '';
+  String name;
+  Location location;
+  if (id != null) {
+    name = id.name;
+    // TODO(danrubel) use lineInfo to determine startLine and startColumn
+    location = new Location(source.fullName, id.offset, id.length, 0, 0);
+  } else {
+    name = '';
+    location = new Location(source.fullName, -1, 0, 1, 0);
+  }
   int flags = protocol.Element.makeFlags(
       isAbstract: isAbstract,
       isDeprecated: isDeprecated,
       isPrivate: Identifier.isPrivateName(name));
   return new protocol.Element(kind, name, flags,
-      parameters: parameters, returnType: nameForType(returnType));
+      location: location,
+      parameters: parameters,
+      returnType: nameForType(returnType));
 }
 
 /**
@@ -36,13 +49,13 @@
  * Return the new suggestion or `null` if it could not be created.
  */
 CompletionSuggestion createFieldSuggestion(
-    FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
+    Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
   bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
   TypeName type = fieldDecl.fields.type;
   return createSuggestion(
       varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
       classDecl: fieldDecl.parent,
-      element: createElement(protocol.ElementKind.FIELD, varDecl.name,
+      element: createElement(source, protocol.ElementKind.FIELD, varDecl.name,
           returnType: type, isDeprecated: deprecated));
 }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/optype.dart b/pkg/analysis_server/lib/src/services/completion/optype.dart
index c9d88bcd..7ab13f9 100644
--- a/pkg/analysis_server/lib/src/services/completion/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/optype.dart
@@ -543,7 +543,6 @@
     if (identical(entity, node.expression)) {
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
-      optype.includeVoidReturnSuggestions = true;
     }
   }
 
@@ -553,6 +552,21 @@
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
+    if (identical(entity, node.rightBracket)) {
+      if (node.members.isNotEmpty) {
+        optype.includeReturnValueSuggestions = true;
+        optype.includeTypeNameSuggestions = true;
+        optype.includeVoidReturnSuggestions = true;
+      }
+    }
+    if (entity is SwitchMember && entity != node.members.first) {
+      SwitchMember member = entity as SwitchMember;
+      if (offset <= member.offset) {
+          optype.includeReturnValueSuggestions = true;
+          optype.includeTypeNameSuggestions = true;
+          optype.includeVoidReturnSuggestions = true;
+      }
+    }
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart b/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
index 5abb208..f3a9db4 100644
--- a/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
@@ -8,9 +8,12 @@
 
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
 import 'package:analysis_server/src/services/completion/local_declaration_visitor.dart';
-import 'package:analysis_server/src/services/completion/local_suggestion_builder.dart';
+import 'package:analysis_server/src/services/completion/local_suggestion_builder.dart'
+    hide createSuggestion;
 import 'package:analysis_server/src/services/completion/optype.dart';
 import 'package:analysis_server/src/services/completion/suggestion_builder.dart';
+import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
+    show createSuggestion;
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 
@@ -134,7 +137,7 @@
                 if (fieldName != null && fieldName.length > 0) {
                   if (!referencedFields.contains(fieldName)) {
                     CompletionSuggestion suggestion =
-                        createFieldSuggestion(member, varDecl);
+                        createFieldSuggestion(request.source, member, varDecl);
                     if (suggestion != null) {
                       request.addSuggestion(suggestion);
                     }
@@ -405,20 +408,8 @@
                 request.target.containingNode.parent is TypeName);
             modified = true;
             if (directive.deferredKeyword != null) {
-              String completion = 'loadLibrary';
-              CompletionSuggestion suggestion = new CompletionSuggestion(
-                  CompletionSuggestionKind.INVOCATION, DART_RELEVANCE_DEFAULT,
-                  completion, completion.length, 0, false, false,
-                  parameterNames: [],
-                  parameterTypes: [],
-                  requiredParameterCount: 0,
-                  hasNamedParameters: false,
-                  returnType: 'void');
-              suggestion.element = new protocol.Element(
-                  protocol.ElementKind.FUNCTION, completion,
-                  protocol.Element.makeFlags(),
-                  parameters: '()', returnType: 'void');
-              request.addSuggestion(suggestion);
+              FunctionElement loadLibFunct = library.loadLibraryFunction;
+              request.addSuggestion(createSuggestion(loadLibFunct));
             }
           }
         }
diff --git a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
index 157a9e0..c6e376a 100644
--- a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
@@ -28,35 +28,10 @@
 CompletionSuggestion createSuggestion(Element element,
     {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
     int relevance: DART_RELEVANCE_DEFAULT, Source importForSource}) {
-  String nameForType(DartType type) {
-    if (type == null) {
-      return DYNAMIC;
-    }
-    String name = type.displayName;
-    if (name == null || name.length <= 0) {
-      return DYNAMIC;
-    }
-    //TODO (danrubel) include type arguments ??
-    return name;
+  if (element is ExecutableElement && element.isOperator) {
+    // Do not include operators in suggestions
+    return null;
   }
-
-  String returnType = null;
-  if (element is ExecutableElement) {
-    if (element.isOperator) {
-      // Do not include operators in suggestions
-      return null;
-    }
-    if (element is PropertyAccessorElement && element.isSetter) {
-      // no return type
-    } else {
-      returnType = nameForType(element.returnType);
-    }
-  } else if (element is VariableElement) {
-    returnType = nameForType(element.type);
-  } else if (element is FunctionTypeAliasElement) {
-    returnType = nameForType(element.returnType);
-  }
-
   String completion = element.displayName;
   bool isDeprecated = element.isDeprecated;
   CompletionSuggestion suggestion = new CompletionSuggestion(kind,
@@ -67,7 +42,7 @@
   if (enclosingElement is ClassElement) {
     suggestion.declaringType = enclosingElement.displayName;
   }
-  suggestion.returnType = returnType;
+  suggestion.returnType = getReturnTypeString(element);
   if (element is ExecutableElement && element is! PropertyAccessorElement) {
     suggestion.parameterNames = element.parameters
         .map((ParameterElement parameter) => parameter.name)
@@ -476,6 +451,12 @@
   @override
   visitCompilationUnitElement(CompilationUnitElement element) {
     element.visitChildren(this);
+    LibraryElement containingLibrary = element.library;
+    if (containingLibrary != null) {
+      for (var lib in containingLibrary.exportedLibraries) {
+        lib.visitChildren(this);
+      }
+    }
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 9c5e9ba..cf87d27 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -399,13 +399,19 @@
       return;
     }
     Expression returnValue = (body as ExpressionFunctionBody).expression;
+    DartType returnValueType = returnValue.staticType;
+    String returnValueCode = _getNodeText(returnValue);
     // prepare prefix
     String prefix = utils.getNodePrefix(body.parent);
-    // add change
     String indent = utils.getIndent(1);
-    String returnSource = 'return ' + _getNodeText(returnValue);
-    String newBodySource = '{$eol$prefix$indent$returnSource;$eol$prefix}';
-    _addReplaceEdit(rangeNode(body), newBodySource);
+    // add change
+    String statementCode =
+        (returnValueType.isVoid ? '' : 'return ') + returnValueCode;
+    SourceBuilder sb = new SourceBuilder(file, body.offset);
+    sb.append('{$eol$prefix$indent$statementCode;');
+    sb.setExitOffset();
+    sb.append('$eol$prefix}');
+    _insertBuilder(sb, body.length);
     // add proposal
     _addAssist(DartAssistKind.CONVERT_INTO_BLOCK_BODY, []);
   }
@@ -423,13 +429,14 @@
       _coverageMarker();
       return;
     }
-    if (statements[0] is! ReturnStatement) {
-      _coverageMarker();
-      return;
-    }
-    ReturnStatement returnStatement = statements[0] as ReturnStatement;
+    Statement onlyStatement = statements.first;
     // prepare returned expression
-    Expression returnExpression = returnStatement.expression;
+    Expression returnExpression;
+    if (onlyStatement is ReturnStatement) {
+      returnExpression = onlyStatement.expression;
+    } else if (onlyStatement is ExpressionStatement) {
+      returnExpression = onlyStatement.expression;
+    }
     if (returnExpression == null) {
       _coverageMarker();
       return;
@@ -484,8 +491,8 @@
       // check number of references
       {
         int numOfReferences = 0;
-        AstVisitor visitor = new _SimpleIdentifierRecursiveAstVisitor(
-            (SimpleIdentifier node) {
+        AstVisitor visitor =
+            new _SimpleIdentifierRecursiveAstVisitor((SimpleIdentifier node) {
           if (node.staticElement == parameterElement) {
             numOfReferences++;
           }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 46ae81f..dde87a0 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -6,6 +6,7 @@
 
 import 'package:analysis_server/edit/fix/fix_core.dart';
 import 'package:analysis_server/src/plugin/server_plugin.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -15,13 +16,14 @@
  * reported after it's source was analyzed in the given [context]. The [plugin]
  * is used to get the list of fix contributors.
  */
-List<Fix> computeFixes(
-    ServerPlugin plugin, AnalysisContext context, AnalysisError error) {
+List<Fix> computeFixes(ServerPlugin plugin, ResourceProvider resourceProvider,
+    AnalysisContext context, AnalysisError error) {
   List<Fix> fixes = <Fix>[];
   List<FixContributor> contributors = plugin.fixContributors;
   for (FixContributor contributor in contributors) {
     try {
-      List<Fix> contributedFixes = contributor.computeFixes(context, error);
+      List<Fix> contributedFixes =
+          contributor.computeFixes(resourceProvider, context, error);
       if (contributedFixes != null) {
         fixes.addAll(contributedFixes);
       }
@@ -44,7 +46,8 @@
   static const ADD_FIELD_FORMAL_PARAMETERS = const FixKind(
       'ADD_FIELD_FORMAL_PARAMETERS', 30, "Add final field formal parameters");
   static const ADD_MISSING_PARAMETER_POSITIONAL = const FixKind(
-      'ADD_MISSING_PARAMETER_POSITIONAL', 31,
+      'ADD_MISSING_PARAMETER_POSITIONAL',
+      31,
       "Add optional positional parameter");
   static const ADD_MISSING_PARAMETER_REQUIRED = const FixKind(
       'ADD_MISSING_PARAMETER_REQUIRED', 30, "Add required parameter");
@@ -53,7 +56,8 @@
   static const ADD_PART_OF =
       const FixKind('ADD_PART_OF', 50, "Add 'part of' directive");
   static const ADD_SUPER_CONSTRUCTOR_INVOCATION = const FixKind(
-      'ADD_SUPER_CONSTRUCTOR_INVOCATION', 50,
+      'ADD_SUPER_CONSTRUCTOR_INVOCATION',
+      50,
       "Add super constructor {0} invocation");
   static const CHANGE_TO = const FixKind('CHANGE_TO', 49, "Change to '{0}'");
   static const CHANGE_TO_STATIC_ACCESS = const FixKind(
@@ -63,7 +67,8 @@
   static const CREATE_CONSTRUCTOR =
       const FixKind('CREATE_CONSTRUCTOR', 50, "Create constructor '{0}'");
   static const CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS = const FixKind(
-      'CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS', 50,
+      'CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS',
+      50,
       "Create constructor for final fields");
   static const CREATE_CONSTRUCTOR_SUPER = const FixKind(
       'CREATE_CONSTRUCTOR_SUPER', 50, "Create constructor to call {0}");
@@ -98,10 +103,12 @@
   static const REMOVE_DEAD_CODE =
       const FixKind('REMOVE_DEAD_CODE', 50, "Remove dead code");
   static const REMOVE_PARAMETERS_IN_GETTER_DECLARATION = const FixKind(
-      'REMOVE_PARAMETERS_IN_GETTER_DECLARATION', 50,
+      'REMOVE_PARAMETERS_IN_GETTER_DECLARATION',
+      50,
       "Remove parameters in getter declaration");
   static const REMOVE_PARENTHESIS_IN_GETTER_INVOCATION = const FixKind(
-      'REMOVE_PARENTHESIS_IN_GETTER_INVOCATION', 50,
+      'REMOVE_PARENTHESIS_IN_GETTER_INVOCATION',
+      50,
       "Remove parentheses in getter invocation");
   static const REMOVE_UNNECASSARY_CAST =
       const FixKind('REMOVE_UNNECASSARY_CAST', 50, "Remove unnecessary cast");
@@ -118,11 +125,13 @@
   static const REPLACE_VAR_WITH_DYNAMIC = const FixKind(
       'REPLACE_VAR_WITH_DYNAMIC', 50, "Replace 'var' with 'dynamic'");
   static const REPLACE_RETURN_TYPE_FUTURE = const FixKind(
-      'REPLACE_RETURN_TYPE_FUTURE', 50,
+      'REPLACE_RETURN_TYPE_FUTURE',
+      50,
       "Return 'Future' from 'async' function");
   static const USE_CONST = const FixKind('USE_CONST', 50, "Change to constant");
   static const USE_EFFECTIVE_INTEGER_DIVISION = const FixKind(
-      'USE_EFFECTIVE_INTEGER_DIVISION', 50,
+      'USE_EFFECTIVE_INTEGER_DIVISION',
+      50,
       "Use effective integer division ~/");
   static const USE_EQ_EQ_NULL =
       const FixKind('USE_EQ_EQ_NULL', 50, "Use == null instead of 'is Null'");
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 cb695b8..3c8f1a7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -5,6 +5,7 @@
 library analysis_server.src.services.correction.fix_internal;
 
 import 'dart:collection';
+import 'dart:core' hide Resource;
 
 import 'package:analysis_server/edit/fix/fix_core.dart';
 import 'package:analysis_server/edit/fix/fix_dart.dart';
@@ -22,6 +23,7 @@
 import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -33,6 +35,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:path/path.dart';
+import 'package:path/path.dart' as ppp;
 
 /**
  * A predicate is a one-argument function that returns a boolean value.
@@ -44,8 +47,9 @@
  */
 class DefaultFixContributor extends DartFixContributor {
   @override
-  List<Fix> internalComputeFixes(CompilationUnit unit, AnalysisError error) {
-    FixProcessor processor = new FixProcessor(unit, error);
+  List<Fix> internalComputeFixes(ResourceProvider resourceProvider,
+      CompilationUnit unit, AnalysisError error) {
+    FixProcessor processor = new FixProcessor(resourceProvider, unit, error);
     return processor.compute();
   }
 }
@@ -56,6 +60,7 @@
 class FixProcessor {
   static const int MAX_LEVENSHTEIN_DISTANCE = 3;
 
+  final ResourceProvider resourceProvider;
   final CompilationUnit unit;
   final AnalysisError error;
   AnalysisContext context;
@@ -83,7 +88,7 @@
   AstNode node;
   AstNode coveredNode;
 
-  FixProcessor(this.unit, this.error) {
+  FixProcessor(this.resourceProvider, this.unit, this.error) {
     unitElement = unit.element;
     context = unitElement.context;
     unitSource = unitElement.source;
@@ -207,8 +212,7 @@
     if (errorCode == StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR) {
       _addFix_createConstructor_named();
     }
-    if (errorCode ==
-            StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE ||
+    if (errorCode == StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE ||
         errorCode ==
             StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO ||
         errorCode ==
@@ -249,6 +253,7 @@
       bool isAsync = _addFix_addAsync();
       if (!isAsync) {
         _addFix_undefinedClassAccessor_useSimilar();
+        _addFix_createClass();
         _addFix_createField();
         _addFix_createGetter();
         _addFix_createFunction_forFunctionType();
@@ -423,7 +428,8 @@
         CorrectionUtils partUtils = new CorrectionUtils(partUnit);
         CorrectionUtils_InsertDesc desc = partUtils.getInsertDescTop();
         String libraryName = unitLibraryElement.name;
-        _addInsertEdit(desc.offset,
+        _addInsertEdit(
+            desc.offset,
             '${desc.prefix}part of $libraryName;$eol${desc.suffix}',
             partUnit.element);
         _addFix(DartFixKind.ADD_PART_OF, []);
@@ -440,17 +446,20 @@
   void _addFix_createClass() {
     Element prefixElement = null;
     String name = null;
+    SimpleIdentifier nameNode;
     if (node is SimpleIdentifier) {
       AstNode parent = node.parent;
       if (parent is PrefixedIdentifier) {
         PrefixedIdentifier prefixedIdentifier = parent;
         prefixElement = prefixedIdentifier.prefix.staticElement;
         parent = prefixedIdentifier.parent;
+        nameNode = prefixedIdentifier.identifier;
         name = prefixedIdentifier.identifier.name;
       } else {
-        name = (node as SimpleIdentifier).name;
+        nameNode = node;
+        name = nameNode.name;
       }
-      if (parent is! TypeName) {
+      if (!_mayBeTypeIdentifier(nameNode)) {
         return;
       }
     } else {
@@ -1050,8 +1059,7 @@
       if (source != null) {
         String file = source.fullName;
         if (isAbsolute(file)) {
-          String libName = removeEnd(source.shortName, '.dart');
-          libName = libName.replaceAll('_', '.');
+          String libName = _computeLibraryName(file);
           SourceEdit edit = new SourceEdit(0, 0, 'library $libName;$eol$eol');
           doSourceChange_addSourceEdit(change, context, source, edit);
           _addFix(DartFixKind.CREATE_FILE, [source.shortName]);
@@ -1344,10 +1352,8 @@
       if (prefix != null) {
         SourceRange range = rf.rangeStartLength(node, 0);
         _addReplaceEdit(range, '${prefix.displayName}.');
-        _addFix(DartFixKind.IMPORT_LIBRARY_PREFIX, [
-          libraryElement.displayName,
-          prefix.displayName
-        ]);
+        _addFix(DartFixKind.IMPORT_LIBRARY_PREFIX,
+            [libraryElement.displayName, prefix.displayName]);
         continue;
       }
       // may be update "show" directive
@@ -1657,7 +1663,8 @@
   void _addFix_undefinedClass_useSimilar() {
     if (_mayBeTypeIdentifier(node)) {
       String name = (node as SimpleIdentifier).name;
-      _ClosestElementFinder finder = new _ClosestElementFinder(name,
+      _ClosestElementFinder finder = new _ClosestElementFinder(
+          name,
           (Element element) => element is ClassElement,
           MAX_LEVENSHTEIN_DISTANCE);
       // find closest element
@@ -1790,7 +1797,8 @@
   void _addFix_undefinedFunction_useSimilar() {
     if (node is SimpleIdentifier) {
       String name = (node as SimpleIdentifier).name;
-      _ClosestElementFinder finder = new _ClosestElementFinder(name,
+      _ClosestElementFinder finder = new _ClosestElementFinder(
+          name,
           (Element element) => element is FunctionElement,
           MAX_LEVENSHTEIN_DISTANCE);
       // this library
@@ -2052,9 +2060,16 @@
    * Prepares proposal for creating function corresponding to the given
    * [FunctionType].
    */
-  void _addProposal_createFunction(FunctionType functionType, String name,
-      Source targetSource, int insertOffset, bool isStatic, String prefix,
-      String sourcePrefix, String sourceSuffix, Element target) {
+  void _addProposal_createFunction(
+      FunctionType functionType,
+      String name,
+      Source targetSource,
+      int insertOffset,
+      bool isStatic,
+      String prefix,
+      String sourcePrefix,
+      String sourceSuffix,
+      Element target) {
     // build method source
     String targetFile = targetSource.fullName;
     SourceBuilder sb = new SourceBuilder(targetFile, insertOffset);
@@ -2154,8 +2169,15 @@
       sourcePrefix = eol;
     }
     String sourceSuffix = eol;
-    _addProposal_createFunction(functionType, name, targetSource, insertOffset,
-        _inStaticContext(), prefix, sourcePrefix, sourceSuffix,
+    _addProposal_createFunction(
+        functionType,
+        name,
+        targetSource,
+        insertOffset,
+        _inStaticContext(),
+        prefix,
+        sourcePrefix,
+        sourceSuffix,
         targetClassElement);
     // add proposal
     _addFix(DartFixKind.CREATE_METHOD, [name]);
@@ -2274,6 +2296,51 @@
   }
 
   /**
+   * Computes the name of the library at the given [path].
+   * See https://www.dartlang.org/articles/style-guide/#names for conventions.
+   */
+  String _computeLibraryName(String path) {
+    Context pathContext = resourceProvider.pathContext;
+    String packageFolder = _computePackageFolder(path);
+    if (packageFolder == null) {
+      return pathContext.basenameWithoutExtension(path);
+    }
+    String packageName = pathContext.basename(packageFolder);
+    String relPath = pathContext.relative(path, from: packageFolder);
+    List<String> relPathParts = pathContext.split(relPath);
+    if (relPathParts.isNotEmpty) {
+      if (relPathParts[0].toLowerCase() == 'lib') {
+        relPathParts.removeAt(0);
+      }
+      {
+        String nameWithoutExt = pathContext.withoutExtension(relPathParts.last);
+        relPathParts[relPathParts.length - 1] = nameWithoutExt;
+      }
+    }
+    return packageName + '.' + relPathParts.join('.');
+  }
+
+  /**
+   * Returns the path of the folder which contains the given [path].
+   */
+  String _computePackageFolder(String path) {
+    Context pathContext = resourceProvider.pathContext;
+    String pubspecFolder = dirname(path);
+    while (true) {
+      if (resourceProvider
+          .getResource(pathContext.join(pubspecFolder, 'pubspec.yaml'))
+          .exists) {
+        return pubspecFolder;
+      }
+      String pubspecFolderNew = pathContext.dirname(pubspecFolder);
+      if (pubspecFolderNew == pubspecFolder) {
+        return null;
+      }
+      pubspecFolder = pubspecFolderNew;
+    }
+  }
+
+  /**
    * @return the string to display as the name of the given constructor in a proposal name.
    */
   String _getConstructorProposalName(ConstructorElement constructor) {
@@ -2611,24 +2678,27 @@
     return <String>['arg$index'];
   }
 
+  static bool _isNameOfType(String name) {
+    if (name.isEmpty) {
+      return false;
+    }
+    String firstLetter = name.substring(0, 1);
+    if (firstLetter.toUpperCase() != firstLetter) {
+      return false;
+    }
+    return true;
+  }
+
   /**
    * Returns `true` if [node] is a type name.
    */
   static bool _mayBeTypeIdentifier(AstNode node) {
     if (node is SimpleIdentifier) {
       AstNode parent = node.parent;
-      if (parent is Annotation) {
-        return true;
-      }
       if (parent is TypeName) {
         return true;
       }
-      if (parent is MethodInvocation) {
-        return parent.realTarget == node;
-      }
-      if (parent is PrefixedIdentifier) {
-        return parent.prefix == node;
-      }
+      return _isNameOfType(node.name);
     }
     return false;
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
new file mode 100644
index 0000000..b12ecb1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
@@ -0,0 +1,248 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library services.src.refactoring.organize_directives;
+
+import 'package:analysis_server/src/protocol.dart' hide AnalysisError, Element;
+import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'dart:math';
+
+/**
+ * Organizer of directives in the [unit].
+ */
+class DirectiveOrganizer {
+  final String initialCode;
+  final CompilationUnit unit;
+  final List<AnalysisError> errors;
+  final bool removeUnresolved;
+  final bool removeUnused;
+  String code;
+  String endOfLine;
+
+  DirectiveOrganizer(this.initialCode, this.unit, this.errors,
+      {this.removeUnresolved: true, this.removeUnused: true}) {
+    this.code = initialCode;
+    this.endOfLine = getEOL(code);
+  }
+
+  /**
+   * Return the [SourceEdit]s that organize directives in the [unit].
+   */
+  List<SourceEdit> organize() {
+    _organizeDirectives();
+    // prepare edits
+    List<SourceEdit> edits = <SourceEdit>[];
+    if (code != initialCode) {
+      int suffixLength = findCommonSuffix(initialCode, code);
+      SourceEdit edit = new SourceEdit(0, initialCode.length - suffixLength,
+          code.substring(0, code.length - suffixLength));
+      edits.add(edit);
+    }
+    return edits;
+  }
+
+  bool _isUnresolvedUri(UriBasedDirective directive) {
+    for (AnalysisError error in errors) {
+      if (error.errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST &&
+          directive.uri.offset == error.offset) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool _isUnusedImport(UriBasedDirective directive) {
+    for (AnalysisError error in errors) {
+      if (error.errorCode == HintCode.UNUSED_IMPORT &&
+          directive.uri.offset == error.offset) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Oraganize all [Directive]s.
+   */
+  void _organizeDirectives() {
+    List<_DirectiveInfo> directives = [];
+    for (Directive directive in unit.directives) {
+      if (directive is UriBasedDirective) {
+        _DirectivePriority priority = getDirectivePriority(directive);
+        if (priority != null) {
+          int offset = directive.offset;
+          int length = directive.length;
+          String text = code.substring(offset, offset + length);
+          String uriContent = directive.uri.stringValue;
+          directives
+              .add(new _DirectiveInfo(directive, priority, uriContent, text));
+        }
+      }
+    }
+    // nothing to do
+    if (directives.isEmpty) {
+      return;
+    }
+    int firstDirectiveOffset = directives.first.directive.offset;
+    int lastDirectiveEnd = directives.last.directive.end;
+    // sort
+    directives.sort();
+    // append directives with grouping
+    String directivesCode;
+    {
+      StringBuffer sb = new StringBuffer();
+      _DirectivePriority currentPriority = null;
+      for (_DirectiveInfo directiveInfo in directives) {
+        if (removeUnresolved && _isUnresolvedUri(directiveInfo.directive)) {
+          continue;
+        }
+        if (removeUnused && _isUnusedImport(directiveInfo.directive)) {
+          continue;
+        }
+        if (currentPriority != directiveInfo.priority) {
+          if (sb.length != 0) {
+            sb.write(endOfLine);
+          }
+          currentPriority = directiveInfo.priority;
+        }
+        sb.write(directiveInfo.text);
+        sb.write(endOfLine);
+      }
+      directivesCode = sb.toString();
+      directivesCode = directivesCode.trimRight();
+    }
+    // append comment tokens which otherwise would be removed completely
+    {
+      bool firstCommentToken = true;
+      Token token = unit.beginToken;
+      while (token != null &&
+          token.type != TokenType.EOF &&
+          token.end < lastDirectiveEnd) {
+        Token commentToken = token.precedingComments;
+        while (commentToken != null) {
+          int offset = commentToken.offset;
+          int end = commentToken.end;
+          if (offset > firstDirectiveOffset && offset < lastDirectiveEnd) {
+            if (firstCommentToken) {
+              directivesCode += endOfLine;
+              firstCommentToken = false;
+            }
+            directivesCode += code.substring(offset, end) + endOfLine;
+          }
+          commentToken = commentToken.next;
+        }
+        token = token.next;
+      }
+    }
+    // prepare code
+    String beforeDirectives = code.substring(0, firstDirectiveOffset);
+    String afterDirectives = code.substring(lastDirectiveEnd);
+    code = beforeDirectives + directivesCode + afterDirectives;
+  }
+
+  static _DirectivePriority getDirectivePriority(UriBasedDirective directive) {
+    String uriContent = directive.uri.stringValue;
+    if (directive is ImportDirective) {
+      if (uriContent.startsWith("dart:")) {
+        return _DirectivePriority.IMPORT_SDK;
+      } else if (uriContent.startsWith("package:")) {
+        return _DirectivePriority.IMPORT_PKG;
+      } else if (uriContent.contains('://')) {
+        return _DirectivePriority.IMPORT_OTHER;
+      } else {
+        return _DirectivePriority.IMPORT_REL;
+      }
+    }
+    if (directive is ExportDirective) {
+      if (uriContent.startsWith("dart:")) {
+        return _DirectivePriority.EXPORT_SDK;
+      } else if (uriContent.startsWith("package:")) {
+        return _DirectivePriority.EXPORT_PKG;
+      } else if (uriContent.contains('://')) {
+        return _DirectivePriority.EXPORT_OTHER;
+      } else {
+        return _DirectivePriority.EXPORT_REL;
+      }
+    }
+    if (directive is PartDirective) {
+      return _DirectivePriority.PART;
+    }
+    return null;
+  }
+
+  /**
+   * Return the EOL to use for [code].
+   */
+  static String getEOL(String code) {
+    if (code.contains('\r\n')) {
+      return '\r\n';
+    } else {
+      return '\n';
+    }
+  }
+}
+
+class _DirectiveInfo implements Comparable<_DirectiveInfo> {
+  final UriBasedDirective directive;
+  final _DirectivePriority priority;
+  final String uri;
+  final String text;
+
+  _DirectiveInfo(this.directive, this.priority, this.uri, this.text);
+
+  @override
+  int compareTo(_DirectiveInfo other) {
+    if (priority == other.priority) {
+      return _compareUri(uri, other.uri);
+    }
+    return priority.ordinal - other.priority.ordinal;
+  }
+
+  @override
+  String toString() => '(priority=$priority; text=$text)';
+
+  static int _compareUri(String a, String b) {
+    List<String> aList = _splitUri(a);
+    List<String> bList = _splitUri(b);
+    int result;
+    if ((result = aList[0].compareTo(bList[0])) != 0) return result;
+    if ((result = aList[1].compareTo(bList[1])) != 0) return result;
+    return 0;
+  }
+
+  /**
+   * Split the given [uri] like `package:some.name/and/path.dart` into a list
+   * like `[package:some.name, and/path.dart]`.
+   */
+  static List<String> _splitUri(String uri) {
+    int index = uri.indexOf('/');
+    if (index == -1) {
+      return <String>[uri, ''];
+    }
+    return <String>[uri.substring(0, index), uri.substring(index + 1)];
+  }
+}
+
+class _DirectivePriority {
+  static const IMPORT_SDK = const _DirectivePriority('IMPORT_SDK', 0);
+  static const IMPORT_PKG = const _DirectivePriority('IMPORT_PKG', 1);
+  static const IMPORT_OTHER = const _DirectivePriority('IMPORT_OTHER', 2);
+  static const IMPORT_REL = const _DirectivePriority('IMPORT_REL', 3);
+  static const EXPORT_SDK = const _DirectivePriority('EXPORT_SDK', 4);
+  static const EXPORT_PKG = const _DirectivePriority('EXPORT_PKG', 5);
+  static const EXPORT_OTHER = const _DirectivePriority('EXPORT_OTHER', 6);
+  static const EXPORT_REL = const _DirectivePriority('EXPORT_REL', 7);
+  static const PART = const _DirectivePriority('PART', 8);
+
+  final String name;
+  final int ordinal;
+
+  const _DirectivePriority(this.name, this.ordinal);
+
+  @override
+  String toString() => name;
+}
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 1968766..d5abd12 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -11,10 +11,10 @@
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analysis_server/src/services/index/local_file_index.dart';
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
 import 'package:analysis_server/uri/resolver_provider.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
 import 'package:plugin/plugin.dart';
 
@@ -81,9 +81,8 @@
     }
 
     analysisServer = new AnalysisServer(serverChannel, resourceProvider,
-        new OptimizingPubPackageMapProvider(resourceProvider, defaultSdk),
-        index, serverPlugin, analysisServerOptions, defaultSdk,
-        instrumentationService,
+        new PubPackageMapProvider(resourceProvider, defaultSdk), index,
+        serverPlugin, analysisServerOptions, defaultSdk, instrumentationService,
         contextManager: contextManager,
         packageResolverProvider: packageResolverProvider,
         rethrowExceptions: false);
diff --git a/pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart b/pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart
deleted file mode 100644
index deeee77..0000000
--- a/pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library source.optimizing_pub_package_map_provider;
-
-import 'dart:core' hide Resource;
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_provider.dart';
-import 'package:analyzer/source/pub_package_map_provider.dart';
-import 'package:analyzer/src/generated/sdk_io.dart';
-
-/**
- * Extension of [PackageMapInfo] that tracks the modification timestamps of
- * pub dependencies.  This allows the analysis server to avoid making redundant
- * calls to "pub list" when nothing has changed.
- */
-class OptimizingPubPackageMapInfo extends PackageMapInfo {
-  /**
-   * Map from file path to the file's modification timestamp prior to running
-   * "pub list".  Since the set of dependencies is not always known prior to
-   * running "pub list", some or all of the dependencies may be missing from
-   * this map.
-   */
-  final Map<String, int> modificationTimes;
-
-  OptimizingPubPackageMapInfo(Map<String, List<Folder>> packageMap,
-      Set<String> dependencies, this.modificationTimes)
-      : super(packageMap, dependencies);
-
-  /**
-   * Return `true` if the given [path] is listed as a dependency, and we cannot
-   * prove using modification timestamps that it is unchanged.
-   * [resourceProvider] is used (if necessary) to read the [path]'s
-   * modification time.
-   */
-  bool isChangedDependency(String path, ResourceProvider resourceProvider) {
-    if (!dependencies.contains(path)) {
-      // Path is not a dependency.
-      return false;
-    }
-    int lastModificationTime = modificationTimes[path];
-    if (lastModificationTime != null) {
-      Resource resource = resourceProvider.getResource(path);
-      if (resource is File) {
-        try {
-          if (resource.modificationStamp == lastModificationTime) {
-            // Path is a dependency, but it hasn't changed since the last run
-            // of "pub list".
-            return false;
-          }
-        } on FileSystemException {
-          // Path is a dependency, but we can't read its timestamp.  Assume
-          // it's changed to be safe.
-        }
-      }
-    }
-    // Path is a dependency, and we couldn't prove that it hadn't changed.
-    // Assume it's changed to be safe.
-    return true;
-  }
-}
-
-/**
- * Extension of [PubPackageMapProvider] that outputs additional information to
- * allow the analysis server to avoid making redundant calls to "pub list" when
- * nothing has changed.
- */
-class OptimizingPubPackageMapProvider extends PubPackageMapProvider {
-  OptimizingPubPackageMapProvider(
-      ResourceProvider resourceProvider, DirectoryBasedDartSdk sdk, [RunPubList runPubList])
-      : super(resourceProvider, sdk, runPubList);
-
-  /**
-   * Compute a package map for the given folder by executing "pub list".  If
-   * [previousInfo] is provided, it is used as a guess of which files the
-   * package map is likely to depend on; the modification times of those files
-   * are captured prior to executing "pub list" so that they can be used to
-   * avoid making redundant calls to "pub list" in the future.
-   *
-   * Also, in the case where dependencies can't be determined because of an
-   * error, the dependencies from [previousInfo] will be preserved.
-   */
-  OptimizingPubPackageMapInfo computePackageMap(Folder folder,
-      [OptimizingPubPackageMapInfo previousInfo]) {
-    // Prior to running "pub list", read the modification timestamps of all of
-    // the old dependencies (if known).
-    Map<String, int> modificationTimes = <String, int>{};
-    if (previousInfo != null) {
-      for (String path in previousInfo.dependencies) {
-        Resource resource = resourceProvider.getResource(path);
-        if (resource is File) {
-          try {
-            modificationTimes[path] = resource.modificationStamp;
-          } on FileSystemException {
-            // File no longer exists.  Don't record a timestamp for it; this
-            // will ensure that if the file reappears, we will re-run "pub
-            // list" regardless of the timestamp it reappears with.
-          }
-        }
-      }
-    }
-
-    // Try running "pub list".
-    PackageMapInfo info = super.computePackageMap(folder);
-    if (info == null) {
-      // Computing the package map resulted in an error.  Merge the old
-      // dependencies with the new ones, if possible.
-      info = super.computePackageMapError(folder);
-      if (previousInfo != null) {
-        info.dependencies.addAll(previousInfo.dependencies);
-      }
-    }
-
-    // Discard any elements of modificationTimes that are no longer
-    // dependencies.
-    if (previousInfo != null) {
-      for (String dependency
-          in previousInfo.dependencies.difference(info.dependencies)) {
-        modificationTimes.remove(dependency);
-      }
-    }
-
-    // Bundle the modificationTimes with the other info.
-    return new OptimizingPubPackageMapInfo(
-        info.packageMap, info.dependencies, modificationTimes);
-  }
-
-  @override
-  PackageMapInfo computePackageMapError(Folder folder) {
-    // Return null to indicate to our override of computePackageMap that there
-    // was an error, so it can compute dependencies correctly.
-    return null;
-  }
-}
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 0a053bd..5b5236c 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -1042,7 +1042,7 @@
     List<Folder> folders = folderMap.keys.toList();
     folders.sort((Folder first, Folder second) =>
         first.shortName.compareTo(second.shortName));
-    AnalysisOptionsImpl options = analysisServer.contextManager.defaultOptions;
+    AnalysisOptionsImpl options = analysisServer.defaultContextOptions;
     ServerOperationQueue operationQueue = analysisServer.operationQueue;
 
     buffer.write('<h3>Analysis Domain</h3>');
@@ -1084,8 +1084,6 @@
       _writeOption(
           buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
       _writeOption(buffer, 'Cache size', options.cacheSize);
-      _writeOption(buffer, 'Enable null-aware operators',
-          options.enableNullAwareOperators);
       _writeOption(
           buffer, 'Enable strict call checks', options.enableStrictCallChecks);
       _writeOption(buffer, 'Generate hints', options.hint);
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index a9cb19b..2b14dd6 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -6,7 +6,7 @@
 environment:
   sdk: '>=1.9.0 <2.0.0'
 dependencies:
-  analyzer: '>=0.25.3-alpha.0 <0.26.0'
+  analyzer: '>=0.26.0-alpha.0 <0.27.0'
   args: '>=0.13.0 <0.14.0'
   dart_style: '>=0.1.7 <0.2.0'
   logging: any
diff --git a/pkg/analysis_server/test/analysis/get_errors_test.dart b/pkg/analysis_server/test/analysis/get_errors_test.dart
index 14203c9..4cc0a2f 100644
--- a/pkg/analysis_server/test/analysis/get_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/get_errors_test.dart
@@ -99,7 +99,7 @@
     // remove context, causes sending an "invalid file" error
     {
       Folder projectFolder = resourceProvider.getResource(projectPath);
-      server.contextManager.removeContext(projectFolder);
+      server.contextManager.callbacks.removeContext(projectFolder, <String>[]);
     }
     // wait for an error response
     return serverChannel.waitForResponse(request).then((Response response) {
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index 1de99e4..752ee27 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -28,19 +28,6 @@
     createProject();
   }
 
-  test_afterAnalysisComplete() async {
-    addTestFile('''
-main() {
-  var test = 0;
-  print(test);
-}
-''');
-    await waitForTasksFinished();
-    await _getNavigation(testFile, testCode.indexOf('test);'), 0);
-    assertHasRegion('test);');
-    assertHasTarget('test = 0');
-  }
-
   test_beforeAnalysisComplete() async {
     addTestFile('''
 main() {
@@ -68,6 +55,36 @@
     return _checkInvalid(file, -1, -1);
   }
 
+  test_multipleRegions() async {
+    addTestFile('''
+main() {
+  var aaa = 1;
+  var bbb = 2;
+  var ccc = 3;
+  var ddd = 4;
+  print(aaa + bbb + ccc + ddd);
+}
+''');
+    await waitForTasksFinished();
+    // request navigation
+    String navCode = ' + bbb + ';
+    await _getNavigation(testFile, testCode.indexOf(navCode), navCode.length);
+    // verify
+    {
+      assertHasRegion('aaa +');
+      assertHasTarget('aaa = 1');
+    }
+    {
+      assertHasRegion('bbb +');
+      assertHasTarget('bbb = 2');
+    }
+    {
+      assertHasRegion('ccc +');
+      assertHasTarget('ccc = 3');
+    }
+    assertNoRegionAt('ddd)');
+  }
+
   test_removeContextAfterRequest() async {
     addTestFile('''
 main() {
@@ -82,7 +99,7 @@
     // remove context, causes sending an "invalid file" error
     {
       Folder projectFolder = resourceProvider.getResource(projectPath);
-      server.contextManager.removeContext(projectFolder);
+      server.contextManager.callbacks.removeContext(projectFolder, <String>[]);
     }
     // wait for an error response
     Response response = await serverChannel.waitForResponse(request);
@@ -90,6 +107,32 @@
     expect(response.error.code, RequestErrorCode.GET_NAVIGATION_INVALID_FILE);
   }
 
+  test_zeroLength_end() async {
+    addTestFile('''
+main() {
+  var test = 0;
+  print(test);
+}
+''');
+    await waitForTasksFinished();
+    await _getNavigation(testFile, testCode.indexOf(');'), 0);
+    assertHasRegion('test);');
+    assertHasTarget('test = 0');
+  }
+
+  test_zeroLength_start() async {
+    addTestFile('''
+main() {
+  var test = 0;
+  print(test);
+}
+''');
+    await waitForTasksFinished();
+    await _getNavigation(testFile, testCode.indexOf('test);'), 0);
+    assertHasRegion('test);');
+    assertHasTarget('test = 0');
+  }
+
   _checkInvalid(String file, int offset, int length) async {
     Request request = _createGetNavigationRequest(file, offset, length);
     Response response = await serverChannel.sendRequest(request);
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 6c440471ca..09de3e8 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -18,6 +18,155 @@
   defineReflectiveTests(AnalysisNotificationNavigationTest);
 }
 
+class AbstractNavigationTest extends AbstractAnalysisTest {
+  List<NavigationRegion> regions;
+  List<NavigationTarget> targets;
+  List<String> targetFiles;
+
+  NavigationRegion testRegion;
+  List<int> testTargetIndexes;
+  NavigationTarget testTarget;
+
+  /**
+   * Validates that there is a target in [testTargetIndexes] with [file],
+   * at [offset] and with the given [length].
+   */
+  void assertHasFileTarget(String file, int offset, int length) {
+    List<NavigationTarget> testTargets =
+        testTargetIndexes.map((int index) => targets[index]).toList();
+    for (NavigationTarget target in testTargets) {
+      if (targetFiles[target.fileIndex] == file &&
+          target.offset == offset &&
+          target.length == length) {
+        testTarget = target;
+        return;
+      }
+    }
+    fail(
+        'Expected to find target (file=$file; offset=$offset; length=$length) in\n'
+        '${testRegion} in\n' '${testTargets.join('\n')}');
+  }
+
+  void assertHasOperatorRegion(String regionSearch, int regionLength,
+      String targetSearch, int targetLength) {
+    assertHasRegion(regionSearch, regionLength);
+    assertHasTarget(targetSearch, targetLength);
+  }
+
+  /**
+   * Validates that there is a region at the offset of [search] in [testFile].
+   * If [length] is not specified explicitly, then length of an identifier
+   * from [search] is used.
+   */
+  void assertHasRegion(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = findIdentifierLength(search);
+    }
+    findRegion(offset, length, true);
+  }
+
+  /**
+   * Validates that there is a region at the offset of [search] in [testFile]
+   * with the given [length] or the length of [search].
+   */
+  void assertHasRegionString(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = search.length;
+    }
+    findRegion(offset, length, true);
+  }
+
+  /**
+   * Validates that there is an identifier region at [regionSearch] with target
+   * at [targetSearch].
+   */
+  void assertHasRegionTarget(String regionSearch, String targetSearch) {
+    assertHasRegion(regionSearch);
+    assertHasTarget(targetSearch);
+  }
+
+  /**
+   * Validates that there is a target in [testTargets]  with [testFile], at the
+   * offset of [search] in [testFile], and with the given [length] or the length
+   * of an leading identifier in [search].
+   */
+  void assertHasTarget(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = findIdentifierLength(search);
+    }
+    assertHasFileTarget(testFile, offset, length);
+  }
+
+  /**
+   * Validates that there is no a region at [search] and with the given
+   * [length].
+   */
+  void assertNoRegion(String search, int length) {
+    int offset = findOffset(search);
+    findRegion(offset, length, false);
+  }
+
+  /**
+   * Validates that there is no a region at [search] with any length.
+   */
+  void assertNoRegionAt(String search) {
+    int offset = findOffset(search);
+    findRegion(offset, -1, false);
+  }
+
+  /**
+   * Validates that there is no a region for [search] string.
+   */
+  void assertNoRegionString(String search) {
+    int offset = findOffset(search);
+    int length = search.length;
+    findRegion(offset, length, false);
+  }
+
+  void assertRegionsSorted() {
+    int lastEnd = -1;
+    for (NavigationRegion region in regions) {
+      int offset = region.offset;
+      if (offset < lastEnd) {
+        fail('$lastEnd was expected to be > $offset in\n' + regions.join('\n'));
+      }
+      lastEnd = offset + region.length;
+    }
+  }
+
+  /**
+   * Finds the navigation region with the given [offset] and [length].
+   * If [length] is `-1`, then it is ignored.
+   *
+   * If [exists] is `true`, then fails if such region does not exist.
+   * Otherwise remembers this it into [testRegion].
+   * Also fills [testTargets] with its targets.
+   *
+   * If [exists] is `false`, then fails if such region exists.
+   */
+  void findRegion(int offset, int length, bool exists) {
+    for (NavigationRegion region in regions) {
+      if (region.offset == offset &&
+          (length == -1 || region.length == length)) {
+        if (exists == false) {
+          fail('Not expected to find (offset=$offset; length=$length) in\n'
+              '${regions.join('\n')}');
+        }
+        testRegion = region;
+        testTargetIndexes = region.targets;
+        return;
+      }
+    }
+    if (exists == true) {
+      fail('Expected to find (offset=$offset; length=$length) in\n'
+          '${regions.join('\n')}');
+    }
+  }
+}
+
 @reflectiveTest
 class AnalysisNotificationNavigationTest extends AbstractNavigationTest {
   Future prepareNavigation() {
@@ -295,6 +444,23 @@
     });
   }
 
+  test_inComment() async {
+    addTestFile('''
+class FirstClass {}
+class SecondClass {
+  /**
+   * Return a [FirstClass] object equivalent to this object in every other way.
+   */
+  convert() {
+    return new FirstClass();
+  }
+}
+''');
+    await prepareNavigation();
+    assertHasRegionTarget('FirstClass]', 'FirstClass {');
+    assertHasRegionTarget('FirstClass(', 'FirstClass {');
+  }
+
   test_instanceCreation_implicit() {
     addTestFile('''
 class A {
@@ -638,152 +804,3 @@
     });
   }
 }
-
-class AbstractNavigationTest extends AbstractAnalysisTest {
-  List<NavigationRegion> regions;
-  List<NavigationTarget> targets;
-  List<String> targetFiles;
-
-  NavigationRegion testRegion;
-  List<int> testTargetIndexes;
-  NavigationTarget testTarget;
-
-  /**
-   * Validates that there is a target in [testTargetIndexes] with [file],
-   * at [offset] and with the given [length].
-   */
-  void assertHasFileTarget(String file, int offset, int length) {
-    List<NavigationTarget> testTargets =
-        testTargetIndexes.map((int index) => targets[index]).toList();
-    for (NavigationTarget target in testTargets) {
-      if (targetFiles[target.fileIndex] == file &&
-          target.offset == offset &&
-          target.length == length) {
-        testTarget = target;
-        return;
-      }
-    }
-    fail(
-        'Expected to find target (file=$file; offset=$offset; length=$length) in\n'
-        '${testRegion} in\n' '${testTargets.join('\n')}');
-  }
-
-  void assertHasOperatorRegion(String regionSearch, int regionLength,
-      String targetSearch, int targetLength) {
-    assertHasRegion(regionSearch, regionLength);
-    assertHasTarget(targetSearch, targetLength);
-  }
-
-  /**
-   * Validates that there is a region at the offset of [search] in [testFile].
-   * If [length] is not specified explicitly, then length of an identifier
-   * from [search] is used.
-   */
-  void assertHasRegion(String search, [int length = -1]) {
-    int offset = findOffset(search);
-    if (length == -1) {
-      length = findIdentifierLength(search);
-    }
-    findRegion(offset, length, true);
-  }
-
-  /**
-   * Validates that there is a region at the offset of [search] in [testFile]
-   * with the given [length] or the length of [search].
-   */
-  void assertHasRegionString(String search, [int length = -1]) {
-    int offset = findOffset(search);
-    if (length == -1) {
-      length = search.length;
-    }
-    findRegion(offset, length, true);
-  }
-
-  /**
-   * Validates that there is an identifier region at [regionSearch] with target
-   * at [targetSearch].
-   */
-  void assertHasRegionTarget(String regionSearch, String targetSearch) {
-    assertHasRegion(regionSearch);
-    assertHasTarget(targetSearch);
-  }
-
-  /**
-   * Validates that there is a target in [testTargets]  with [testFile], at the
-   * offset of [search] in [testFile], and with the given [length] or the length
-   * of an leading identifier in [search].
-   */
-  void assertHasTarget(String search, [int length = -1]) {
-    int offset = findOffset(search);
-    if (length == -1) {
-      length = findIdentifierLength(search);
-    }
-    assertHasFileTarget(testFile, offset, length);
-  }
-
-  /**
-   * Validates that there is no a region at [search] and with the given
-   * [length].
-   */
-  void assertNoRegion(String search, int length) {
-    int offset = findOffset(search);
-    findRegion(offset, length, false);
-  }
-
-  /**
-   * Validates that there is no a region at [search] with any length.
-   */
-  void assertNoRegionAt(String search) {
-    int offset = findOffset(search);
-    findRegion(offset, -1, false);
-  }
-
-  /**
-   * Validates that there is no a region for [search] string.
-   */
-  void assertNoRegionString(String search) {
-    int offset = findOffset(search);
-    int length = search.length;
-    findRegion(offset, length, false);
-  }
-
-  void assertRegionsSorted() {
-    int lastEnd = -1;
-    for (NavigationRegion region in regions) {
-      int offset = region.offset;
-      if (offset < lastEnd) {
-        fail('$lastEnd was expected to be > $offset in\n' + regions.join('\n'));
-      }
-      lastEnd = offset + region.length;
-    }
-  }
-
-  /**
-   * Finds the navigation region with the given [offset] and [length].
-   * If [length] is `-1`, then it is ignored.
-   *
-   * If [exists] is `true`, then fails if such region does not exist.
-   * Otherwise remembers this it into [testRegion].
-   * Also fills [testTargets] with its targets.
-   *
-   * If [exists] is `false`, then fails if such region exists.
-   */
-  void findRegion(int offset, int length, bool exists) {
-    for (NavigationRegion region in regions) {
-      if (region.offset == offset &&
-          (length == -1 || region.length == length)) {
-        if (exists == false) {
-          fail('Not expected to find (offset=$offset; length=$length) in\n'
-              '${regions.join('\n')}');
-        }
-        testRegion = region;
-        testTargetIndexes = region.targets;
-        return;
-      }
-    }
-    if (exists == true) {
-      fail('Expected to find (offset=$offset; length=$length) in\n'
-          '${regions.join('\n')}');
-    }
-  }
-}
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index af43b51..d81f338 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -7,12 +7,9 @@
 import 'dart:collection';
 
 import 'package:analysis_server/src/context_manager.dart';
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
-import 'package:analysis_server/uri/resolver_provider.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -55,7 +52,9 @@
    */
   static const String TEST_NAME = 'test';
 
-  TestContextManager manager;
+  ContextManagerImpl manager;
+
+  TestContextManagerCallbacks callbacks;
 
   MemoryResourceProvider resourceProvider;
 
@@ -84,14 +83,40 @@
   void setUp() {
     resourceProvider = new MemoryResourceProvider();
     packageMapProvider = new MockPackageMapProvider();
-    manager = new TestContextManager(
-        resourceProvider, providePackageResolver, packageMapProvider);
+    manager = new ContextManagerImpl(resourceProvider, providePackageResolver,
+        packageMapProvider, InstrumentationService.NULL_SERVICE);
+    callbacks = new TestContextManagerCallbacks(resourceProvider);
+    manager.callbacks = callbacks;
     resourceProvider.newFolder(projPath);
-    AbstractContextManager.ENABLE_PACKAGESPEC_SUPPORT = true;
+    ContextManagerImpl.ENABLE_PACKAGESPEC_SUPPORT = true;
   }
 
   void tearDown() {
-    AbstractContextManager.ENABLE_PACKAGESPEC_SUPPORT = false;
+    ContextManagerImpl.ENABLE_PACKAGESPEC_SUPPORT = false;
+  }
+
+  void test_contextsInAnalysisRoot_nestedContext() {
+    String subProjPath = join(projPath, 'subproj');
+    Folder subProjFolder = resourceProvider.newFolder(subProjPath);
+    resourceProvider.newFile(join(subProjPath, 'pubspec.yaml'), 'contents');
+    String subProjFilePath = join(subProjPath, 'file.dart');
+    resourceProvider.newFile(subProjFilePath, 'contents');
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    // Make sure that there really are contexts for both the main project and
+    // the subproject.
+    Folder projFolder = resourceProvider.getFolder(projPath);
+    ContextInfo projContextInfo = manager.getContextInfoFor(projFolder);
+    expect(projContextInfo, isNotNull);
+    expect(projContextInfo.folder, projFolder);
+    ContextInfo subProjContextInfo = manager.getContextInfoFor(subProjFolder);
+    expect(subProjContextInfo, isNotNull);
+    expect(subProjContextInfo.folder, subProjFolder);
+    expect(projContextInfo.context != subProjContextInfo.context, isTrue);
+    // Check that contextsInAnalysisRoot() works.
+    List<AnalysisContext> contexts = manager.contextsInAnalysisRoot(projFolder);
+    expect(contexts, hasLength(2));
+    expect(contexts, contains(projContextInfo.context));
+    expect(contexts, contains(subProjContextInfo.context));
   }
 
   test_ignoreFilesInPackagesFolder() {
@@ -103,12 +128,12 @@
     resourceProvider.newFile(filePath1, 'contents');
     // "packages" files are ignored initially
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    expect(manager.currentContextFilePaths[projPath], isEmpty);
+    expect(callbacks.currentContextFilePaths[projPath], isEmpty);
     // "packages" files are ignored during watch
     String filePath2 = posix.join(projPath, 'packages', 'file2.dart');
     resourceProvider.newFile(filePath2, 'contents');
     return pumpEventQueue().then((_) {
-      expect(manager.currentContextFilePaths[projPath], isEmpty);
+      expect(callbacks.currentContextFilePaths[projPath], isEmpty);
     });
   }
 
@@ -125,6 +150,21 @@
     expect(manager.isInAnalysisRoot('$excludedFolder/test.dart'), isFalse);
   }
 
+  void test_isInAnalysisRoot_inNestedContext() {
+    String subProjPath = join(projPath, 'subproj');
+    Folder subProjFolder = resourceProvider.newFolder(subProjPath);
+    resourceProvider.newFile(join(subProjPath, 'pubspec.yaml'), 'contents');
+    String subProjFilePath = join(subProjPath, 'file.dart');
+    resourceProvider.newFile(subProjFilePath, 'contents');
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    // Make sure that there really is a context for the subproject.
+    ContextInfo subProjContextInfo = manager.getContextInfoFor(subProjFolder);
+    expect(subProjContextInfo, isNotNull);
+    expect(subProjContextInfo.folder, subProjFolder);
+    // Check that isInAnalysisRoot() works.
+    expect(manager.isInAnalysisRoot(subProjFilePath), isTrue);
+  }
+
   void test_isInAnalysisRoot_inRoot() {
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     expect(manager.isInAnalysisRoot('$projPath/test.dart'), isTrue);
@@ -135,98 +175,17 @@
     expect(manager.isInAnalysisRoot('/test.dart'), isFalse);
   }
 
-  test_refresh_folder_with_packagespec() {
-    // create a context with a .packages file
-    String packagespecFile = posix.join(projPath, '.packages');
-    resourceProvider.newFile(packagespecFile, '');
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    return pumpEventQueue().then((_) {
-      expect(manager.currentContextPaths.toList(), [projPath]);
-      manager.now++;
-      manager.refresh(null);
-      return pumpEventQueue().then((_) {
-        expect(manager.currentContextPaths.toList(), [projPath]);
-        expect(manager.currentContextTimestamps[projPath], manager.now);
-      });
-    });
-  }
-
-  test_refresh_folder_with_packagespec_subfolders() {
-    // Create a folder with no .packages file, containing two subfolders with
-    // .packages files.
-    String subdir1Path = posix.join(projPath, 'subdir1');
-    String subdir2Path = posix.join(projPath, 'subdir2');
-    String packagespec1Path = posix.join(subdir1Path, '.packages');
-    String packagespec2Path = posix.join(subdir2Path, '.packages');
-    resourceProvider.newFile(packagespec1Path, '');
-    resourceProvider.newFile(packagespec2Path, '');
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    return pumpEventQueue().then((_) {
-      expect(manager.currentContextPaths.toSet(),
-          [subdir1Path, subdir2Path, projPath].toSet());
-      manager.now++;
-      manager.refresh(null);
-      return pumpEventQueue().then((_) {
-        expect(manager.currentContextPaths.toSet(),
-            [subdir1Path, subdir2Path, projPath].toSet());
-        expect(manager.currentContextTimestamps[projPath], manager.now);
-        expect(manager.currentContextTimestamps[subdir1Path], manager.now);
-        expect(manager.currentContextTimestamps[subdir2Path], manager.now);
-      });
-    });
-  }
-
-  test_refresh_folder_with_pubspec() {
-    // create a context with a pubspec.yaml file
-    String pubspecPath = posix.join(projPath, 'pubspec.yaml');
-    resourceProvider.newFile(pubspecPath, 'pubspec');
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    return pumpEventQueue().then((_) {
-      expect(manager.currentContextPaths.toList(), [projPath]);
-      manager.now++;
-      manager.refresh(null);
-      return pumpEventQueue().then((_) {
-        expect(manager.currentContextPaths.toList(), [projPath]);
-        expect(manager.currentContextTimestamps[projPath], manager.now);
-      });
-    });
-  }
-
-  test_refresh_folder_with_pubspec_subfolders() {
-    // Create a folder with no pubspec.yaml, containing two subfolders with
-    // pubspec.yaml files.
-    String subdir1Path = posix.join(projPath, 'subdir1');
-    String subdir2Path = posix.join(projPath, 'subdir2');
-    String pubspec1Path = posix.join(subdir1Path, 'pubspec.yaml');
-    String pubspec2Path = posix.join(subdir2Path, 'pubspec.yaml');
-    resourceProvider.newFile(pubspec1Path, 'pubspec');
-    resourceProvider.newFile(pubspec2Path, 'pubspec');
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    return pumpEventQueue().then((_) {
-      expect(manager.currentContextPaths.toSet(),
-          [subdir1Path, subdir2Path, projPath].toSet());
-      manager.now++;
-      manager.refresh(null);
-      return pumpEventQueue().then((_) {
-        expect(manager.currentContextPaths.toSet(),
-            [subdir1Path, subdir2Path, projPath].toSet());
-        expect(manager.currentContextTimestamps[projPath], manager.now);
-        expect(manager.currentContextTimestamps[subdir1Path], manager.now);
-        expect(manager.currentContextTimestamps[subdir2Path], manager.now);
-      });
-    });
-  }
-
   test_path_filter() async {
     // Setup context.
     Folder root = resourceProvider.newFolder(projPath);
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    expect(manager.currentContextFilePaths[projPath], isEmpty);
+    expect(callbacks.currentContextFilePaths[projPath], isEmpty);
     // Set ignore patterns for context.
+    ContextInfo rootInfo = manager.getContextInfoFor(root);
     manager.setIgnorePatternsForContext(
-        root, ['sdk_ext/**', 'lib/ignoreme.dart']);
+        rootInfo, ['sdk_ext/**', 'lib/ignoreme.dart']);
     // Start creating files.
-    newFile([projPath, AbstractContextManager.PUBSPEC_NAME]);
+    newFile([projPath, ContextManagerImpl.PUBSPEC_NAME]);
     String libPath = newFolder([projPath, LIB_NAME]);
     newFile([libPath, 'main.dart']);
     newFile([libPath, 'ignoreme.dart']);
@@ -237,7 +196,8 @@
     // Pump event loop so new files are discovered and added to context.
     await pumpEventQueue();
     // Verify that ignored files were ignored.
-    Map<String, int> fileTimestamps = manager.currentContextFilePaths[projPath];
+    Map<String, int> fileTimestamps =
+        callbacks.currentContextFilePaths[projPath];
     expect(fileTimestamps, isNotEmpty);
     List<String> files = fileTimestamps.keys.toList();
     expect(files.length, equals(1));
@@ -263,13 +223,186 @@
     // Setup context.
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // Verify that analysis options was parsed and the ignore patterns applied.
-    Map<String, int> fileTimestamps = manager.currentContextFilePaths[projPath];
+    Map<String, int> fileTimestamps =
+        callbacks.currentContextFilePaths[projPath];
     expect(fileTimestamps, isNotEmpty);
     List<String> files = fileTimestamps.keys.toList();
     expect(files.length, equals(1));
     expect(files[0], equals('/my/proj/lib/main.dart'));
   }
 
+  test_path_filter_child_contexts_option() async {
+    // Create files.
+    String libPath = newFolder([projPath, LIB_NAME]);
+    newFile([libPath, 'main.dart']);
+    newFile([libPath, 'pubspec.yaml'], r'''
+name: foobar
+''');
+    String otherLibPath = newFolder([projPath, 'other_lib']);
+    newFile([otherLibPath, 'entry.dart']);
+    newFile([otherLibPath, 'pubspec.yaml'], r'''
+name: other_lib
+''');
+    // Setup analysis options file with ignore list that ignores the 'other_lib'
+    // directory by name.
+    newFile([projPath, '.analysis_options'], r'''
+analyzer:
+  exclude:
+    - 'other_lib'
+''');
+    // Setup context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    // Verify that the context in other_lib wasn't created and that the
+    // context in lib was created.
+    var contexts = manager.contextsInAnalysisRoot(
+        resourceProvider.newFolder(projPath));
+    expect(contexts.length, 2);
+    expect(contexts[0].name, equals('/my/proj'));
+    expect(contexts[1].name, equals('/my/proj/lib'));
+  }
+
+  test_path_filter_wildcard_child_contexts_option() async {
+    // Create files.
+    String libPath = newFolder([projPath, LIB_NAME]);
+    newFile([libPath, 'main.dart']);
+    newFile([libPath, 'pubspec.yaml'], r'''
+name: foobar
+''');
+    String otherLibPath = newFolder([projPath, 'other_lib']);
+    newFile([otherLibPath, 'entry.dart']);
+    newFile([otherLibPath, 'pubspec.yaml'], r'''
+name: other_lib
+''');
+    // Setup analysis options file with ignore list that ignores 'other_lib'
+    // and all immediate children.
+    newFile([projPath, '.analysis_options'], r'''
+analyzer:
+  exclude:
+    - 'other_lib/*'
+''');
+    // Setup context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    // Verify that the context in other_lib wasn't created and that the
+    // context in lib was created.
+    var contexts = manager.contextsInAnalysisRoot(
+        resourceProvider.newFolder(projPath));
+    expect(contexts.length, 2);
+    expect(contexts[0].name, equals('/my/proj'));
+    expect(contexts[1].name, equals('/my/proj/lib'));
+  }
+
+  test_path_filter_recursive_wildcard_child_contexts_option() async {
+    // Create files.
+    String libPath = newFolder([projPath, LIB_NAME]);
+    newFile([libPath, 'main.dart']);
+    newFile([libPath, 'pubspec.yaml'], r'''
+  name: foobar
+  ''');
+    String otherLibPath = newFolder([projPath, 'other_lib']);
+    newFile([otherLibPath, 'entry.dart']);
+    newFile([otherLibPath, 'pubspec.yaml'], r'''
+  name: other_lib
+  ''');
+    // Setup analysis options file with ignore list that ignores 'other_lib'
+    // and all descendants.
+    newFile([projPath, '.analysis_options'], r'''
+analyzer:
+  exclude:
+    - 'other_lib/**'
+  ''');
+    // Setup context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    // Verify that the context in other_lib wasn't created and that the
+    // context in lib was created.
+    var contexts = manager.contextsInAnalysisRoot(
+        resourceProvider.newFolder(projPath));
+    expect(contexts.length, 2);
+    expect(contexts[0].name, equals('/my/proj'));
+    expect(contexts[1].name, equals('/my/proj/lib'));
+  }
+
+  test_refresh_folder_with_packagespec() {
+    // create a context with a .packages file
+    String packagespecFile = posix.join(projPath, '.packages');
+    resourceProvider.newFile(packagespecFile, '');
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    return pumpEventQueue().then((_) {
+      expect(callbacks.currentContextPaths.toList(), [projPath]);
+      callbacks.now++;
+      manager.refresh(null);
+      return pumpEventQueue().then((_) {
+        expect(callbacks.currentContextPaths.toList(), [projPath]);
+        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
+      });
+    });
+  }
+
+  test_refresh_folder_with_packagespec_subfolders() {
+    // Create a folder with no .packages file, containing two subfolders with
+    // .packages files.
+    String subdir1Path = posix.join(projPath, 'subdir1');
+    String subdir2Path = posix.join(projPath, 'subdir2');
+    String packagespec1Path = posix.join(subdir1Path, '.packages');
+    String packagespec2Path = posix.join(subdir2Path, '.packages');
+    resourceProvider.newFile(packagespec1Path, '');
+    resourceProvider.newFile(packagespec2Path, '');
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    return pumpEventQueue().then((_) {
+      expect(callbacks.currentContextPaths.toSet(),
+          [subdir1Path, subdir2Path, projPath].toSet());
+      callbacks.now++;
+      manager.refresh(null);
+      return pumpEventQueue().then((_) {
+        expect(callbacks.currentContextPaths.toSet(),
+            [subdir1Path, subdir2Path, projPath].toSet());
+        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
+        expect(callbacks.currentContextTimestamps[subdir1Path], callbacks.now);
+        expect(callbacks.currentContextTimestamps[subdir2Path], callbacks.now);
+      });
+    });
+  }
+
+  test_refresh_folder_with_pubspec() {
+    // create a context with a pubspec.yaml file
+    String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+    resourceProvider.newFile(pubspecPath, 'pubspec');
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    return pumpEventQueue().then((_) {
+      expect(callbacks.currentContextPaths.toList(), [projPath]);
+      callbacks.now++;
+      manager.refresh(null);
+      return pumpEventQueue().then((_) {
+        expect(callbacks.currentContextPaths.toList(), [projPath]);
+        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
+      });
+    });
+  }
+
+  test_refresh_folder_with_pubspec_subfolders() {
+    // Create a folder with no pubspec.yaml, containing two subfolders with
+    // pubspec.yaml files.
+    String subdir1Path = posix.join(projPath, 'subdir1');
+    String subdir2Path = posix.join(projPath, 'subdir2');
+    String pubspec1Path = posix.join(subdir1Path, 'pubspec.yaml');
+    String pubspec2Path = posix.join(subdir2Path, 'pubspec.yaml');
+    resourceProvider.newFile(pubspec1Path, 'pubspec');
+    resourceProvider.newFile(pubspec2Path, 'pubspec');
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    return pumpEventQueue().then((_) {
+      expect(callbacks.currentContextPaths.toSet(),
+          [subdir1Path, subdir2Path, projPath].toSet());
+      callbacks.now++;
+      manager.refresh(null);
+      return pumpEventQueue().then((_) {
+        expect(callbacks.currentContextPaths.toSet(),
+            [subdir1Path, subdir2Path, projPath].toSet());
+        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
+        expect(callbacks.currentContextTimestamps[subdir1Path], callbacks.now);
+        expect(callbacks.currentContextTimestamps[subdir2Path], callbacks.now);
+      });
+    });
+  }
+
   test_refresh_oneContext() {
     // create two contexts with pubspec.yaml files
     String pubspecPath = posix.join(projPath, 'pubspec.yaml');
@@ -283,14 +416,14 @@
     List<String> roots = <String>[projPath, proj2Path];
     manager.setRoots(roots, <String>[], <String, String>{});
     return pumpEventQueue().then((_) {
-      expect(manager.currentContextPaths.toList(), unorderedEquals(roots));
-      int then = manager.now;
-      manager.now++;
+      expect(callbacks.currentContextPaths.toList(), unorderedEquals(roots));
+      int then = callbacks.now;
+      callbacks.now++;
       manager.refresh([resourceProvider.getResource(proj2Path)]);
       return pumpEventQueue().then((_) {
-        expect(manager.currentContextPaths.toList(), unorderedEquals(roots));
-        expect(manager.currentContextTimestamps[projPath], then);
-        expect(manager.currentContextTimestamps[proj2Path], manager.now);
+        expect(callbacks.currentContextPaths.toList(), unorderedEquals(roots));
+        expect(callbacks.currentContextTimestamps[projPath], then);
+        expect(callbacks.currentContextTimestamps[proj2Path], callbacks.now);
       });
     });
   }
@@ -300,7 +433,7 @@
     resourceProvider.newFile(filePath, 'contents');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // verify
-    var filePaths = manager.currentContextFilePaths[projPath];
+    var filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
     List<AnalysisContext> contextsInAnalysisRoot =
@@ -318,7 +451,7 @@
     resourceProvider.newFile(filePath, 'contents');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // verify
-    var filePaths = manager.currentContextFilePaths[projPath];
+    var filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
   }
@@ -328,7 +461,7 @@
     resourceProvider.newDummyLink(filePath);
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // verify
-    var filePaths = manager.currentContextFilePaths[projPath];
+    var filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, isEmpty);
   }
 
@@ -336,9 +469,9 @@
     String examplePath = newFolder([projPath, EXAMPLE_NAME]);
     String libPath = newFolder([projPath, LIB_NAME]);
 
-    newFile([projPath, AbstractContextManager.PACKAGE_SPEC_NAME]);
+    newFile([projPath, ContextManagerImpl.PACKAGE_SPEC_NAME]);
     newFile([libPath, 'main.dart']);
-    newFile([examplePath, AbstractContextManager.PACKAGE_SPEC_NAME]);
+    newFile([examplePath, ContextManagerImpl.PACKAGE_SPEC_NAME]);
     newFile([examplePath, 'example.dart']);
 
     packageMapProvider.packageMap['proj'] =
@@ -346,15 +479,15 @@
 
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
 
-    expect(manager.currentContextPaths, hasLength(2));
+    expect(callbacks.currentContextPaths, hasLength(2));
 
-    expect(manager.currentContextPaths, contains(projPath));
-    Set<Source> projSources = manager.currentContextSources[projPath];
+    expect(callbacks.currentContextPaths, contains(projPath));
+    Set<Source> projSources = callbacks.currentContextSources[projPath];
     expect(projSources, hasLength(1));
     expect(projSources.first.uri.toString(), 'file:///my/proj/lib/main.dart');
 
-    expect(manager.currentContextPaths, contains(examplePath));
-    Set<Source> exampleSources = manager.currentContextSources[examplePath];
+    expect(callbacks.currentContextPaths, contains(examplePath));
+    Set<Source> exampleSources = callbacks.currentContextSources[examplePath];
     expect(exampleSources, hasLength(1));
     expect(exampleSources.first.uri.toString(),
         'file:///my/proj/example/example.dart');
@@ -364,9 +497,9 @@
     String examplePath = newFolder([projPath, EXAMPLE_NAME]);
     String libPath = newFolder([projPath, LIB_NAME]);
 
-    newFile([projPath, AbstractContextManager.PUBSPEC_NAME]);
+    newFile([projPath, ContextManagerImpl.PUBSPEC_NAME]);
     newFile([libPath, 'main.dart']);
-    newFile([examplePath, AbstractContextManager.PUBSPEC_NAME]);
+    newFile([examplePath, ContextManagerImpl.PUBSPEC_NAME]);
     newFile([examplePath, 'example.dart']);
 
     packageMapProvider.packageMap['proj'] =
@@ -374,15 +507,15 @@
 
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
 
-    expect(manager.currentContextPaths, hasLength(2));
+    expect(callbacks.currentContextPaths, hasLength(2));
 
-    expect(manager.currentContextPaths, contains(projPath));
-    Set<Source> projSources = manager.currentContextSources[projPath];
+    expect(callbacks.currentContextPaths, contains(projPath));
+    Set<Source> projSources = callbacks.currentContextSources[projPath];
     expect(projSources, hasLength(1));
     expect(projSources.first.uri.toString(), 'package:proj/main.dart');
 
-    expect(manager.currentContextPaths, contains(examplePath));
-    Set<Source> exampleSources = manager.currentContextSources[examplePath];
+    expect(callbacks.currentContextPaths, contains(examplePath));
+    Set<Source> exampleSources = callbacks.currentContextSources[examplePath];
     expect(exampleSources, hasLength(1));
     expect(exampleSources.first.uri.toString(),
         'file:///my/proj/example/example.dart');
@@ -392,9 +525,9 @@
     packageMapProvider.packageMap = null;
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // verify
-    expect(manager.currentContextPaths, hasLength(1));
-    expect(manager.currentContextPaths, contains(projPath));
-    expect(manager.currentContextFilePaths[projPath], hasLength(0));
+    expect(callbacks.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, contains(projPath));
+    expect(callbacks.currentContextFilePaths[projPath], hasLength(0));
   }
 
   void test_setRoots_addFolderWithPackagespec() {
@@ -409,12 +542,12 @@
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
 
     // verify
-    expect(manager.currentContextPaths, hasLength(1));
-    expect(manager.currentContextPaths, contains(projPath));
-    expect(manager.currentContextFilePaths[projPath], hasLength(1));
+    expect(callbacks.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, contains(projPath));
+    expect(callbacks.currentContextFilePaths[projPath], hasLength(1));
 
     // smoketest resolution
-    SourceFactory sourceFactory = manager.currentContext.sourceFactory;
+    SourceFactory sourceFactory = callbacks.currentContext.sourceFactory;
     Source resolvedSource =
         sourceFactory.resolveUri(source, 'package:unittest/unittest.dart');
     expect(resolvedSource, isNotNull);
@@ -427,9 +560,9 @@
     resourceProvider.newFile(pubspecPath, 'pubspec');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // verify
-    expect(manager.currentContextPaths, hasLength(1));
-    expect(manager.currentContextPaths, contains(projPath));
-    expect(manager.currentContextFilePaths[projPath], hasLength(0));
+    expect(callbacks.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, contains(projPath));
+    expect(callbacks.currentContextFilePaths[projPath], hasLength(0));
   }
 
   void test_setRoots_addFolderWithPubspec_andPackagespec() {
@@ -439,7 +572,7 @@
     resourceProvider.newFile(packagespecPath, '');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // verify
-    manager.assertContextPaths([projPath]);
+    callbacks.assertContextPaths([projPath]);
   }
 
   void test_setRoots_addFolderWithPubspecAndLib() {
@@ -448,7 +581,7 @@
     String srcPath = newFolder([libPath, SRC_NAME]);
     String testPath = newFolder([projPath, TEST_NAME]);
 
-    newFile([projPath, AbstractContextManager.PUBSPEC_NAME]);
+    newFile([projPath, ContextManagerImpl.PUBSPEC_NAME]);
     String appPath = newFile([binPath, 'app.dart']);
     newFile([libPath, 'main.dart']);
     newFile([srcPath, 'internal.dart']);
@@ -458,10 +591,10 @@
         [resourceProvider.getResource(libPath)];
 
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    Set<Source> sources = manager.currentContextSources[projPath];
+    Set<Source> sources = callbacks.currentContextSources[projPath];
 
-    expect(manager.currentContextPaths, hasLength(1));
-    expect(manager.currentContextPaths, contains(projPath));
+    expect(callbacks.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, contains(projPath));
     expect(sources, hasLength(4));
     List<String> uris =
         sources.map((Source source) => source.uri.toString()).toList();
@@ -491,11 +624,11 @@
 
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProjectA, subProjectB]);
+    callbacks.assertContextPaths([root, subProjectA, subProjectB]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProjectA, [subProjectA_file]);
-    manager.assertContextFiles(subProjectB, [subProjectB_file]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
+    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
   }
 
   void test_setRoots_addFolderWithPubspecFolders() {
@@ -519,11 +652,11 @@
     };
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProjectA, subProjectB]);
+    callbacks.assertContextPaths([root, subProjectA, subProjectB]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProjectA, [subProjectA_file]);
-    manager.assertContextFiles(subProjectB, [subProjectB_file]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
+    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
     // verify package maps
     _checkPackageMap(root, isNull);
     _checkPackageMap(
@@ -572,8 +705,8 @@
     resourceProvider.newFile(file2, '// 2');
     // set roots
     manager.setRoots(<String>[project], <String>[file1], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file2]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file2]);
   }
 
   void test_setRoots_exclude_newRoot_withExcludedFolder() {
@@ -588,8 +721,8 @@
     resourceProvider.newFile(fileB, 'library b;');
     // set roots
     manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [fileA]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
   }
 
   void test_setRoots_exclude_sameRoot_addExcludedFile() {
@@ -602,12 +735,12 @@
     resourceProvider.newFile(file2, '// 2');
     // set roots
     manager.setRoots(<String>[project], <String>[], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file1, file2]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1, file2]);
     // exclude "2"
     manager.setRoots(<String>[project], <String>[file2], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file1]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
   }
 
   void test_setRoots_exclude_sameRoot_addExcludedFolder() {
@@ -622,12 +755,12 @@
     resourceProvider.newFile(fileB, 'library b;');
     // initially both "aaa/a" and "bbb/b" are included
     manager.setRoots(<String>[project], <String>[], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [fileA, fileB]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA, fileB]);
     // exclude "bbb/"
     manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [fileA]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
   }
 
   void test_setRoots_exclude_sameRoot_removeExcludedFile() {
@@ -640,12 +773,12 @@
     resourceProvider.newFile(file2, '// 2');
     // set roots
     manager.setRoots(<String>[project], <String>[file2], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file1]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
     // stop excluding "2"
     manager.setRoots(<String>[project], <String>[], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file1, file2]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1, file2]);
   }
 
   void test_setRoots_exclude_sameRoot_removeExcludedFile_inFolder() {
@@ -658,12 +791,12 @@
     resourceProvider.newFile(file2, '// 2');
     // set roots
     manager.setRoots(<String>[project], <String>[file2], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file1]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
     // stop excluding "2"
     manager.setRoots(<String>[project], <String>[], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [file1, file2]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1, file2]);
   }
 
   void test_setRoots_exclude_sameRoot_removeExcludedFolder() {
@@ -678,12 +811,12 @@
     resourceProvider.newFile(fileB, 'library b;');
     // exclude "bbb/"
     manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [fileA]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
     // stop excluding "bbb/"
     manager.setRoots(<String>[project], <String>[], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [fileA, fileB]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA, fileB]);
   }
 
   void test_setRoots_newFolderWithPackageRoot() {
@@ -723,11 +856,11 @@
     packageMapProvider.packageMap = null;
     // add one root - there is a context
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    expect(manager.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, hasLength(1));
     // set empty roots - no contexts
     manager.setRoots(<String>[], <String>[], <String, String>{});
-    expect(manager.currentContextPaths, hasLength(0));
-    expect(manager.currentContextFilePaths, hasLength(0));
+    expect(callbacks.currentContextPaths, hasLength(0));
+    expect(callbacks.currentContextFilePaths, hasLength(0));
   }
 
   void test_setRoots_removeFolderWithPackagespec() {
@@ -736,11 +869,11 @@
     resourceProvider.newFile(pubspecPath, '');
     // add one root - there is a context
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    expect(manager.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, hasLength(1));
     // set empty roots - no contexts
     manager.setRoots(<String>[], <String>[], <String, String>{});
-    expect(manager.currentContextPaths, hasLength(0));
-    expect(manager.currentContextFilePaths, hasLength(0));
+    expect(callbacks.currentContextPaths, hasLength(0));
+    expect(callbacks.currentContextFilePaths, hasLength(0));
   }
 
   void test_setRoots_removeFolderWithPackagespecFolder() {
@@ -765,16 +898,17 @@
     // set roots
     manager.setRoots(
         <String>[projectA, projectB], <String>[], <String, String>{});
-    manager.assertContextPaths([projectA, subProjectA, projectB, subProjectB]);
-    manager.assertContextFiles(projectA, [projectA_file]);
-    manager.assertContextFiles(projectB, [projectB_file]);
-    manager.assertContextFiles(subProjectA, [subProjectA_file]);
-    manager.assertContextFiles(subProjectB, [subProjectB_file]);
+    callbacks
+        .assertContextPaths([projectA, subProjectA, projectB, subProjectB]);
+    callbacks.assertContextFiles(projectA, [projectA_file]);
+    callbacks.assertContextFiles(projectB, [projectB_file]);
+    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
+    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
     // remove "projectB"
     manager.setRoots(<String>[projectA], <String>[], <String, String>{});
-    manager.assertContextPaths([projectA, subProjectA]);
-    manager.assertContextFiles(projectA, [projectA_file]);
-    manager.assertContextFiles(subProjectA, [subProjectA_file]);
+    callbacks.assertContextPaths([projectA, subProjectA]);
+    callbacks.assertContextFiles(projectA, [projectA_file]);
+    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
   }
 
   void test_setRoots_removeFolderWithPubspec() {
@@ -783,11 +917,11 @@
     resourceProvider.newFile(pubspecPath, 'pubspec');
     // add one root - there is a context
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    expect(manager.currentContextPaths, hasLength(1));
+    expect(callbacks.currentContextPaths, hasLength(1));
     // set empty roots - no contexts
     manager.setRoots(<String>[], <String>[], <String, String>{});
-    expect(manager.currentContextPaths, hasLength(0));
-    expect(manager.currentContextFilePaths, hasLength(0));
+    expect(callbacks.currentContextPaths, hasLength(0));
+    expect(callbacks.currentContextFilePaths, hasLength(0));
   }
 
   void test_setRoots_removeFolderWithPubspecFolder() {
@@ -812,16 +946,17 @@
     // set roots
     manager.setRoots(
         <String>[projectA, projectB], <String>[], <String, String>{});
-    manager.assertContextPaths([projectA, subProjectA, projectB, subProjectB]);
-    manager.assertContextFiles(projectA, [projectA_file]);
-    manager.assertContextFiles(projectB, [projectB_file]);
-    manager.assertContextFiles(subProjectA, [subProjectA_file]);
-    manager.assertContextFiles(subProjectB, [subProjectB_file]);
+    callbacks
+        .assertContextPaths([projectA, subProjectA, projectB, subProjectB]);
+    callbacks.assertContextFiles(projectA, [projectA_file]);
+    callbacks.assertContextFiles(projectB, [projectB_file]);
+    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
+    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
     // remove "projectB"
     manager.setRoots(<String>[projectA], <String>[], <String, String>{});
-    manager.assertContextPaths([projectA, subProjectA]);
-    manager.assertContextFiles(projectA, [projectA_file]);
-    manager.assertContextFiles(subProjectA, [subProjectA_file]);
+    callbacks.assertContextPaths([projectA, subProjectA]);
+    callbacks.assertContextFiles(projectA, [projectA_file]);
+    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
   }
 
   void test_setRoots_removePackageRoot() {
@@ -842,7 +977,7 @@
   test_watch_addDummyLink() {
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // empty folder initially
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, isEmpty);
     // add link
     String filePath = posix.join(projPath, 'foo.dart');
@@ -856,7 +991,7 @@
   test_watch_addFile() {
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // empty folder initially
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(0));
     // add file
     String filePath = posix.join(projPath, 'foo.dart');
@@ -879,20 +1014,20 @@
     resourceProvider.newFile(fileA, 'library a;');
     // set roots
     manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
-    manager.assertContextPaths([project]);
-    manager.assertContextFiles(project, [fileA]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
     // add a file, ignored as excluded
     resourceProvider.newFile(fileB, 'library b;');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([project]);
-      manager.assertContextFiles(project, [fileA]);
+      callbacks.assertContextPaths([project]);
+      callbacks.assertContextFiles(project, [fileA]);
     });
   }
 
   test_watch_addFileInSubfolder() {
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // empty folder initially
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(0));
     // add file in subfolder
     String filePath = posix.join(projPath, 'foo', 'bar.dart');
@@ -913,14 +1048,14 @@
     resourceProvider.newFile(rootFile, 'library root;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root]);
+    callbacks.assertContextPaths([root]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(root, [rootFile]);
     // add packagespec - still just one root
     resourceProvider.newFile(rootPackagespec, '');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root]);
-      manager.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextPaths([root]);
+      callbacks.assertContextFiles(root, [rootFile]);
       // TODO(pquitslund): verify that a new source factory is created --
       // likely this will need to happen in a corresponding ServerContextManagerTest.
     });
@@ -938,15 +1073,15 @@
     resourceProvider.newFile(subFile, 'library a;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root]);
+    callbacks.assertContextPaths([root]);
     // verify files
-    manager.assertContextFiles(root, [rootFile, subFile]);
+    callbacks.assertContextFiles(root, [rootFile, subFile]);
     // add .packages
     resourceProvider.newFile(subPubspec, '');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root, subProject]);
-      manager.assertContextFiles(root, [rootFile]);
-      manager.assertContextFiles(subProject, [subFile]);
+      callbacks.assertContextPaths([root, subProject]);
+      callbacks.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextFiles(subProject, [subFile]);
     });
   }
 
@@ -964,15 +1099,15 @@
     resourceProvider.newFile(subFile, 'library sub;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
+    callbacks.assertContextPaths([root, subProject]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProject, [subFile]);
     // add pubspec - ignore, because is already in a packagespec-based context
     resourceProvider.newFile(subSubPubspec, '');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root, subProject]);
-      manager.assertContextFiles(root, [rootFile]);
-      manager.assertContextFiles(subProject, [subFile]);
+      callbacks.assertContextPaths([root, subProject]);
+      callbacks.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextFiles(subProject, [subFile]);
     });
   }
 
@@ -990,18 +1125,18 @@
     resourceProvider.newFile(subFile, 'library a;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
+    callbacks.assertContextPaths([root, subProject]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProject, [subFile]);
 
     // add .packages
     resourceProvider.newFile(subPackagespec, '');
     return pumpEventQueue().then((_) {
       // Should NOT create another context.
-      manager.assertContextPaths([root, subProject]);
-      manager.assertContextFiles(root, [rootFile]);
-      manager.assertContextFiles(subProject, [subFile]);
+      callbacks.assertContextPaths([root, subProject]);
+      callbacks.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextFiles(subProject, [subFile]);
     });
   }
 
@@ -1014,14 +1149,14 @@
     resourceProvider.newFile(rootFile, 'library root;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root]);
+    callbacks.assertContextPaths([root]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(root, [rootFile]);
     // add pubspec - still just one root
     resourceProvider.newFile(rootPubspec, 'pubspec');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root]);
-      manager.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextPaths([root]);
+      callbacks.assertContextFiles(root, [rootFile]);
     });
   }
 
@@ -1037,15 +1172,15 @@
     resourceProvider.newFile(subFile, 'library a;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root]);
+    callbacks.assertContextPaths([root]);
     // verify files
-    manager.assertContextFiles(root, [rootFile, subFile]);
+    callbacks.assertContextFiles(root, [rootFile, subFile]);
     // add pubspec
     resourceProvider.newFile(subPubspec, 'pubspec');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root, subProject]);
-      manager.assertContextFiles(root, [rootFile]);
-      manager.assertContextFiles(subProject, [subFile]);
+      callbacks.assertContextPaths([root, subProject]);
+      callbacks.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextFiles(subProject, [subFile]);
     });
   }
 
@@ -1063,15 +1198,15 @@
     resourceProvider.newFile(subFile, 'library sub;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
+    callbacks.assertContextPaths([root, subProject]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProject, [subFile]);
     // add pubspec - ignore, because is already in a pubspec-based context
     resourceProvider.newFile(subSubPubspec, 'pubspec');
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root, subProject]);
-      manager.assertContextFiles(root, [rootFile]);
-      manager.assertContextFiles(subProject, [subFile]);
+      callbacks.assertContextPaths([root, subProject]);
+      callbacks.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextFiles(subProject, [subFile]);
     });
   }
 
@@ -1082,7 +1217,7 @@
     Folder projFolder = file.parent;
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // the file was added
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
     expect(file.exists, isTrue);
@@ -1103,7 +1238,7 @@
     Folder projFolder = file.parent;
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // the file was added
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
     expect(file.exists, isTrue);
@@ -1127,13 +1262,13 @@
     resourceProvider.newFile(rootFile, 'library root;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root]);
-    manager.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextPaths([root]);
+    callbacks.assertContextFiles(root, [rootFile]);
     // delete the pubspec
     resourceProvider.deleteFile(rootPubspec);
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root]);
-      manager.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextPaths([root]);
+      callbacks.assertContextFiles(root, [rootFile]);
     });
   }
 
@@ -1150,15 +1285,15 @@
     resourceProvider.newFile(subFile, 'library a;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
+    callbacks.assertContextPaths([root, subProject]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProject, [subFile]);
     // delete the pubspec
     resourceProvider.deleteFile(subPubspec);
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root]);
-      manager.assertContextFiles(root, [rootFile, subFile]);
+      callbacks.assertContextPaths([root]);
+      callbacks.assertContextFiles(root, [rootFile, subFile]);
     });
   }
 
@@ -1177,16 +1312,16 @@
     resourceProvider.newFile(subFile, 'library a;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
+    callbacks.assertContextPaths([root, subProject]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProject, [subFile]);
     // delete the packagespec
     resourceProvider.deleteFile(subPackagespec);
     return pumpEventQueue().then((_) {
       // Should NOT merge
-      manager.assertContextPaths([root, subProject]);
-      manager.assertContextFiles(subProject, [subFile]);
+      callbacks.assertContextPaths([root, subProject]);
+      callbacks.assertContextFiles(subProject, [subFile]);
     });
   }
 
@@ -1200,13 +1335,13 @@
     resourceProvider.newFile(rootFile, 'library root;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root]);
-    manager.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextPaths([root]);
+    callbacks.assertContextFiles(root, [rootFile]);
     // delete the pubspec
     resourceProvider.deleteFile(rootPubspec);
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root]);
-      manager.assertContextFiles(root, [rootFile]);
+      callbacks.assertContextPaths([root]);
+      callbacks.assertContextFiles(root, [rootFile]);
     });
   }
 
@@ -1223,15 +1358,15 @@
     resourceProvider.newFile(subFile, 'library a;');
     // set roots
     manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
+    callbacks.assertContextPaths([root, subProject]);
     // verify files
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
+    callbacks.assertContextFiles(root, [rootFile]);
+    callbacks.assertContextFiles(subProject, [subFile]);
     // delete the pubspec
     resourceProvider.deleteFile(subPubspec);
     return pumpEventQueue().then((_) {
-      manager.assertContextPaths([root]);
-      manager.assertContextFiles(root, [rootFile, subFile]);
+      callbacks.assertContextPaths([root]);
+      callbacks.assertContextFiles(root, [rootFile, subFile]);
     });
   }
 
@@ -1241,15 +1376,15 @@
     resourceProvider.newFile(filePath, 'contents');
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     // the file was added
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
-    expect(filePaths[filePath], equals(manager.now));
+    expect(filePaths[filePath], equals(callbacks.now));
     // update the file
-    manager.now++;
+    callbacks.now++;
     resourceProvider.modifyFile(filePath, 'new contents');
     return pumpEventQueue().then((_) {
-      return expect(filePaths[filePath], equals(manager.now));
+      return expect(filePaths[filePath], equals(callbacks.now));
     });
   }
 
@@ -1302,70 +1437,6 @@
     });
   }
 
-  test_watch_modifyPackageMapDependency_outsideProject() {
-    // create a dependency file
-    String dependencyPath = '/my/other/dep';
-    resourceProvider.newFile(dependencyPath, 'contents');
-    packageMapProvider.dependencies.add(dependencyPath);
-    // create a Dart file
-    String dartFilePath = posix.join(projPath, 'main.dart');
-    resourceProvider.newFile(dartFilePath, 'contents');
-    // the created context has the expected empty package map
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    _checkPackageMap(projPath, isEmpty);
-    // configure package map
-    String packagePath = '/package/foo';
-    resourceProvider.newFolder(packagePath);
-    packageMapProvider.packageMap = {'foo': projPath};
-    // Changing a .dart file in the project shouldn't cause a new
-    // package map to be picked up.
-    resourceProvider.modifyFile(dartFilePath, 'new contents');
-    return pumpEventQueue().then((_) {
-      _checkPackageMap(projPath, isEmpty);
-      // However, changing the package map dependency should.
-      resourceProvider.modifyFile(dependencyPath, 'new contents');
-      return pumpEventQueue().then((_) {
-        _checkPackageMap(projPath, equals(packageMapProvider.packageMap));
-      });
-    });
-  }
-
-  test_watch_modifyPackageMapDependency_redundantly() async {
-    // Create two dependency files
-    String dependencyPath1 = posix.join(projPath, 'dep1');
-    String dependencyPath2 = posix.join(projPath, 'dep2');
-    resourceProvider.newFile(dependencyPath1, 'contents');
-    resourceProvider.newFile(dependencyPath2, 'contents');
-    packageMapProvider.dependencies.add(dependencyPath1);
-    packageMapProvider.dependencies.add(dependencyPath2);
-    // Create a dart file
-    String dartFilePath = posix.join(projPath, 'main.dart');
-    resourceProvider.newFile(dartFilePath, 'contents');
-    // Verify that the created context has the expected empty package map.
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    _checkPackageMap(projPath, isEmpty);
-    expect(packageMapProvider.computeCount, 1);
-    // Set up a different package map
-    String packagePath = '/package/foo';
-    resourceProvider.newFolder(packagePath);
-    packageMapProvider.packageMap = {'foo': projPath};
-    // Change both dependencies.
-    resourceProvider.modifyFile(dependencyPath1, 'new contents');
-    resourceProvider.modifyFile(dependencyPath2, 'new contents');
-    // Arrange for the next call to computePackageMap to return the correct
-    // timestamps for the dependencies.
-    packageMapProvider.modificationTimes = <String, int>{};
-    for (String path in [dependencyPath1, dependencyPath2]) {
-      File resource = resourceProvider.getResource(path);
-      packageMapProvider.modificationTimes[path] = resource.modificationStamp;
-    }
-    // This should cause the new package map to be picked up, by executing
-    // computePackageMap just one additional time.
-    await pumpEventQueue();
-    _checkPackageMap(projPath, equals(packageMapProvider.packageMap));
-    expect(packageMapProvider.computeCount, 2);
-  }
-
   test_watch_modifyPackagespec() {
     String packagesPath = '$projPath/.packages';
     String filePath = '$projPath/bin/main.dart';
@@ -1375,18 +1446,18 @@
 
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
 
-    Map<String, int> filePaths = manager.currentContextFilePaths[projPath];
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
     expect(filePaths, hasLength(1));
     expect(filePaths, contains(filePath));
-    Packages packages = manager.currentContextPackagespecs[projPath];
+    Packages packages = callbacks.currentContextDispositions[projPath].packages;
     expect(packages.packages, isEmpty);
 
     // update .packages
-    manager.now++;
+    callbacks.now++;
     resourceProvider.modifyFile(packagesPath, 'main:./lib/');
     return pumpEventQueue().then((_) {
       // verify new package info
-      packages = manager.currentContextPackagespecs[projPath];
+      packages = callbacks.currentContextDispositions[projPath].packages;
       expect(packages.packages, unorderedEquals(['main']));
     });
   }
@@ -1396,9 +1467,9 @@
    * using a package map matching [expectation].
    */
   void _checkPackageMap(String path, expectation) {
-    UriResolver resolver = manager.currentContextPackageUriResolvers[path];
+    FolderDisposition disposition = callbacks.currentContextDispositions[path];
     Map<String, List<Folder>> packageMap =
-        resolver is PackageMapUriResolver ? resolver.packageMap : null;
+        disposition is PackageMapDisposition ? disposition.packageMap : null;
     expect(packageMap, expectation);
   }
 
@@ -1407,14 +1478,14 @@
    * using a package root maching [expectation].
    */
   void _checkPackageRoot(String path, expectation) {
-    UriResolver resolver = manager.currentContextPackageUriResolvers[path];
-    expect(resolver, new isInstanceOf<PackageUriResolver>());
-    PackageUriResolver packageUriResolver = resolver;
-    expect(packageUriResolver.packagesDirectory_forTesting, expectation);
+    FolderDisposition disposition = callbacks.currentContextDispositions[path];
+    expect(disposition.packageRoot, expectation);
+    // TODO(paulberry): we should also verify that the package map itself is
+    // correct.  See dartbug.com/23909.
   }
 }
 
-class TestContextManager extends AbstractContextManager {
+class TestContextManagerCallbacks extends ContextManagerCallbacks {
   /**
    * Source of timestamps stored in [currentContextFilePaths].
    */
@@ -1444,21 +1515,17 @@
   };
 
   /**
-   * Map from context to package URI resolver.
+   * Map from context to folder disposition.
    */
-  final Map<String, UriResolver> currentContextPackageUriResolvers =
-      <String, UriResolver>{};
+  final Map<String, FolderDisposition> currentContextDispositions =
+      <String, FolderDisposition>{};
 
   /**
-   * Map from context to packages object.
+   * Resource provider used for this test.
    */
-  final Map<String, Packages> currentContextPackagespecs = <String, Packages>{};
+  final ResourceProvider resourceProvider;
 
-  TestContextManager(MemoryResourceProvider resourceProvider,
-      ResolverProvider packageResolverProvider,
-      OptimizingPubPackageMapProvider packageMapProvider)
-      : super(resourceProvider, packageResolverProvider, packageMapProvider,
-          InstrumentationService.NULL_SERVICE);
+  TestContextManagerCallbacks(this.resourceProvider);
 
   /**
    * Iterable of the paths to contexts that currently exist.
@@ -1466,21 +1533,18 @@
   Iterable<String> get currentContextPaths => currentContextTimestamps.keys;
 
   @override
-  AnalysisContext addContext(
-      Folder folder, UriResolver packageUriResolver, Packages packages) {
+  AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
     String path = folder.path;
     expect(currentContextPaths, isNot(contains(path)));
     currentContextTimestamps[path] = now;
     currentContextFilePaths[path] = <String, int>{};
     currentContextSources[path] = new HashSet<Source>();
-    currentContextPackageUriResolvers[path] = packageUriResolver;
-    currentContextPackagespecs[path] = packages;
+    currentContextDispositions[path] = disposition;
     currentContext = AnalysisEngine.instance.createAnalysisContext();
     List<UriResolver> resolvers = [new FileUriResolver()];
-    if (packageUriResolver != null) {
-      resolvers.add(packageUriResolver);
-    }
-    currentContext.sourceFactory = new SourceFactory(resolvers, packages);
+    resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
+    currentContext.sourceFactory =
+        new SourceFactory(resolvers, disposition.packages);
     return currentContext;
   }
 
@@ -1517,13 +1581,13 @@
   }
 
   @override
-  void removeContext(Folder folder) {
+  void removeContext(Folder folder, List<String> flushedFiles) {
     String path = folder.path;
     expect(currentContextPaths, contains(path));
     currentContextTimestamps.remove(path);
     currentContextFilePaths.remove(path);
     currentContextSources.remove(path);
-    currentContextPackageUriResolvers.remove(path);
+    currentContextDispositions.remove(path);
   }
 
   @override
@@ -1542,9 +1606,8 @@
 
   @override
   void updateContextPackageUriResolver(
-      Folder contextFolder, UriResolver packageUriResolver, Packages packages) {
-    currentContextPackageUriResolvers[contextFolder.path] = packageUriResolver;
-    currentContextPackagespecs[contextFolder.path] = packages;
+      Folder contextFolder, FolderDisposition disposition) {
+    currentContextDispositions[contextFolder.path] = disposition;
   }
 }
 
@@ -1564,7 +1627,7 @@
   TestUriResolver(this.uriMap);
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     return uriMap[uri];
   }
 }
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 63cd20f..08916ce 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -21,9 +21,9 @@
 import 'package:analysis_server/src/services/index/index.dart' show Index;
 import 'package:analysis_server/src/services/index/local_memory_index.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -657,7 +657,7 @@
 
   Test_AnalysisServer(ServerCommunicationChannel channel,
       ResourceProvider resourceProvider,
-      OptimizingPubPackageMapProvider packageMapProvider, Index index,
+      PubPackageMapProvider packageMapProvider, Index index,
       ServerPlugin serverPlugin, AnalysisServerOptions analysisServerOptions,
       DartSdk defaultSdk, InstrumentationService instrumentationService)
       : super(channel, resourceProvider, packageMapProvider, index,
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index 8fa9234..2ff54e1 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -8,6 +8,7 @@
 
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domain_execution.dart';
 import 'package:analysis_server/src/plugin/server_plugin.dart';
 import 'package:analysis_server/src/protocol.dart';
@@ -225,7 +226,7 @@
       when(context.getLibrariesReferencedFromHtml(anyObject))
           .thenReturn([source6, source7]);
 
-      ServerContextManager manager = new ServerContextManagerMock();
+      ContextManager manager = new ServerContextManagerMock();
       when(manager.isInAnalysisRoot(anyString)).thenReturn(true);
 
       AnalysisServer server = new AnalysisServerMock();
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
new file mode 100644
index 0000000..e4402ef
--- /dev/null
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.edit.organize_directives;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/edit/edit_domain.dart';
+import 'package:analysis_server/src/protocol.dart';
+import 'package:plugin/manager.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart' hide ERROR;
+
+import '../analysis_abstract.dart';
+import '../mocks.dart';
+
+main() {
+  groupSep = ' | ';
+  defineReflectiveTests(OrganizeDirectivesTest);
+}
+
+@reflectiveTest
+class OrganizeDirectivesTest extends AbstractAnalysisTest {
+  SourceFileEdit fileEdit;
+
+  @override
+  void setUp() {
+    super.setUp();
+    createProject();
+    ExtensionManager manager = new ExtensionManager();
+    manager.processPlugins([server.serverPlugin]);
+    handler = new EditDomainHandler(server);
+  }
+
+  Future test_BAD_doesNotExist() async {
+    await waitForTasksFinished();
+    Request request =
+        new EditOrganizeDirectivesParams('/no/such/file.dart').toRequest('0');
+    Response response = handler.handleRequest(request);
+    expect(
+        response, isResponseFailure('0', RequestErrorCode.FILE_NOT_ANALYZED));
+  }
+
+  Future test_BAD_hasParseError() async {
+    addTestFile('''
+import 'dart:async'
+
+main() {}
+''');
+    await waitForTasksFinished();
+    Request request = new EditOrganizeDirectivesParams(testFile).toRequest('0');
+    Response response = handler.handleRequest(request);
+    expect(response,
+        isResponseFailure('0', RequestErrorCode.ORGANIZE_DIRECTIVES_ERROR));
+  }
+
+  Future test_BAD_notDartFile() async {
+    await waitForTasksFinished();
+    Request request =
+        new EditOrganizeDirectivesParams('/not-a-Dart-file.txt').toRequest('0');
+    Response response = handler.handleRequest(request);
+    expect(
+        response, isResponseFailure('0', RequestErrorCode.FILE_NOT_ANALYZED));
+  }
+
+  Future test_OK_remove_unresolvedDirectives() {
+    addFile('$testFolder/existing_part1.dart', 'part of lib;');
+    addFile('$testFolder/existing_part2.dart', 'part of lib;');
+    addTestFile('''
+library lib;
+
+export 'dart:noSuchExportSdkLibrary';
+export 'dart:async';
+export 'package:noSuchExportPackage/andLib.dart';
+export 'dart:math';
+
+import 'dart:async';
+import 'dart:noSuchImportSdkLibrary';
+import 'dart:math';
+import 'package:noSuchImportPackage/andLib.dart';
+
+part 'existing_part1.dart';
+part 'no_such_part.dart';
+part 'existing_part2.dart';
+
+main(Future f) {
+  print(PI);
+}
+''');
+    return _assertOrganized(r'''
+library lib;
+
+import 'dart:async';
+import 'dart:math';
+
+export 'dart:async';
+export 'dart:math';
+
+part 'existing_part1.dart';
+part 'existing_part2.dart';
+
+main(Future f) {
+  print(PI);
+}
+''');
+  }
+
+  Future test_OK_remove_unusedImports() {
+    addTestFile('''
+library lib;
+
+import 'dart:async';
+import 'dart:math';
+import 'dart:convert';
+import 'dart:collection';
+
+main() {
+  print(PI);
+  new HashMap();
+}
+''');
+    return _assertOrganized(r'''
+library lib;
+
+import 'dart:collection';
+import 'dart:math';
+
+main() {
+  print(PI);
+  new HashMap();
+}
+''');
+  }
+
+  Future _assertOrganized(String expectedCode) async {
+    await waitForTasksFinished();
+    _requestOrganize();
+    String resultCode = SourceEdit.applySequence(testCode, fileEdit.edits);
+    expect(resultCode, expectedCode);
+  }
+
+  void _requestOrganize() {
+    Request request = new EditOrganizeDirectivesParams(testFile).toRequest('0');
+    Response response = handleSuccessfulRequest(request);
+    var result = new EditOrganizeDirectivesResult.fromResponse(response);
+    fileEdit = result.edit;
+  }
+}
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index 6aa638c..194baa9 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -33,38 +33,35 @@
     handler = new EditDomainHandler(server);
   }
 
-  Future test_BAD_doesNotExist() {
-    return waitForTasksFinished().then((_) {
-      Request request =
-          new EditSortMembersParams('/no/such/file.dart').toRequest('0');
-      Response response = handler.handleRequest(request);
-      expect(response,
-          isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_INVALID_FILE));
-    });
+  Future test_BAD_doesNotExist() async {
+    await waitForTasksFinished();
+    Request request =
+        new EditSortMembersParams('/no/such/file.dart').toRequest('0');
+    Response response = handler.handleRequest(request);
+    expect(response,
+        isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_INVALID_FILE));
   }
 
-  Future test_BAD_hasParseError() {
+  Future test_BAD_hasParseError() async {
     addTestFile('''
 main() {
   print()
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      Request request = new EditSortMembersParams(testFile).toRequest('0');
-      Response response = handler.handleRequest(request);
-      expect(response,
-          isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_PARSE_ERRORS));
-    });
+    await waitForTasksFinished();
+    Request request = new EditSortMembersParams(testFile).toRequest('0');
+    Response response = handler.handleRequest(request);
+    expect(response,
+        isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_PARSE_ERRORS));
   }
 
-  Future test_BAD_notDartFile() {
-    return waitForTasksFinished().then((_) {
-      Request request =
-          new EditSortMembersParams('/not-a-Dart-file.txt').toRequest('0');
-      Response response = handler.handleRequest(request);
-      expect(response,
-          isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_INVALID_FILE));
-    });
+  Future test_BAD_notDartFile() async {
+    await waitForTasksFinished();
+    Request request =
+        new EditSortMembersParams('/not-a-Dart-file.txt').toRequest('0');
+    Response response = handler.handleRequest(request);
+    expect(response,
+        isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_INVALID_FILE));
   }
 
   Future test_OK_classMembers_method() {
@@ -148,12 +145,11 @@
 ''');
   }
 
-  Future _assertSorted(String expectedCode) {
-    return waitForTasksFinished().then((_) {
-      _requestSort();
-      String resultCode = SourceEdit.applySequence(testCode, fileEdit.edits);
-      expect(resultCode, expectedCode);
-    });
+  Future _assertSorted(String expectedCode) async {
+    await waitForTasksFinished();
+    _requestSort();
+    String resultCode = SourceEdit.applySequence(testCode, fileEdit.edits);
+    expect(resultCode, expectedCode);
   }
 
   void _requestSort() {
diff --git a/pkg/analysis_server/test/edit/test_all.dart b/pkg/analysis_server/test/edit/test_all.dart
index 40e83f1..e9a9ea1 100644
--- a/pkg/analysis_server/test/edit/test_all.dart
+++ b/pkg/analysis_server/test/edit/test_all.dart
@@ -9,6 +9,7 @@
 import 'assists_test.dart' as assists_test;
 import 'fixes_test.dart' as fixes_test;
 import 'format_test.dart' as format_test;
+import 'organize_directives_test.dart' as organize_directives_test;
 import 'refactoring_test.dart' as refactoring_test;
 import 'sort_members_test.dart' as sort_members_test;
 
@@ -21,6 +22,7 @@
     assists_test.main();
     fixes_test.main();
     format_test.main();
+    organize_directives_test.main();
     refactoring_test.main();
     sort_members_test.main();
   });
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index 4da1b0c..8f3915e 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -1390,6 +1390,39 @@
   }
 
   /**
+   * Organizes all of the directives - removes unused imports and sorts
+   * directives of the given Dart file according to the Dart Style Guide.
+   *
+   * If a request is made for a file that does not exist, does not belong to an
+   * analysis root or is not a Dart file, FILE_NOT_ANALYZED will be generated.
+   *
+   * If directives of the Dart file cannot be organized, for example because it
+   * has scan or parse errors, or by other reasons, ORGANIZE_DIRECTIVES_ERROR
+   * will be generated. The message will provide datails about the reason.
+   *
+   * Parameters
+   *
+   * file ( FilePath )
+   *
+   *   The Dart file to organize directives in.
+   *
+   * Returns
+   *
+   * edit ( SourceFileEdit )
+   *
+   *   The file edit that is to be applied to the given file to effect the
+   *   organizing.
+   */
+  Future<EditOrganizeDirectivesResult> sendEditOrganizeDirectives(String file) {
+    var params = new EditOrganizeDirectivesParams(file).toJson();
+    return server.send("edit.organizeDirectives", params)
+        .then((result) {
+      ResponseDecoder decoder = new ResponseDecoder(null);
+      return new EditOrganizeDirectivesResult.fromJson(decoder, 'result', result);
+    });
+  }
+
+  /**
    * Create an execution context for the executable file with the given path.
    * The context that is created will persist until execution.deleteContext is
    * used to delete it. Clients, therefore, are responsible for managing the
diff --git a/pkg/analysis_server/test/integration/integration_tests.dart b/pkg/analysis_server/test/integration/integration_tests.dart
index f46b338..3345554 100644
--- a/pkg/analysis_server/test/integration/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/integration_tests.dart
@@ -16,6 +16,7 @@
 
 import 'integration_test_methods.dart';
 import 'protocol_matchers.dart';
+import 'package:analysis_server/src/server/driver.dart' as analysisServer;
 
 const Matcher isBool = const isInstanceOf<bool>('bool');
 
@@ -590,7 +591,8 @@
    * "--pause-isolates-on-exit", allowing the observatory to be used.
    */
   Future start({bool debugServer: false, int diagnosticPort,
-      bool profileServer: false, bool useAnalysisHighlight2: false}) {
+      bool profileServer: false, bool newTaskModel: false,
+      bool useAnalysisHighlight2: false}) {
     if (_process != null) {
       throw new Exception('Process already started');
     }
@@ -619,6 +621,9 @@
     if (useAnalysisHighlight2) {
       arguments.add('--useAnalysisHighlight2');
     }
+    if (newTaskModel) {
+      arguments.add('--${analysisServer.Driver.ENABLE_NEW_TASK_MODEL}');
+    }
     return Process.start(dartBinary, arguments).then((Process process) {
       _process = process;
       process.exitCode.then((int code) {
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 0a5ae19..24cc21e 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -853,6 +853,30 @@
   }));
 
 /**
+ * edit.organizeDirectives params
+ *
+ * {
+ *   "file": FilePath
+ * }
+ */
+final Matcher isEditOrganizeDirectivesParams = new LazyMatcher(() => new MatchesJsonObject(
+  "edit.organizeDirectives params", {
+    "file": isFilePath
+  }));
+
+/**
+ * edit.organizeDirectives result
+ *
+ * {
+ *   "edit": SourceFileEdit
+ * }
+ */
+final Matcher isEditOrganizeDirectivesResult = new LazyMatcher(() => new MatchesJsonObject(
+  "edit.organizeDirectives result", {
+    "edit": isSourceFileEdit
+  }));
+
+/**
  * execution.createContext params
  *
  * {
@@ -1936,6 +1960,7 @@
  *
  * enum {
  *   CONTENT_MODIFIED
+ *   FILE_NOT_ANALYZED
  *   FORMAT_INVALID_FILE
  *   FORMAT_WITH_ERRORS
  *   GET_ERRORS_INVALID_FILE
@@ -1946,6 +1971,7 @@
  *   INVALID_PARAMETER
  *   INVALID_REQUEST
  *   NO_INDEX_GENERATED
+ *   ORGANIZE_DIRECTIVES_ERROR
  *   REFACTORING_REQUEST_CANCELLED
  *   SERVER_ALREADY_STARTED
  *   SERVER_ERROR
@@ -1959,6 +1985,7 @@
  */
 final Matcher isRequestErrorCode = new MatchesEnum("RequestErrorCode", [
   "CONTENT_MODIFIED",
+  "FILE_NOT_ANALYZED",
   "FORMAT_INVALID_FILE",
   "FORMAT_WITH_ERRORS",
   "GET_ERRORS_INVALID_FILE",
@@ -1969,6 +1996,7 @@
   "INVALID_PARAMETER",
   "INVALID_REQUEST",
   "NO_INDEX_GENERATED",
+  "ORGANIZE_DIRECTIVES_ERROR",
   "REFACTORING_REQUEST_CANCELLED",
   "SERVER_ALREADY_STARTED",
   "SERVER_ERROR",
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 1aa8f47..3358b47 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -4,20 +4,20 @@
 
 library mocks;
 
-@MirrorsUsed(targets: 'mocks', override: '*')
-import 'dart:mirrors';
 import 'dart:async';
 import 'dart:io';
+@MirrorsUsed(targets: 'mocks', override: '*')
+import 'dart:mirrors';
 
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/channel/channel.dart';
 import 'package:analysis_server/src/operation/operation.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart';
 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind;
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
 import 'package:analyzer/file_system/file_system.dart' as resource;
 import 'package:analyzer/file_system/memory_file_system.dart' as resource;
 import 'package:analyzer/source/package_map_provider.dart';
+import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -152,7 +152,7 @@
 /**
  * A mock [PackageMapProvider].
  */
-class MockPackageMapProvider implements OptimizingPubPackageMapProvider {
+class MockPackageMapProvider implements PubPackageMapProvider {
   /**
    * Package map that will be returned by the next call to [computePackageMap].
    */
@@ -170,36 +170,17 @@
   Set<String> dependencies = new Set<String>();
 
   /**
-   * Modification times that will be returned by the next call to
-   * [computePackageMap].  This will be filtered to include only those paths
-   * mentioned in the `dependencies` field of [computePackageMap]'s
-   * `previousInfo` argument.
-   */
-  Map<String, int> modificationTimes = <String, int>{};
-
-  /**
    * Number of times [computePackageMap] has been called.
    */
   int computeCount = 0;
 
   @override
-  OptimizingPubPackageMapInfo computePackageMap(resource.Folder folder,
-      [OptimizingPubPackageMapInfo previousInfo]) {
+  PackageMapInfo computePackageMap(resource.Folder folder) {
     ++computeCount;
-    Map<String, int> filteredModificationTimes = <String, int>{};
-    if (previousInfo != null) {
-      for (String dependency in previousInfo.dependencies) {
-        if (modificationTimes.containsKey(dependency)) {
-          filteredModificationTimes[dependency] = modificationTimes[dependency];
-        }
-      }
-    }
     if (packageMaps != null) {
-      return new OptimizingPubPackageMapInfo(
-          packageMaps[folder.path], dependencies, filteredModificationTimes);
+      return new PackageMapInfo(packageMaps[folder.path], dependencies);
     }
-    return new OptimizingPubPackageMapInfo(
-        packageMap, dependencies, filteredModificationTimes);
+    return new PackageMapInfo(packageMap, dependencies);
   }
 
   noSuchMethod(Invocation invocation) {
diff --git a/pkg/analysis_server/test/operation/operation_queue_test.dart b/pkg/analysis_server/test/operation/operation_queue_test.dart
index 71569e8..47f0bcf 100644
--- a/pkg/analysis_server/test/operation/operation_queue_test.dart
+++ b/pkg/analysis_server/test/operation/operation_queue_test.dart
@@ -5,6 +5,7 @@
 library test.operation.queue;
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/operation/operation.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart';
 import 'package:analysis_server/src/operation/operation_queue.dart';
@@ -39,7 +40,6 @@
 }
 
 class AnalysisServerMock extends TypedMock implements AnalysisServer {
-
   @override
   final ResourceProvider resourceProvider;
 
@@ -51,8 +51,7 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
-class ServerContextManagerMock extends TypedMock
-    implements ServerContextManager {
+class ServerContextManagerMock extends TypedMock implements ContextManager {
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
diff --git a/pkg/analysis_server/test/server_options_test.dart b/pkg/analysis_server/test/server_options_test.dart
new file mode 100644
index 0000000..f3a3790
--- /dev/null
+++ b/pkg/analysis_server/test/server_options_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// This code was auto-generated, is not intended to be edited, and is subject to
+// significant change. Please see the README file for more information.
+
+library analysis_server.test.server_options;
+
+import 'package:analysis_server/src/server_options.dart';
+import 'package:unittest/unittest.dart';
+
+void main() {
+  groupSep = ' | ';
+
+  group('server_options', () {
+    test('basic - []', () {
+      var options = new ServerOptions.fromContents('''# ignored
+foo: bar
+baz: padded   
+''');
+      expect(options['foo'], equals('bar'));
+      expect(options['baz'], equals('padded'));
+    });
+    test('basic - isSet', () {
+      var options = new ServerOptions.fromContents('''foo: true
+bar: TRUE
+baz: false
+foobar: off
+''');
+      expect(options.isSet('foo'), isTrue);
+      expect(options.isSet('bar'), isTrue);
+      expect(options.isSet('baz'), isFalse);
+      expect(options.isSet('foobar'), isFalse);
+      expect(options.isSet('does_not_exist'), isFalse);
+      expect(options.isSet('does_not_exist', defaultValue: true), isTrue);
+    });
+
+    test('basic - getStringValue', () {
+      var options = new ServerOptions.fromContents('''foo: someValue
+''');
+      expect(options.getStringValue('foo'), equals('someValue'));
+      expect(options.getStringValue('not_there'), isNull);
+      expect(options.getStringValue('not_there', defaultValue: 'bar'),
+          equals('bar'));
+    });
+  });
+}
diff --git a/pkg/analysis_server/test/services/completion/completion_target_test.dart b/pkg/analysis_server/test/services/completion/completion_target_test.dart
index 57fb4e9..072f97c 100644
--- a/pkg/analysis_server/test/services/completion/completion_target_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_target_test.dart
@@ -498,6 +498,30 @@
     assertTarget('zoo', 'zoo(z) {}');
   }
 
+  test_SwitchStatement_c() {
+    // Token('c') SwitchStatement
+    addTestSource('main() { switch(x) {c^} }');
+    assertTarget('}', 'switch (x) {}');
+  }
+
+  test_SwitchStatement_c2() {
+    // Token('c') SwitchStatement
+    addTestSource('main() { switch(x) { c^ } }');
+    assertTarget('}', 'switch (x) {}');
+  }
+
+  test_SwitchStatement_empty() {
+    // SwitchStatement
+    addTestSource('main() { switch(x) {^} }');
+    assertTarget('}', 'switch (x) {}');
+  }
+
+  test_SwitchStatement_empty2() {
+    // SwitchStatement
+    addTestSource('main() { switch(x) { ^ } }');
+    assertTarget('}', 'switch (x) {}');
+  }
+
   test_TypeArgumentList() {
     // TypeName  TypeArgumentList  TypeName
     addTestSource('main() { C<^> c; }');
diff --git a/pkg/analysis_server/test/services/completion/completion_test_util.dart b/pkg/analysis_server/test/services/completion/completion_test_util.dart
index 249e1c0..6bcbce1 100644
--- a/pkg/analysis_server/test/services/completion/completion_test_util.dart
+++ b/pkg/analysis_server/test/services/completion/completion_test_util.dart
@@ -115,7 +115,7 @@
       {CompletionSuggestionKind csKind: CompletionSuggestionKind.INVOCATION,
       int relevance: DART_RELEVANCE_DEFAULT, String importUri,
       protocol.ElementKind elemKind: null, bool isDeprecated: false,
-      bool isPotential: false}) {
+      bool isPotential: false, String elemFile, int elemOffset}) {
     CompletionSuggestion cs =
         getSuggest(completion: completion, csKind: csKind, elemKind: elemKind);
     if (cs == null) {
@@ -133,18 +133,34 @@
     expect(cs.selectionLength, equals(0));
     expect(cs.isDeprecated, equals(isDeprecated));
     expect(cs.isPotential, equals(isPotential));
+    if (cs.element != null) {
+      expect(cs.element.location, isNotNull);
+      expect(cs.element.location.file, isNotNull);
+      expect(cs.element.location.offset, isNotNull);
+      expect(cs.element.location.length, isNotNull);
+      expect(cs.element.location.startColumn, isNotNull);
+      expect(cs.element.location.startLine, isNotNull);
+    }
+    if (elemFile != null) {
+      expect(cs.element.location.file, elemFile);
+    }
+    if (elemOffset != null) {
+      expect(cs.element.location.offset, elemOffset);
+    }
     return cs;
   }
 
   CompletionSuggestion assertSuggestClass(String name,
       {int relevance: DART_RELEVANCE_DEFAULT, String importUri,
       CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
-      bool isDeprecated: false}) {
+      bool isDeprecated: false, String elemFile, int elemOffset}) {
     CompletionSuggestion cs = assertSuggest(name,
         csKind: kind,
         relevance: relevance,
         importUri: importUri,
-        isDeprecated: isDeprecated);
+        isDeprecated: isDeprecated,
+        elemFile: elemFile,
+        elemOffset: elemOffset);
     protocol.Element element = cs.element;
     expect(element, isNotNull);
     expect(element.kind, equals(protocol.ElementKind.CLASS));
@@ -171,9 +187,10 @@
   }
 
   CompletionSuggestion assertSuggestConstructor(String name,
-      {int relevance: DART_RELEVANCE_DEFAULT, String importUri}) {
-    CompletionSuggestion cs =
-        assertSuggest(name, relevance: relevance, importUri: importUri);
+      {int relevance: DART_RELEVANCE_DEFAULT, String importUri,
+      int elemOffset}) {
+    CompletionSuggestion cs = assertSuggest(name,
+        relevance: relevance, importUri: importUri, elemOffset: elemOffset);
     protocol.Element element = cs.element;
     expect(element, isNotNull);
     expect(element.kind, equals(protocol.ElementKind.CONSTRUCTOR));
@@ -573,7 +590,8 @@
 
   CompletionSuggestion assertSuggestImportedClass(String name,
       {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
-      int relevance: DART_RELEVANCE_DEFAULT, String importUri}) {
+      int relevance: DART_RELEVANCE_DEFAULT, String importUri,
+      String elemFile}) {
     return assertNotSuggested(name);
   }
 
@@ -683,7 +701,8 @@
 
   CompletionSuggestion assertSuggestLocalClass(String name,
       {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
-      int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
+      int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false,
+      String elemFile, int elemOffset}) {
     return assertNotSuggested(name);
   }
 
@@ -692,7 +711,8 @@
     return assertNotSuggested(name);
   }
 
-  CompletionSuggestion assertSuggestLocalConstructor(String name) {
+  CompletionSuggestion assertSuggestLocalConstructor(String name,
+      {int elemOffset}) {
     return assertNotSuggested(name);
   }
 
@@ -1249,7 +1269,7 @@
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
 
-      assertSuggestLocalClass('X');
+      assertSuggestLocalClass('X', elemFile: testFile);
       assertSuggestLocalClass('Z');
       assertSuggestLocalMethod('a', 'X', null);
       assertSuggestLocalMethod('b', 'X', 'void');
@@ -1260,7 +1280,7 @@
       assertNotSuggested('x');
       assertNotSuggested('partT8');
 
-      assertSuggestImportedClass('A');
+      assertSuggestImportedClass('A', elemFile: '/testAB.dart');
       assertNotSuggested('_B');
       assertSuggestImportedClass('C');
       assertNotSuggested('partBoo');
@@ -1945,7 +1965,7 @@
     return computeFull((bool result) {
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
-      assertSuggestLocalClass('A');
+      assertSuggestLocalClass('A', elemOffset: 6);
       assertSuggestImportedClass('Object');
       assertNotSuggested('x');
     });
@@ -3986,6 +4006,35 @@
     });
   }
 
+  test_SwitchStatement_c() {
+    // SwitchStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class A {String g(int x) {switch(x) {c^}}}');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_SwitchStatement_case() {
+    // SwitchStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class A {String g(int x) {switch(x) {case 0: ^}}}');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestLocalClass('A');
+      assertSuggestLocalMethod('g', 'A', 'String');
+      assertSuggestImportedClass('String');
+    });
+  }
+
+  test_SwitchStatement_empty() {
+    // SwitchStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class A {String g(int x) {switch(x) {^}}}');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
   test_ThisExpression_block() {
     // MethodInvocation  ExpressionStatement  Block
     addTestSource('''
diff --git a/pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart
index c33ec14..42a32cd 100644
--- a/pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart
@@ -125,9 +125,13 @@
   @override
   CompletionSuggestion assertSuggestImportedClass(String name,
       {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
-      int relevance: DART_RELEVANCE_DEFAULT, String importUri}) {
+      int relevance: DART_RELEVANCE_DEFAULT, String importUri,
+      String elemFile}) {
     return assertSuggestClass(name,
-        relevance: relevance, kind: kind, importUri: importUri);
+        relevance: relevance,
+        kind: kind,
+        importUri: importUri,
+        elemFile: elemFile);
   }
 
   @override
diff --git a/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
index c9666b1..6db5b89 100644
--- a/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
@@ -1128,6 +1128,33 @@
         relevance: DART_RELEVANCE_HIGH);
   }
 
+  test_switch_start5() {
+    addTestSource('main() {switch(1) {c^ default:}}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.CASE, Keyword.DEFAULT],
+        relevance: DART_RELEVANCE_HIGH);
+    expect(request.replacementOffset, 19);
+    expect(request.replacementLength, 1);
+  }
+
+  test_switch_start6() {
+    addTestSource('main() {switch(1) {c^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.CASE, Keyword.DEFAULT],
+        relevance: DART_RELEVANCE_HIGH);
+    expect(request.replacementOffset, 19);
+    expect(request.replacementLength, 1);
+  }
+
+  test_switch_start7() {
+    addTestSource('main() {switch(1) { c^ }}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.CASE, Keyword.DEFAULT],
+        relevance: DART_RELEVANCE_HIGH);
+    expect(request.replacementOffset, 20);
+    expect(request.replacementLength, 1);
+  }
+
   test_switch_statement() {
     addTestSource('main() {switch(1) {case 1:^}}');
     expect(computeFast(), isTrue);
diff --git a/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
index e46a771..36310da 100644
--- a/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
@@ -24,9 +24,14 @@
   @override
   CompletionSuggestion assertSuggestLocalClass(String name,
       {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
-      int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
+      int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false,
+      String elemFile, int elemOffset}) {
     return assertSuggestClass(name,
-        kind: kind, relevance: relevance, isDeprecated: isDeprecated);
+        elemFile: elemFile,
+        elemOffset: elemOffset,
+        isDeprecated: isDeprecated,
+        kind: kind,
+        relevance: relevance);
   }
 
   @override
@@ -36,8 +41,9 @@
   }
 
   @override
-  CompletionSuggestion assertSuggestLocalConstructor(String name) {
-    return assertSuggestConstructor(name);
+  CompletionSuggestion assertSuggestLocalConstructor(String name,
+      {int elemOffset}) {
+    return assertSuggestConstructor(name, elemOffset: elemOffset);
   }
 
   @override
@@ -602,7 +608,7 @@
     return computeFull((bool result) {
       CompletionSuggestion suggestion;
 
-      suggestion = assertSuggestLocalConstructor('A');
+      suggestion = assertSuggestLocalConstructor('A', elemOffset: -1);
       expect(suggestion.element.parameters, '()');
       expect(suggestion.element.returnType, 'A');
       expect(suggestion.declaringType, 'A');
diff --git a/pkg/analysis_server/test/services/completion/optype_test.dart b/pkg/analysis_server/test/services/completion/optype_test.dart
index 27e32b7..04ce497 100644
--- a/pkg/analysis_server/test/services/completion/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/optype_test.dart
@@ -1124,19 +1124,72 @@
     assertOpType(typeNames: true);
   }
 
-  test_SwitchCase() {
-    // SimpleIdentifier  SwitchCase  SwitchStatement
-    addTestSource('''m() {switch (x) {case ^D: return;}}''');
-    // TODO (danrubel) should refine this to return constants
+  test_SwitchCase_before() {
+    // SwitchCase  SwitchStatement  Block
+    addTestSource('main() {switch(k) {^case 1:}}');
+    assertOpType();
+  }
+
+  test_SwitchCase_between() {
+    // SwitchCase  SwitchStatement  Block
+    addTestSource('main() {switch(k) {case 1: ^ case 2: return}}');
     assertOpType(returnValue: true, typeNames: true, voidReturn: true);
   }
 
-  test_SwitchStatement() {
+  test_SwitchCase_expression1() {
+    // SimpleIdentifier  SwitchCase  SwitchStatement
+    addTestSource('''m() {switch (x) {case ^D: return;}}''');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
+  test_SwitchCase_expression2() {
+    // SimpleIdentifier  SwitchCase  SwitchStatement
+    addTestSource('''m() {switch (x) {case ^}}''');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
+  test_SwitchDefault_before() {
+    // SwitchDefault  SwitchStatement  Block
+    addTestSource('main() {switch(k) { ^ default: return;}}');
+    assertOpType();
+  }
+
+  test_SwitchDefault_between() {
+    // SwitchDefault  SwitchStatement  Block
+    addTestSource('main() {switch(k) {case 1: ^ default: return;}}');
+    assertOpType(returnValue: true, typeNames: true, voidReturn: true);
+  }
+
+  test_SwitchStatement_body_empty() {
+    // Token('}')  SwitchStatement  Block
+    addTestSource('main() {switch(k) {^}}');
+    assertOpType();
+  }
+
+  test_SwitchStatement_body_end() {
+    // Token('}')  SwitchStatement  Block
+    addTestSource('main() {switch(k) {case 1:^}}');
+    assertOpType(returnValue: true, typeNames: true, voidReturn: true);
+  }
+
+  test_SwitchStatement_expression1() {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(^k) {case 1:{}}}');
     assertOpType(returnValue: true, typeNames: true);
   }
 
+  test_SwitchStatement_expression2() {
+    // SimpleIdentifier  SwitchStatement  Block
+    addTestSource('main() {switch(k^) {case 1:{}}}');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
+  test_SwitchStatement_expression_empty() {
+    // SimpleIdentifier  SwitchStatement  Block
+    addTestSource('main() {switch(^) {case 1:{}}}');
+    assertOpType(returnValue: true, typeNames: true);
+  }
+
   test_ThisExpression_block() {
     // MethodInvocation  ExpressionStatement  Block
     addTestSource('''
diff --git a/pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart b/pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart
index 7e77a87..7778869 100644
--- a/pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart
@@ -238,7 +238,18 @@
     addTestSource('import "dart:async" deferred as bar; foo() {bar.^}');
     return computeFull((bool result) {
       assertSuggestClass('Future');
-      assertSuggestFunction('loadLibrary', 'void');
+      assertSuggestFunction('loadLibrary', 'Future<dynamic>');
+    });
+  }
+
+  test_libraryPrefix_with_exports() {
+    addSource('/libA.dart', 'library libA; class A { }');
+    addSource('/libB.dart', 'library libB; export "/libA.dart"; class B { }');
+    addTestSource('import "/libB.dart" as foo; main() {foo.^} class C { }');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestClass('B');
+      assertSuggestClass('A');
     });
   }
 
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index 8e27fa5..e1c9f62 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -106,7 +106,9 @@
   }
 
   void test_addTypeAnnotation_BAD_privateType_closureParameter() {
-    addSource('/my_lib.dart', '''
+    addSource(
+        '/my_lib.dart',
+        '''
 library my_lib;
 class A {}
 class _B extends A {}
@@ -122,7 +124,9 @@
   }
 
   void test_addTypeAnnotation_BAD_privateType_declaredIdentifier() {
-    addSource('/my_lib.dart', '''
+    addSource(
+        '/my_lib.dart',
+        '''
 library my_lib;
 class A {}
 class _B extends A {}
@@ -141,7 +145,9 @@
   }
 
   void test_addTypeAnnotation_BAD_privateType_list() {
-    addSource('/my_lib.dart', '''
+    addSource(
+        '/my_lib.dart',
+        '''
 library my_lib;
 class A {}
 class _B extends A {}
@@ -157,7 +163,9 @@
   }
 
   void test_addTypeAnnotation_BAD_privateType_variable() {
-    addSource('/my_lib.dart', '''
+    addSource(
+        '/my_lib.dart',
+        '''
 library my_lib;
 class A {}
 class _B extends A {}
@@ -178,7 +186,10 @@
   final f = 0;
 }
 ''');
-    assertHasAssistAt('final ', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'final ',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class A {
   final int f = 0;
 }
@@ -191,7 +202,10 @@
   var f = 0;
 }
 ''');
-    assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'var ',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class A {
   int f = 0;
 }
@@ -239,7 +253,10 @@
   }
 }
 ''');
-    assertHasAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'item in',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class A<T> {
   main(List<List<T>> items) {
     for (List<T> item in items) {
@@ -257,14 +274,20 @@
 }
 ''');
     // on identifier
-    assertHasAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'item in',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main(List<String> items) {
   for (String item in items) {
   }
 }
 ''');
     // on "for"
-    assertHasAssistAt('for (', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'for (',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main(List<String> items) {
   for (String item in items) {
   }
@@ -273,7 +296,9 @@
   }
 
   void test_addTypeAnnotation_declaredIdentifier_OK_addImport_dartUri() {
-    addSource('/my_lib.dart', r'''
+    addSource(
+        '/my_lib.dart',
+        r'''
 import 'dart:async';
 List<Future<int>> getFutures() => null;
 ''');
@@ -284,7 +309,10 @@
   }
 }
 ''');
-    assertHasAssistAt('future in', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'future in',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 import 'my_lib.dart';
 import 'dart:async';
 main() {
@@ -301,7 +329,10 @@
   }
 }
 ''');
-    assertHasAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'item in',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main(List<String> items) {
   for (final String item in items) {
   }
@@ -317,7 +348,10 @@
   }
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class A {
   main(List<int> items) {
     List<int> v = items;
@@ -334,7 +368,10 @@
   }
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class A<T> {
   main(List<T> items) {
     List<T> v = items;
@@ -344,7 +381,9 @@
   }
 
   void test_addTypeAnnotation_local_OK_addImport_dartUri() {
-    addSource('/my_lib.dart', r'''
+    addSource(
+        '/my_lib.dart',
+        r'''
 import 'dart:async';
 Future<int> getFutureInt() => null;
 ''');
@@ -354,7 +393,10 @@
   var v = getFutureInt();
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 import 'my_lib.dart';
 import 'dart:async';
 main() {
@@ -365,7 +407,9 @@
 
   void test_addTypeAnnotation_local_OK_addImport_notLibraryUnit() {
     // prepare library
-    addSource('/my_lib.dart', r'''
+    addSource(
+        '/my_lib.dart',
+        r'''
 import 'dart:async';
 Future<int> getFutureInt() => null;
 ''');
@@ -398,7 +442,9 @@
     {
       var testFileEdit = change.getFileEdit('/app.dart');
       var resultCode = SourceEdit.applySequence(appCode, testFileEdit.edits);
-      expect(resultCode, '''
+      expect(
+          resultCode,
+          '''
 library my_app;
 import 'my_lib.dart';
 import 'dart:async';
@@ -408,7 +454,9 @@
     {
       var testFileEdit = change.getFileEdit('/test.dart');
       var resultCode = SourceEdit.applySequence(testCode, testFileEdit.edits);
-      expect(resultCode, '''
+      expect(
+          resultCode,
+          '''
 part of my_app;
 main() {
   Future<int> v = getFutureInt();
@@ -418,10 +466,14 @@
   }
 
   void test_addTypeAnnotation_local_OK_addImport_relUri() {
-    addSource('/aa/bbb/lib_a.dart', r'''
+    addSource(
+        '/aa/bbb/lib_a.dart',
+        r'''
 class MyClass {}
 ''');
-    addSource('/ccc/lib_b.dart', r'''
+    addSource(
+        '/ccc/lib_b.dart',
+        r'''
 import '../aa/bbb/lib_a.dart';
 MyClass newMyClass() => null;
 ''');
@@ -431,7 +483,10 @@
   var v = newMyClass();
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 import 'ccc/lib_b.dart';
 import 'aa/bbb/lib_a.dart';
 main() {
@@ -446,7 +501,10 @@
   var v = () => 1;
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   Function v = () => 1;
 }
@@ -459,7 +517,10 @@
   var v = 0;
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   int v = 0;
 }
@@ -472,7 +533,10 @@
   var v = <String>[];
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   List<String> v = <String>[];
 }
@@ -487,7 +551,10 @@
   var x = f();
 }
 ''');
-    assertHasAssistAt('x =', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'x =',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class C {}
 C f() => null;
 main() {
@@ -502,7 +569,10 @@
   var v = 123;
 }
 ''');
-    assertHasAssistAt('23', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        '23',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   int v = 123;
 }
@@ -515,7 +585,10 @@
   var abc = 0;
 }
 ''');
-    assertHasAssistAt('bc', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'bc',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   int abc = 0;
 }
@@ -528,7 +601,10 @@
   var v = 0;
 }
 ''');
-    assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'var ',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   int v = 0;
 }
@@ -541,7 +617,10 @@
   var v = 123; // marker
 }
 ''');
-    assertHasAssistAt(' // marker', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        ' // marker',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 main() {
   int v = 123; // marker
 }
@@ -603,7 +682,10 @@
   var v = getValue();
 }
 ''');
-    assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'var ',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 class _A {}
 _A getValue() => new _A();
 main() {
@@ -639,7 +721,10 @@
   foo((test) {});
 }
 ''');
-    assertHasAssistAt('test', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'test',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 foo(f(int p)) {}
 main() {
   foo((int test) {});
@@ -651,7 +736,10 @@
     resolveTestUnit('''
 var V = 0;
 ''');
-    assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'var ',
+        DartAssistKind.ADD_TYPE_ANNOTATION,
+        '''
 int V = 0;
 ''');
   }
@@ -678,7 +766,9 @@
 }
 List<int> readBytes() => <int>[];
 ''');
-    assertHasAssistAt('readBytes();', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE,
+    assertHasAssistAt(
+        'readBytes();',
+        DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE,
         '''
 main() {
   List<int> bytes;
@@ -686,10 +776,11 @@
 }
 List<int> readBytes() => <int>[];
 ''');
-    _assertLinkedGroup(change.linkedEditGroups[0], [
-      'readBytes = '
-    ], expectedSuggestions(
-        LinkedEditSuggestionKind.VARIABLE, ['list', 'bytes2', 'readBytes']));
+    _assertLinkedGroup(
+        change.linkedEditGroups[0],
+        ['readBytes = '],
+        expectedSuggestions(LinkedEditSuggestionKind.VARIABLE,
+            ['list', 'bytes2', 'readBytes']));
   }
 
   void test_assignToLocalVariable_alreadyAssignment() {
@@ -735,17 +826,52 @@
     resolveTestUnit('''
 setup(x) {}
 main() {
-  setup(() => print('done'));
+  setup(() => 42);
 }
 ''');
-    assertHasAssistAt('() => print', DartAssistKind.CONVERT_INTO_BLOCK_BODY, '''
+    assertHasAssistAt(
+        '() => 42',
+        DartAssistKind.CONVERT_INTO_BLOCK_BODY,
+        '''
 setup(x) {}
 main() {
   setup(() {
-    return print('done');
+    return 42;
   });
 }
 ''');
+    {
+      Position exitPos = change.selection;
+      expect(exitPos, isNotNull);
+      expect(exitPos.file, testFile);
+      expect(exitPos.offset - 3, resultCode.indexOf('42;'));
+    }
+  }
+
+  void test_convertToBlockBody_OK_closure_voidExpression() {
+    resolveTestUnit('''
+setup(x) {}
+main() {
+  setup(() => print('done'));
+}
+''');
+    assertHasAssistAt(
+        '() => print',
+        DartAssistKind.CONVERT_INTO_BLOCK_BODY,
+        '''
+setup(x) {}
+main() {
+  setup(() {
+    print('done');
+  });
+}
+''');
+    {
+      Position exitPos = change.selection;
+      expect(exitPos, isNotNull);
+      expect(exitPos.file, testFile);
+      expect(exitPos.offset - 3, resultCode.indexOf("');"));
+    }
   }
 
   void test_convertToBlockBody_OK_constructor() {
@@ -754,7 +880,10 @@
   factory A() => null;
 }
 ''');
-    assertHasAssistAt('A()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, '''
+    assertHasAssistAt(
+        'A()',
+        DartAssistKind.CONVERT_INTO_BLOCK_BODY,
+        '''
 class A {
   factory A() {
     return null;
@@ -769,7 +898,10 @@
   mmm() => 123;
 }
 ''');
-    assertHasAssistAt('mmm()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, '''
+    assertHasAssistAt(
+        'mmm()',
+        DartAssistKind.CONVERT_INTO_BLOCK_BODY,
+        '''
 class A {
   mmm() {
     return 123;
@@ -782,7 +914,10 @@
     resolveTestUnit('''
 fff() => 123;
 ''');
-    assertHasAssistAt('fff()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, '''
+    assertHasAssistAt(
+        'fff()',
+        DartAssistKind.CONVERT_INTO_BLOCK_BODY,
+        '''
 fff() {
   return 123;
 }
@@ -793,7 +928,10 @@
     resolveTestUnit('''
 fff() => 123;
 ''');
-    assertHasAssistAt('23;', DartAssistKind.CONVERT_INTO_BLOCK_BODY, '''
+    assertHasAssistAt(
+        '23;',
+        DartAssistKind.CONVERT_INTO_BLOCK_BODY,
+        '''
 fff() {
   return 123;
 }
@@ -825,7 +963,10 @@
   });
 }
 ''');
-    assertHasAssistAt('42;', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, '''
+    assertHasAssistAt(
+        '42;',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
 setup(x) {}
 main() {
   setup(() => 42);
@@ -833,6 +974,26 @@
 ''');
   }
 
+  void test_convertToExpressionBody_OK_closure_voidExpression() {
+    resolveTestUnit('''
+setup(x) {}
+main() {
+  setup(() {
+    print('test');
+  });
+}
+''');
+    assertHasAssistAt(
+        'print(',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
+setup(x) {}
+main() {
+  setup(() => print('test'));
+}
+''');
+  }
+
   void test_convertToExpressionBody_OK_constructor() {
     resolveTestUnit('''
 class A {
@@ -841,7 +1002,10 @@
   }
 }
 ''');
-    assertHasAssistAt('A()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, '''
+    assertHasAssistAt(
+        'A()',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
 class A {
   factory A() => null;
 }
@@ -854,7 +1018,10 @@
   return 42;
 }
 ''');
-    assertHasAssistAt('{', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, '''
+    assertHasAssistAt(
+        '{',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
 fff() => 42;
 ''');
   }
@@ -865,7 +1032,10 @@
   return 42;
 }
 ''');
-    assertHasAssistAt('ff()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, '''
+    assertHasAssistAt(
+        'ff()',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
 fff() => 42;
 ''');
   }
@@ -878,8 +1048,10 @@
   }
 }
 ''');
-    assertHasAssistAt('{ // marker',
-        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, '''
+    assertHasAssistAt(
+        '{ // marker',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
 class A {
   m() => 42;
 }
@@ -892,7 +1064,10 @@
   return 42;
 }
 ''');
-    assertHasAssistAt('return', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, '''
+    assertHasAssistAt(
+        'return',
+        DartAssistKind.CONVERT_INTO_EXPRESSION_BODY,
+        '''
 fff() => 42;
 ''');
   }
@@ -968,7 +1143,10 @@
   A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb;
 }
 ''');
-    assertHasAssistAt('aaa, ', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, '''
+    assertHasAssistAt(
+        'aaa, ',
+        DartAssistKind.CONVERT_TO_FIELD_PARAMETER,
+        '''
 class A {
   double aaa2;
   int bbb2;
@@ -985,7 +1163,10 @@
   }
 }
 ''');
-    assertHasAssistAt('test {', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, '''
+    assertHasAssistAt(
+        'test {',
+        DartAssistKind.CONVERT_TO_FIELD_PARAMETER,
+        '''
 class A {
   int test2;
   A(this.test2) {
@@ -1002,7 +1183,10 @@
   }
 }
 ''');
-    assertHasAssistAt('test)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, '''
+    assertHasAssistAt(
+        'test)',
+        DartAssistKind.CONVERT_TO_FIELD_PARAMETER,
+        '''
 class A {
   int test;
   A(this.test) {
@@ -1019,7 +1203,10 @@
   A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb;
 }
 ''');
-    assertHasAssistAt('bbb)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, '''
+    assertHasAssistAt(
+        'bbb)',
+        DartAssistKind.CONVERT_TO_FIELD_PARAMETER,
+        '''
 class A {
   double aaa2;
   int bbb2;
@@ -1091,7 +1278,10 @@
   }
 }
 ''');
-    assertHasAssistAt('item in', DartAssistKind.CONVERT_INTO_FOR_INDEX, '''
+    assertHasAssistAt(
+        'item in',
+        DartAssistKind.CONVERT_INTO_FOR_INDEX,
+        '''
 main(List<String> items) {
   for (int i = 0; i < items.length; i++) {
     String item = items[i];
@@ -1109,7 +1299,10 @@
   }
 }
 ''');
-    assertHasAssistAt('tring item', DartAssistKind.CONVERT_INTO_FOR_INDEX, '''
+    assertHasAssistAt(
+        'tring item',
+        DartAssistKind.CONVERT_INTO_FOR_INDEX,
+        '''
 main(List<String> items) {
   for (int i = 0; i < items.length; i++) {
     String item = items[i];
@@ -1127,7 +1320,10 @@
   }
 }
 ''');
-    assertHasAssistAt('for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX, '''
+    assertHasAssistAt(
+        'for (String',
+        DartAssistKind.CONVERT_INTO_FOR_INDEX,
+        '''
 main(List<String> items) {
   for (int i = 0; i < items.length; i++) {
     String item = items[i];
@@ -1145,7 +1341,10 @@
   }
 }
 ''');
-    assertHasAssistAt('for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX, '''
+    assertHasAssistAt(
+        'for (String',
+        DartAssistKind.CONVERT_INTO_FOR_INDEX,
+        '''
 main(List<String> items) {
   for (int j = 0; j < items.length; j++) {
     String item = items[j];
@@ -1164,7 +1363,10 @@
   }
 }
 ''');
-    assertHasAssistAt('for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX, '''
+    assertHasAssistAt(
+        'for (String',
+        DartAssistKind.CONVERT_INTO_FOR_INDEX,
+        '''
 main(List<String> items) {
   for (int k = 0; k < items.length; k++) {
     String item = items[k];
@@ -1181,7 +1383,10 @@
   !(p is String);
 }
 ''');
-    assertHasAssistAt('p is', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        'p is',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   p is! String;
 }
@@ -1194,7 +1399,10 @@
   !(p is String);
 }
 ''');
-    assertHasAssistAt('String)', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        'String)',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   p is! String;
 }
@@ -1207,7 +1415,10 @@
   !(p is String);
 }
 ''');
-    assertHasAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        'is String',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   p is! String;
 }
@@ -1220,7 +1431,10 @@
   !!(p is String);
 }
 ''');
-    assertHasAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        'is String',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   !(p is! String);
 }
@@ -1233,7 +1447,10 @@
   !!(p is String);
 }
 ''');
-    assertHasAssistAt('!(p', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        '!(p',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   !(p is! String);
 }
@@ -1246,7 +1463,10 @@
   !(p is String);
 }
 ''');
-    assertHasAssistAt('!(p', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        '!(p',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   p is! String;
 }
@@ -1259,7 +1479,10 @@
   !(p is String);
 }
 ''');
-    assertHasAssistAt('(p is', DartAssistKind.CONVERT_INTO_IS_NOT, '''
+    assertHasAssistAt(
+        '(p is',
+        DartAssistKind.CONVERT_INTO_IS_NOT,
+        '''
 main(p) {
   p is! String;
 }
@@ -1355,7 +1578,10 @@
   !str.isEmpty;
 }
 ''');
-    assertHasAssistAt('isEmpty', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, '''
+    assertHasAssistAt(
+        'isEmpty',
+        DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY,
+        '''
 main(String str) {
   str.isNotEmpty;
 }
@@ -1368,7 +1594,10 @@
   !str.isEmpty;
 }
 ''');
-    assertHasAssistAt('str.', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, '''
+    assertHasAssistAt(
+        'str.',
+        DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY,
+        '''
 main(String str) {
   str.isNotEmpty;
 }
@@ -1381,7 +1610,10 @@
   !'text'.isEmpty;
 }
 ''');
-    assertHasAssistAt('isEmpty', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, '''
+    assertHasAssistAt(
+        'isEmpty',
+        DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY,
+        '''
 main(String str) {
   'text'.isNotEmpty;
 }
@@ -1436,7 +1668,10 @@
   }
 }
 ''');
-    assertHasAssistAt('test)', DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, '''
+    assertHasAssistAt(
+        'test)',
+        DartAssistKind.CONVERT_TO_NORMAL_PARAMETER,
+        '''
 class A {
   var test;
   A(test) : test = test {
@@ -1453,7 +1688,10 @@
   }
 }
 ''');
-    assertHasAssistAt('test)', DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, '''
+    assertHasAssistAt(
+        'test)',
+        DartAssistKind.CONVERT_TO_NORMAL_PARAMETER,
+        '''
 class A {
   int test;
   A(int test) : test = test {
@@ -1470,7 +1708,10 @@
   A(this.bbb) : aaa = 1.0;
 }
 ''');
-    assertHasAssistAt('bbb)', DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, '''
+    assertHasAssistAt(
+        'bbb)',
+        DartAssistKind.CONVERT_TO_NORMAL_PARAMETER,
+        '''
 class A {
   double aaa;
   int bbb;
@@ -1553,7 +1794,10 @@
   print(a.test);
 }
 ''');
-    assertHasAssistAt('test = 42', DartAssistKind.ENCAPSULATE_FIELD, '''
+    assertHasAssistAt(
+        'test = 42',
+        DartAssistKind.ENCAPSULATE_FIELD,
+        '''
 class A {
   int _test = 42;
 
@@ -1579,7 +1823,10 @@
   print(a.test);
 }
 ''');
-    assertHasAssistAt('test = 42', DartAssistKind.ENCAPSULATE_FIELD, '''
+    assertHasAssistAt(
+        'test = 42',
+        DartAssistKind.ENCAPSULATE_FIELD,
+        '''
 class A {
   var _test = 42;
 
@@ -1608,7 +1855,10 @@
   return a $initialOperator b;
 }
 ''');
-      assertHasAssistAt(initialOperator, DartAssistKind.EXCHANGE_OPERANDS, '''
+      assertHasAssistAt(
+          initialOperator,
+          DartAssistKind.EXCHANGE_OPERANDS,
+          '''
 bool main(int a, int b) {
   return b $resultOperator a;
 }
@@ -1622,7 +1872,10 @@
   1 * 2 * 3 + 4;
 }
 ''');
-    assertHasAssistAt('* 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '* 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 * 3 * 1 + 4;
 }
@@ -1635,7 +1888,10 @@
   1 + 2 - 3 + 4;
 }
 ''');
-    assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '+ 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 + 1 - 3 + 4;
 }
@@ -1648,7 +1904,10 @@
   1 + 2 + 3;
 }
 ''');
-    assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '+ 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 + 3 + 1;
 }
@@ -1661,7 +1920,10 @@
   1 + 2 + 3;
 }
 ''');
-    assertHasAssistAt('+ 3', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '+ 3',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   3 + 1 + 2;
 }
@@ -1674,7 +1936,10 @@
   1 + 2;
 }
 ''');
-    assertHasAssistAt(' 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        ' 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 + 1;
 }
@@ -1687,7 +1952,10 @@
   1 + 2;
 }
 ''');
-    assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '+ 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 + 1;
 }
@@ -1701,7 +1969,10 @@
 }
 ''');
     length = '1 + 2'.length;
-    assertHasAssistAt('1 + 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '1 + 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 + 1;
 }
@@ -1715,7 +1986,10 @@
 }
 ''');
     length = 2;
-    assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, '''
+    assertHasAssistAt(
+        '+ 2',
+        DartAssistKind.EXCHANGE_OPERANDS,
+        '''
 main() {
   2 + 1;
 }
@@ -1784,7 +2058,10 @@
   return x.foo();
 }
 ''');
-    assertHasAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW, '''
+    assertHasAssistAt(
+        'import ',
+        DartAssistKind.IMPORT_ADD_SHOW,
+        '''
 import 'dart:math' show PI;
 main(x) {
   PI;
@@ -1802,7 +2079,10 @@
   max(1, 2);
 }
 ''');
-    assertHasAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW, '''
+    assertHasAssistAt(
+        'import ',
+        DartAssistKind.IMPORT_ADD_SHOW,
+        '''
 import 'dart:math' show E, PI, max;
 main() {
   PI;
@@ -1821,7 +2101,10 @@
   max(1, 2);
 }
 ''');
-    assertHasAssistAt('art:math', DartAssistKind.IMPORT_ADD_SHOW, '''
+    assertHasAssistAt(
+        'art:math',
+        DartAssistKind.IMPORT_ADD_SHOW,
+        '''
 import 'dart:math' show E, PI, max;
 main() {
   PI;
@@ -1871,10 +2154,11 @@
 ''';
     assertHasAssistAt(
         'is MyType', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected);
-    _assertLinkedGroup(change.linkedEditGroups[0], [
-      'myTypeName = '
-    ], expectedSuggestions(
-        LinkedEditSuggestionKind.VARIABLE, ['myTypeName', 'typeName', 'name']));
+    _assertLinkedGroup(
+        change.linkedEditGroups[0],
+        ['myTypeName = '],
+        expectedSuggestions(LinkedEditSuggestionKind.VARIABLE,
+            ['myTypeName', 'typeName', 'name']));
     // another good location
     assertHasAssistAt(
         'if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected);
@@ -1900,10 +2184,11 @@
 ''';
     assertHasAssistAt(
         'is! MyType', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected);
-    _assertLinkedGroup(change.linkedEditGroups[0], [
-      'myTypeName = '
-    ], expectedSuggestions(
-        LinkedEditSuggestionKind.VARIABLE, ['myTypeName', 'typeName', 'name']));
+    _assertLinkedGroup(
+        change.linkedEditGroups[0],
+        ['myTypeName = '],
+        expectedSuggestions(LinkedEditSuggestionKind.VARIABLE,
+            ['myTypeName', 'typeName', 'name']));
     // another good location
     assertHasAssistAt(
         'if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected);
@@ -1948,7 +2233,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (', DartAssistKind.INVERT_IF_STATEMENT, '''
+    assertHasAssistAt(
+        'if (',
+        DartAssistKind.INVERT_IF_STATEMENT,
+        '''
 main() {
   if (false) {
     1;
@@ -1968,7 +2256,10 @@
     1;
 }
 ''');
-    assertHasAssistAt('if (', DartAssistKind.INVERT_IF_STATEMENT, '''
+    assertHasAssistAt(
+        'if (',
+        DartAssistKind.INVERT_IF_STATEMENT,
+        '''
 main() {
   if (false)
     1;
@@ -1988,7 +2279,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (1 == 1 && (2 == 2 || 3 == 3)) {
     print(0);
@@ -2008,7 +2302,10 @@
 }
 bool isCheck() => false;
 ''');
-    assertHasAssistAt('if (isCheck', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (isCheck',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (isCheck() && 2 == 2) {
     print(0);
@@ -2028,7 +2325,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if ((1 == 1 || 2 == 2) && 3 == 3) {
     print(0);
@@ -2047,7 +2347,10 @@
   }
 }
 ''');
-    assertHasAssistAt('1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        '1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2066,7 +2369,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2084,7 +2390,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2105,7 +2414,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(1);
@@ -2125,7 +2437,10 @@
     }
 }
 ''');
-    assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, '''
+    assertHasAssistAt(
+        'if (1 ==',
+        DartAssistKind.JOIN_IF_WITH_INNER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2194,7 +2509,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (2 ==', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (2 ==',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && (2 == 2 || 3 == 3)) {
     print(0);
@@ -2214,7 +2532,10 @@
 }
 bool isCheck() => false;
 ''');
-    assertHasAssistAt('if (isCheck', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (isCheck',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && isCheck()) {
     print(0);
@@ -2234,7 +2555,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (3 == 3', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (3 == 3',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if ((1 == 1 || 2 == 2) && 3 == 3) {
     print(0);
@@ -2253,7 +2577,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (2 == 2',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2272,7 +2599,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (2 == 2',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2290,7 +2620,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (2 == 2',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2311,7 +2644,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (2 == 2',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(1);
@@ -2331,7 +2667,10 @@
     }
 }
 ''');
-    assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, '''
+    assertHasAssistAt(
+        'if (2 == 2',
+        DartAssistKind.JOIN_IF_WITH_OUTER,
+        '''
 main() {
   if (1 == 1 && 2 == 2) {
     print(0);
@@ -2397,7 +2736,10 @@
   v = 1;
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.JOIN_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.JOIN_VARIABLE_DECLARATION,
+        '''
 main() {
   var v = 1;
 }
@@ -2494,7 +2836,10 @@
   v = 1;
 }
 ''');
-    assertHasAssistAt('v;', DartAssistKind.JOIN_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'v;',
+        DartAssistKind.JOIN_VARIABLE_DECLARATION,
+        '''
 main() {
   var v = 1;
 }
@@ -2508,7 +2853,10 @@
   v = 1;
 }
 ''');
-    assertHasAssistAt('int v', DartAssistKind.JOIN_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'int v',
+        DartAssistKind.JOIN_VARIABLE_DECLARATION,
+        '''
 main() {
   int v = 1;
 }
@@ -2522,7 +2870,10 @@
   v = 1;
 }
 ''');
-    assertHasAssistAt('var v', DartAssistKind.JOIN_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'var v',
+        DartAssistKind.JOIN_VARIABLE_DECLARATION,
+        '''
 main() {
   var v = 1;
 }
@@ -2595,7 +2946,10 @@
   int v = 1;
 }
 ''');
-    assertHasAssistAt('v = ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v = ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 class A {
   var v = 1;
 }
@@ -2608,7 +2962,10 @@
   final int v = 1;
 }
 ''');
-    assertHasAssistAt('v = ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'v = ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 class A {
   final v = 1;
 }
@@ -2621,7 +2978,10 @@
   int a = 1, b = 2;
 }
 ''');
-    assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'int ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 main() {
   var a = 1, b = 2;
 }
@@ -2634,7 +2994,10 @@
   const int v = 1;
 }
 ''');
-    assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'int ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 main() {
   const v = 1;
 }
@@ -2647,7 +3010,10 @@
   final int v = 1;
 }
 ''');
-    assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'int ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 main() {
   final v = 1;
 }
@@ -2658,7 +3024,10 @@
     resolveTestUnit('''
 int V = 1;
 ''');
-    assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'int ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 var V = 1;
 ''');
   }
@@ -2667,7 +3036,10 @@
     resolveTestUnit('''
 final int V = 1;
 ''');
-    assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, '''
+    assertHasAssistAt(
+        'int ',
+        DartAssistKind.REMOVE_TYPE_ANNOTATION,
+        '''
 final V = 1;
 ''');
   }
@@ -2680,7 +3052,9 @@
 }
 ''');
     // on conditional
-    assertHasAssistAt('11 :', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
+    assertHasAssistAt(
+        '11 :',
+        DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
         '''
 main() {
   var v;
@@ -2692,7 +3066,9 @@
 }
 ''');
     // on variable
-    assertHasAssistAt('v =', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
         '''
 main() {
   var v;
@@ -2711,8 +3087,10 @@
   return true ? 111 : 222;
 }
 ''');
-    assertHasAssistAt('return ',
-        DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, '''
+    assertHasAssistAt(
+        'return ',
+        DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
+        '''
 main() {
   if (true) {
     return 111;
@@ -2729,7 +3107,9 @@
   int a = 1, vvv = true ? 111 : 222, b = 2;
 }
 ''');
-    assertHasAssistAt('11 :', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
+    assertHasAssistAt(
+        '11 :',
+        DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE,
         '''
 main() {
   int a = 1, vvv, b = 2;
@@ -2769,8 +3149,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (true)',
-        DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, '''
+    assertHasAssistAt(
+        'if (true)',
+        DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL,
+        '''
 main() {
   int vvv;
   vvv = true ? 111 : 222;
@@ -2788,8 +3170,10 @@
   }
 }
 ''');
-    assertHasAssistAt('if (true)',
-        DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, '''
+    assertHasAssistAt(
+        'if (true)',
+        DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL,
+        '''
 main() {
   return true ? 111 : 222;
 }
@@ -2843,7 +3227,10 @@
   }
 }
 ''');
-    assertHasAssistAt('&& 2 == 2', DartAssistKind.SPLIT_AND_CONDITION, '''
+    assertHasAssistAt(
+        '&& 2 == 2',
+        DartAssistKind.SPLIT_AND_CONDITION,
+        '''
 main() {
   if (1 == 1) {
     if (2 == 2 && 3 == 3) {
@@ -2865,7 +3252,10 @@
   }
 }
 ''');
-    assertHasAssistAt('&& false', DartAssistKind.SPLIT_AND_CONDITION, '''
+    assertHasAssistAt(
+        '&& false',
+        DartAssistKind.SPLIT_AND_CONDITION,
+        '''
 main() {
   if (true) {
     if (false) {
@@ -2886,7 +3276,10 @@
     print(0);
 }
 ''');
-    assertHasAssistAt('&& false', DartAssistKind.SPLIT_AND_CONDITION, '''
+    assertHasAssistAt(
+        '&& false',
+        DartAssistKind.SPLIT_AND_CONDITION,
+        '''
 main() {
   if (true)
     if (false)
@@ -2967,7 +3360,10 @@
   var v = 1;
 }
 ''');
-    assertHasAssistAt('v =', DartAssistKind.SPLIT_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'v =',
+        DartAssistKind.SPLIT_VARIABLE_DECLARATION,
+        '''
 main() {
   var v;
   v = 1;
@@ -2981,7 +3377,10 @@
   int v = 1;
 }
 ''');
-    assertHasAssistAt('int ', DartAssistKind.SPLIT_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'int ',
+        DartAssistKind.SPLIT_VARIABLE_DECLARATION,
+        '''
 main() {
   int v;
   v = 1;
@@ -2995,7 +3394,10 @@
   var v = 1;
 }
 ''');
-    assertHasAssistAt('var ', DartAssistKind.SPLIT_VARIABLE_DECLARATION, '''
+    assertHasAssistAt(
+        'var ',
+        DartAssistKind.SPLIT_VARIABLE_DECLARATION,
+        '''
 main() {
   var v;
   v = 1;
@@ -3022,7 +3424,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_BLOCK, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_BLOCK,
+        '''
 main() {
 // start
   {
@@ -3044,7 +3448,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_DO_WHILE, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_DO_WHILE,
+        '''
 main() {
 // start
   do {
@@ -3066,7 +3472,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_FOR, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_FOR,
+        '''
 main() {
 // start
   for (var v = init; condition; increment) {
@@ -3088,7 +3496,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_FOR_IN, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_FOR_IN,
+        '''
 main() {
 // start
   for (var item in iterable) {
@@ -3110,7 +3520,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_IF, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_IF,
+        '''
 main() {
 // start
   if (condition) {
@@ -3132,7 +3544,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_TRY_CATCH, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_TRY_CATCH,
+        '''
 main() {
 // start
   try {
@@ -3156,7 +3570,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_TRY_FINALLY, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_TRY_FINALLY,
+        '''
 main() {
 // start
   try {
@@ -3180,7 +3596,9 @@
 }
 ''');
     _setStartEndSelection();
-    assertHasAssist(DartAssistKind.SURROUND_WITH_WHILE, '''
+    assertHasAssist(
+        DartAssistKind.SURROUND_WITH_WHILE,
+        '''
 main() {
 // start
   while (condition) {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 4bbaeb1..f0692c6 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -47,7 +47,9 @@
   $lineWithTest
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   bool b = true;
   $lineWithTest
@@ -114,7 +116,9 @@
   Test(this.a);
 }
 ''');
-    assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
+    assertHasFix(
+        DartFixKind.ADD_FIELD_FORMAL_PARAMETERS,
+        '''
 class Test {
   final int a;
   final int b;
@@ -133,7 +137,9 @@
   Test();
 }
 ''');
-    assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
+    assertHasFix(
+        DartFixKind.ADD_FIELD_FORMAL_PARAMETERS,
+        '''
 class Test {
   final int a;
   final int b;
@@ -152,7 +158,9 @@
   Test([this.c]);
 }
 ''');
-    assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
+    assertHasFix(
+        DartFixKind.ADD_FIELD_FORMAL_PARAMETERS,
+        '''
 class Test {
   final int a;
   final int b;
@@ -169,7 +177,9 @@
   test(1);
 }
 ''');
-    assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, '''
+    assertHasFix(
+        DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL,
+        '''
 test([int i]) {}
 main() {
   test(1);
@@ -184,7 +194,9 @@
   test(1, 2.0);
 }
 ''');
-    assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
+    assertHasFix(
+        DartFixKind.ADD_MISSING_PARAMETER_REQUIRED,
+        '''
 test(int a, double d) {}
 main() {
   test(1, 2.0);
@@ -199,7 +211,9 @@
   test(1);
 }
 ''');
-    assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
+    assertHasFix(
+        DartFixKind.ADD_MISSING_PARAMETER_REQUIRED,
+        '''
 test(int i) {}
 main() {
   test(1);
@@ -216,7 +230,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, '''
+    assertHasFix(
+        DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL,
+        '''
 class A {
   test(int a, [double d]) {}
   main() {
@@ -235,7 +251,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
+    assertHasFix(
+        DartFixKind.ADD_MISSING_PARAMETER_REQUIRED,
+        '''
 class A {
   test(int a, double d) {}
   main() {
@@ -254,7 +272,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
+    assertHasFix(
+        DartFixKind.ADD_MISSING_PARAMETER_REQUIRED,
+        '''
 class A {
   test(int i) {}
   main() {
@@ -285,7 +305,9 @@
     expect(fileEdits, hasLength(1));
     SourceFileEdit fileEdit = change.edits[0];
     expect(fileEdit.file, '/part.dart');
-    expect(SourceEdit.applySequence(partCode, fileEdit.edits), r'''
+    expect(
+        SourceEdit.applySequence(partCode, fileEdit.edits),
+        r'''
 // Comment first.
 // Comment second.
 
@@ -332,7 +354,9 @@
       expect(fileEdits, hasLength(1));
       resultCode = SourceEdit.applySequence(testCode, fileEdits[0].edits);
       // verify
-      expect(resultCode, '''
+      expect(
+          resultCode,
+          '''
 foo() {}
 main() async {
   await foo();
@@ -349,7 +373,9 @@
 foo() {}
 main() => await foo();
 ''');
-    assertHasFix(DartFixKind.ADD_ASYNC, '''
+    assertHasFix(
+        DartFixKind.ADD_ASYNC,
+        '''
 foo() {}
 main() async => await foo();
 ''');
@@ -361,7 +387,9 @@
   boolean v;
 }
 ''');
-    assertHasFix(DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, '''
+    assertHasFix(
+        DartFixKind.REPLACE_BOOLEAN_WITH_BOOL,
+        '''
 main() {
   bool v;
 }
@@ -377,7 +405,9 @@
   a.foo();
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO_STATIC_ACCESS,
+        '''
 class A {
   static foo() {}
 }
@@ -388,13 +418,17 @@
   }
 
   void test_changeToStaticAccess_method_importType() {
-    addSource('/libA.dart', r'''
+    addSource(
+        '/libA.dart',
+        r'''
 library libA;
 class A {
   static foo() {}
 }
 ''');
-    addSource('/libB.dart', r'''
+    addSource(
+        '/libB.dart',
+        r'''
 library libB;
 import 'libA.dart';
 class B extends A {}
@@ -405,7 +439,9 @@
   b.foo();
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO_STATIC_ACCESS,
+        '''
 import 'libB.dart';
 import 'libA.dart';
 main(B b) {
@@ -421,7 +457,9 @@
   f.wait([]);
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO_STATIC_ACCESS,
+        '''
 import 'dart:async' as pref;
 main(pref.Future f) {
   pref.Future.wait([]);
@@ -438,7 +476,9 @@
   a.foo;
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO_STATIC_ACCESS,
+        '''
 class A {
   static get foo => 42;
 }
@@ -449,13 +489,17 @@
   }
 
   void test_changeToStaticAccess_property_importType() {
-    addSource('/libA.dart', r'''
+    addSource(
+        '/libA.dart',
+        r'''
 library libA;
 class A {
   static get foo => null;
 }
 ''');
-    addSource('/libB.dart', r'''
+    addSource(
+        '/libB.dart',
+        r'''
 library libB;
 import 'libA.dart';
 class B extends A {}
@@ -466,7 +510,9 @@
   b.foo;
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO_STATIC_ACCESS,
+        '''
 import 'libB.dart';
 import 'libA.dart';
 main(B b) {
@@ -481,7 +527,9 @@
   Test v = null;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CLASS, '''
+    assertHasFix(
+        DartFixKind.CREATE_CLASS,
+        '''
 main() {
   Test v = null;
 }
@@ -515,7 +563,9 @@
     expect(fileEdits, hasLength(1));
     SourceFileEdit fileEdit = change.edits[0];
     expect(fileEdit.file, '/lib.dart');
-    expect(SourceEdit.applySequence(libCode, fileEdit.edits), r'''
+    expect(
+        SourceEdit.applySequence(libCode, fileEdit.edits),
+        r'''
 library my.lib;
 
 class A {}
@@ -534,7 +584,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CLASS, '''
+    assertHasFix(
+        DartFixKind.CREATE_CLASS,
+        '''
 f() {
   g() {
     Test v = null;
@@ -547,6 +599,51 @@
     _assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']);
   }
 
+  void test_createClass_itemOfList() {
+    resolveTestUnit('''
+main() {
+  var a = [Test];
+}
+''');
+    assertHasFix(
+        DartFixKind.CREATE_CLASS,
+        '''
+main() {
+  var a = [Test];
+}
+
+class Test {
+}
+''');
+    _assertLinkedGroup(change.linkedEditGroups[0], ['Test];', 'Test {']);
+  }
+
+  void test_createClass_itemOfList_inAnnotation() {
+    errorFilter = (AnalysisError error) {
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+    };
+    resolveTestUnit('''
+class MyAnnotation {
+  const MyAnnotation(a, b);
+}
+@MyAnnotation(int, const [Test])
+main() {}
+''');
+    assertHasFix(
+        DartFixKind.CREATE_CLASS,
+        '''
+class MyAnnotation {
+  const MyAnnotation(a, b);
+}
+@MyAnnotation(int, const [Test])
+main() {}
+
+class Test {
+}
+''');
+    _assertLinkedGroup(change.linkedEditGroups[0], ['Test])', 'Test {']);
+  }
+
   void test_createConstructor_forFinalFields() {
     errorFilter = (AnalysisError error) {
       return error.message.contains("'a'");
@@ -558,7 +655,9 @@
   final int c;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS,
+        '''
 class Test {
   final int a;
   final int b = 2;
@@ -580,7 +679,9 @@
   new A(1, 2.0);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR,
+        '''
 class A {
   int field;
 
@@ -604,7 +705,9 @@
   new A.named(1, 2.0);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR,
+        '''
 class A {
   A.named(int i, double d) {
   }
@@ -643,7 +746,9 @@
   B() {}
 }
 ''');
-    assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
+    assertHasFix(
+        DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION,
+        '''
 class A {
   A(bool p1, int p2, double p3, String p4, {p5});
 }
@@ -663,7 +768,9 @@
   B() : field = 42 {}
 }
 ''');
-    assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
+    assertHasFix(
+        DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION,
+        '''
 class A {
   A(int p);
 }
@@ -683,7 +790,9 @@
   B() {}
 }
 ''');
-    assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
+    assertHasFix(
+        DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION,
+        '''
 class A {
   A.named(int p);
 }
@@ -714,7 +823,9 @@
   B();
 }
 ''');
-    assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
+    assertHasFix(
+        DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION,
+        '''
 class A<T> {
   A(T p);
 }
@@ -735,7 +846,9 @@
   void existingMethod() {}
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR_SUPER,
+        '''
 class A {
   A(p1, int p2, List<String> p3, [int p4]);
 }
@@ -761,7 +874,9 @@
   void existingMethod() {}
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR_SUPER,
+        '''
 class A {
   int _field;
   A(this._field);
@@ -777,11 +892,15 @@
   }
 
   void test_createConstructorSuperImplicit_importType() {
-    addSource('/libA.dart', r'''
+    addSource(
+        '/libA.dart',
+        r'''
 library libA;
 class A {}
 ''');
-    addSource('/libB.dart', r'''
+    addSource(
+        '/libB.dart',
+        r'''
 library libB;
 import 'libA.dart';
 class B {
@@ -793,7 +912,9 @@
 class C extends B {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR_SUPER,
+        '''
 import 'libB.dart';
 import 'libA.dart';
 class C extends B {
@@ -813,7 +934,9 @@
   void existingMethod() {}
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR_SUPER,
+        '''
 class A {
   A.named(p1, int p2);
 }
@@ -846,7 +969,9 @@
 }
 class D extends C<int> {
 }''');
-    assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
+    assertHasFix(
+        DartFixKind.CREATE_CONSTRUCTOR_SUPER,
+        '''
 class C<T> {
   final T x;
   C(this.x);
@@ -891,7 +1016,9 @@
   int v = c.b.a.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 }
@@ -915,7 +1042,9 @@
   int v = a.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 }
@@ -936,7 +1065,9 @@
 class B {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   B b;
   void f(Object p) {
@@ -958,7 +1089,9 @@
 }
 f(String s) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   String test;
 
@@ -978,7 +1111,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 
@@ -997,7 +1132,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   var test;
 
@@ -1017,7 +1154,9 @@
   int v = x.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 }
@@ -1037,7 +1176,9 @@
   x.test = 0;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 }
@@ -1049,11 +1190,15 @@
   }
 
   void test_createField_importType() {
-    addSource('/libA.dart', r'''
+    addSource(
+        '/libA.dart',
+        r'''
 library libA;
 class A {}
 ''');
-    addSource('/libB.dart', r'''
+    addSource(
+        '/libB.dart',
+        r'''
 library libB;
 import 'libA.dart';
 A getA() => null;
@@ -1066,7 +1211,9 @@
   c.test = getA();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 import 'libB.dart';
 import 'libA.dart';
 class C {
@@ -1089,7 +1236,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   List test;
 }
@@ -1112,7 +1261,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A<T> {
   List<T> items;
 
@@ -1137,7 +1288,9 @@
   a.test = 5;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int aaa;
   int zzz;
@@ -1161,7 +1314,9 @@
   a.test = 5;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 
@@ -1181,7 +1336,9 @@
   A.test = 5;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   static int test;
 }
@@ -1199,7 +1356,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   int test;
 
@@ -1218,7 +1377,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FIELD, '''
+    assertHasFix(
+        DartFixKind.CREATE_FIELD,
+        '''
 class A {
   static int test;
 
@@ -1244,7 +1405,48 @@
     expect(fileEdit.file, '/my/project/bin/my_file.dart');
     expect(fileEdit.fileStamp, -1);
     expect(fileEdit.edits, hasLength(1));
-    expect(fileEdit.edits[0].replacement, contains('library my.file;'));
+    expect(fileEdit.edits[0].replacement, contains('library my_file;'));
+  }
+
+  void test_createFile_forImport_inPackage_lib() {
+    provider.newFile('/projects/my_package/pubspec.yaml', 'name: my_package');
+    testFile = '/projects/my_package/lib/test.dart';
+    provider.newFolder('/projects/my_package/lib');
+    resolveTestUnit('''
+import 'a/bb/c_cc/my_lib.dart';
+''');
+    AnalysisError error = _findErrorToFix();
+    fix = _assertHasFix(DartFixKind.CREATE_FILE, error);
+    change = fix.change;
+    // validate change
+    List<SourceFileEdit> fileEdits = change.edits;
+    expect(fileEdits, hasLength(1));
+    SourceFileEdit fileEdit = change.edits[0];
+    expect(fileEdit.file, '/projects/my_package/lib/a/bb/c_cc/my_lib.dart');
+    expect(fileEdit.fileStamp, -1);
+    expect(fileEdit.edits, hasLength(1));
+    expect(fileEdit.edits[0].replacement,
+        contains('library my_package.a.bb.c_cc.my_lib;'));
+  }
+
+  void test_createFile_forImport_inPackage_test() {
+    provider.newFile('/projects/my_package/pubspec.yaml', 'name: my_package');
+    testFile = '/projects/my_package/test/misc/test_all.dart';
+    resolveTestUnit('''
+import 'a/bb/my_lib.dart';
+''');
+    AnalysisError error = _findErrorToFix();
+    fix = _assertHasFix(DartFixKind.CREATE_FILE, error);
+    change = fix.change;
+    // validate change
+    List<SourceFileEdit> fileEdits = change.edits;
+    expect(fileEdits, hasLength(1));
+    SourceFileEdit fileEdit = change.edits[0];
+    expect(fileEdit.file, '/projects/my_package/test/misc/a/bb/my_lib.dart');
+    expect(fileEdit.fileStamp, -1);
+    expect(fileEdit.edits, hasLength(1));
+    expect(fileEdit.edits[0].replacement,
+        contains('library my_package.test.misc.a.bb.my_lib;'));
   }
 
   void test_createFile_forPart() {
@@ -1267,17 +1469,22 @@
   }
 
   void test_createFile_forPart_inPackageLib() {
-    provider.newFile('/my/pubspec.yaml', r'''
+    provider.newFile(
+        '/my/pubspec.yaml',
+        r'''
 name: my_test
 ''');
     testFile = '/my/lib/test.dart';
-    addTestSource('''
+    addTestSource(
+        '''
 library my.lib;
 part 'my_part.dart';
-''', Uri.parse('package:my/test.dart'));
+''',
+        Uri.parse('package:my/test.dart'));
     // configure SourceFactory
-    UriResolver pkgResolver = new PackageMapUriResolver(
-        provider, {'my': [provider.getResource('/my/lib')],});
+    UriResolver pkgResolver = new PackageMapUriResolver(provider, {
+      'my': [provider.getResource('/my/lib')],
+    });
     context.sourceFactory = new SourceFactory(
         [AbstractContextTest.SDK_RESOLVER, pkgResolver, resourceResolver]);
     // prepare fix
@@ -1313,7 +1520,9 @@
   int v = x.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   int get test => null;
 }
@@ -1338,7 +1547,9 @@
   int v = c.b.a.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   int get test => null;
 }
@@ -1362,7 +1573,9 @@
   int v = a.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   int get test => null;
 }
@@ -1383,7 +1596,9 @@
 class B {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   B b;
   void f(Object p) {
@@ -1416,7 +1631,9 @@
 }
 f(String s) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   String get test => null;
 
@@ -1447,7 +1664,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   int get test => null;
 
@@ -1466,7 +1685,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   get test => null;
 
@@ -1485,7 +1706,9 @@
   foo(bar);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 typedef MY_FUNCTION(int p);
 foo(MY_FUNCTION f) {}
 main() {
@@ -1511,7 +1734,9 @@
   int a = test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 main() {
   int test;
   int a = test;
@@ -1527,7 +1752,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 main() {
   bool test;
   if (!test) {
@@ -1544,7 +1771,9 @@
 }
 f(String p) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 main() {
   String test;
   f(test);
@@ -1561,7 +1790,9 @@
   test.add('hello');
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 main() {
   var test;
   test.add('hello');
@@ -1576,7 +1807,9 @@
   test = 42;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 main() {
   var test = 42;
 }
@@ -1589,7 +1822,9 @@
   test += 42;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
+    assertHasFix(
+        DartFixKind.CREATE_LOCAL_VARIABLE,
+        '''
 main() {
   int test;
   test += 42;
@@ -1608,7 +1843,9 @@
 class MyEmulator extends Emulator {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 typedef int Binary(int left, int right);
 
 abstract class Emulator {
@@ -1633,7 +1870,9 @@
 class B extends A {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 abstract class A {
   forEach(int f(double p1, String p2));
 }
@@ -1659,7 +1898,9 @@
 class Test extends IterableMixin<int> {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 class Iterator<T> {
 }
 
@@ -1684,7 +1925,9 @@
 class Test<V> extends ItemProvider<V> {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 abstract class ItemProvider<T> {
   List<T> getItems();
 }
@@ -1708,7 +1951,9 @@
 class B extends A {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 abstract class A {
   get g1;
   int get g2;
@@ -1736,7 +1981,9 @@
 class B extends A {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 import 'dart:async' as aaa;
 abstract class A {
   Map<aaa.Future, List<aaa.Future>> g(aaa.Future p);
@@ -1762,7 +2009,9 @@
 class B implements A {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 class A {
   int ma;
   void mb() {}
@@ -1865,7 +2114,9 @@
 class B extends A {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 abstract class A {
   int operator [](int index);
   void operator []=(int index, String value);
@@ -1896,7 +2147,9 @@
 class B extends A {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
+    assertHasFix(
+        DartFixKind.CREATE_MISSING_OVERRIDES,
+        '''
 abstract class A {
   set s1(x);
   set s2(int x);
@@ -1933,7 +2186,9 @@
   existing() {}
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_NO_SUCH_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_NO_SUCH_METHOD,
+        '''
 abstract class A {
   m1();
   int m2();
@@ -1960,7 +2215,9 @@
   int v = a.test;
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_GETTER, '''
+    assertHasFix(
+        DartFixKind.CREATE_GETTER,
+        '''
 class A {
   int existingField;
 
@@ -1990,7 +2247,9 @@
   a..ma().useFunction(test);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 class A {
   B ma() => null;
 }
@@ -2015,7 +2274,9 @@
 }
 useFunction({Function g}) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   useFunction(g: test);
 }
@@ -2033,7 +2294,9 @@
 }
 useFunction(int g(a, b)) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   useFunction(test);
 }
@@ -2051,7 +2314,9 @@
 }
 useFunction(int g(double a, String b)) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   useFunction(test);
 }
@@ -2069,7 +2334,9 @@
 }
 useFunction({int g(double a, String b)}) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   useFunction(g: test);
 }
@@ -2081,11 +2348,15 @@
   }
 
   void test_creationFunction_forFunctionType_importType() {
-    addSource('/libA.dart', r'''
+    addSource(
+        '/libA.dart',
+        r'''
 library libA;
 class A {}
 ''');
-    addSource('/libB.dart', r'''
+    addSource(
+        '/libB.dart',
+        r'''
 library libB;
 import 'libA.dart';
 useFunction(int g(A a)) {}
@@ -2096,7 +2367,9 @@
   useFunction(test);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 import 'libB.dart';
 import 'libA.dart';
 main() {
@@ -2117,7 +2390,9 @@
 }
 useFunction(int g(double a, String b)) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   static foo() {
     useFunction(test);
@@ -2138,7 +2413,9 @@
 }
 useFunction(int g(double a, String b)) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   var f;
   A() : f = useFunction(test);
@@ -2159,7 +2436,9 @@
 }
 useFunction(int g(double a, String b)) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 main(A a) {
   useFunction(a.test);
 }
@@ -2181,7 +2460,9 @@
 }
 useFunction(int g(double a, String b)) {}
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 main(A a) {
   useFunction(a.test);
 }
@@ -2225,7 +2506,9 @@
   print(0)
 }
 ''');
-    assertHasFix(DartFixKind.INSERT_SEMICOLON, '''
+    assertHasFix(
+        DartFixKind.INSERT_SEMICOLON,
+        '''
 main() {
   print(0);
 }
@@ -2241,7 +2524,9 @@
 int main() async {
 }
 ''');
-    assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, '''
+    assertHasFix(
+        DartFixKind.REPLACE_RETURN_TYPE_FUTURE,
+        '''
 library main;
 import 'dart:async';
 Future<int> main() async {
@@ -2258,7 +2543,9 @@
 int main() async {
 }
 ''');
-    assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, '''
+    assertHasFix(
+        DartFixKind.REPLACE_RETURN_TYPE_FUTURE,
+        '''
 import 'dart:async' as al;
 al.Future<int> main() async {
 }
@@ -2274,7 +2561,9 @@
 List<int> main() async {
 }
 ''');
-    assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, '''
+    assertHasFix(
+        DartFixKind.REPLACE_RETURN_TYPE_FUTURE,
+        '''
 import 'dart:async';
 Future<List<int>> main() async {
 }
@@ -2290,7 +2579,9 @@
 void main() async {
 }
 ''');
-    assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, '''
+    assertHasFix(
+        DartFixKind.REPLACE_RETURN_TYPE_FUTURE,
+        '''
 import 'dart:async';
 Future main() async {
 }
@@ -2309,7 +2600,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'package:my_pkg/my_lib.dart';
 
 main() {
@@ -2326,7 +2619,9 @@
   Future f = null;
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PREFIX, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PREFIX,
+        '''
 import 'dart:async' as pref;
 main() {
   pref.Stream s = null;
@@ -2343,7 +2638,9 @@
   print(PI);
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PREFIX, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PREFIX,
+        '''
 import 'dart:math' as pref;
 main() {
   print(pref.E);
@@ -2353,7 +2650,9 @@
   }
 
   void test_importLibraryProject_withClass_annotation() {
-    addSource('/lib.dart', '''
+    addSource(
+        '/lib.dart',
+        '''
 library lib;
 class Test {
   const Test(int p);
@@ -2365,7 +2664,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'lib.dart';
 
 @Test(0)
@@ -2376,7 +2677,9 @@
 
   void test_importLibraryProject_withClass_inParentFolder() {
     testFile = '/project/bin/test.dart';
-    addSource('/project/lib.dart', '''
+    addSource(
+        '/project/lib.dart',
+        '''
 library lib;
 class Test {}
 ''');
@@ -2386,7 +2689,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import '../lib.dart';
 
 main() {
@@ -2397,7 +2702,9 @@
 
   void test_importLibraryProject_withClass_inRelativeFolder() {
     testFile = '/project/bin/test.dart';
-    addSource('/project/lib/sub/folder/lib.dart', '''
+    addSource(
+        '/project/lib/sub/folder/lib.dart',
+        '''
 library lib;
 class Test {}
 ''');
@@ -2407,7 +2714,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import '../lib/sub/folder/lib.dart';
 
 main() {
@@ -2418,7 +2727,9 @@
 
   void test_importLibraryProject_withClass_inSameFolder() {
     testFile = '/project/bin/test.dart';
-    addSource('/project/bin/lib.dart', '''
+    addSource(
+        '/project/bin/lib.dart',
+        '''
 library lib;
 class Test {}
 ''');
@@ -2428,7 +2739,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'lib.dart';
 
 main() {
@@ -2438,7 +2751,9 @@
   }
 
   void test_importLibraryProject_withFunction() {
-    addSource('/lib.dart', '''
+    addSource(
+        '/lib.dart',
+        '''
 library lib;
 myFunction() {}
 ''');
@@ -2448,7 +2763,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'lib.dart';
 
 main() {
@@ -2458,7 +2775,9 @@
   }
 
   void test_importLibraryProject_withFunction_unresolvedMethod() {
-    addSource('/lib.dart', '''
+    addSource(
+        '/lib.dart',
+        '''
 library lib;
 myFunction() {}
 ''');
@@ -2470,7 +2789,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'lib.dart';
 
 class A {
@@ -2483,7 +2804,9 @@
 
   void test_importLibraryProject_withFunctionTypeAlias() {
     testFile = '/project/bin/test.dart';
-    addSource('/project/bin/lib.dart', '''
+    addSource(
+        '/project/bin/lib.dart',
+        '''
 library lib;
 typedef MyFunction();
 ''');
@@ -2493,7 +2816,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'lib.dart';
 
 main() {
@@ -2503,7 +2828,9 @@
   }
 
   void test_importLibraryProject_withTopLevelVariable() {
-    addSource('/lib.dart', '''
+    addSource(
+        '/lib.dart',
+        '''
 library lib;
 int MY_VAR = 42;
 ''');
@@ -2513,7 +2840,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_PROJECT,
+        '''
 import 'lib.dart';
 
 main() {
@@ -2528,7 +2857,9 @@
   p as Future;
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:async';
 
 main(p) {
@@ -2543,7 +2874,9 @@
   Future.wait(null);
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:async';
 
 main() {
@@ -2558,7 +2891,9 @@
   p is Future;
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:async';
 
 main(p) {
@@ -2567,13 +2902,57 @@
 ''');
   }
 
+  void test_importLibrarySdk_withClass_itemOfList() {
+    resolveTestUnit('''
+main() {
+  var a = [Future];
+}
+''');
+    performAllAnalysisTasks();
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
+import 'dart:async';
+
+main() {
+  var a = [Future];
+}
+''');
+  }
+
+  void test_importLibrarySdk_withClass_itemOfList_inAnnotation() {
+    errorFilter = (AnalysisError error) {
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+    };
+    resolveTestUnit('''
+class MyAnnotation {
+  const MyAnnotation(a, b);
+}
+@MyAnnotation(int, const [Future])
+main() {}
+''');
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
+import 'dart:async';
+
+class MyAnnotation {
+  const MyAnnotation(a, b);
+}
+@MyAnnotation(int, const [Future])
+main() {}
+''');
+  }
+
   void test_importLibrarySdk_withClass_typeAnnotation() {
     resolveTestUnit('''
 main() {
   Future f = null;
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:async';
 
 main() {
@@ -2588,7 +2967,9 @@
   Future.wait;
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:async';
 
 main() {
@@ -2603,7 +2984,9 @@
   List<Future> futures = [];
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:async';
 
 main() {
@@ -2619,7 +3002,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:math';
 
 main() {
@@ -2635,7 +3020,9 @@
 }
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SDK,
+        '''
 import 'dart:math';
 
 @PI
@@ -2652,7 +3039,9 @@
   Future f = null;
 }
 ''');
-    assertHasFix(DartFixKind.IMPORT_LIBRARY_SHOW, '''
+    assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SHOW,
+        '''
 import 'dart:async' show Future, Stream;
 main() {
   Stream s = null;
@@ -2667,7 +3056,9 @@
   p is! Null;
 }
 ''');
-    assertHasFix(DartFixKind.USE_NOT_EQ_NULL, '''
+    assertHasFix(
+        DartFixKind.USE_NOT_EQ_NULL,
+        '''
 main(p) {
   p != null;
 }
@@ -2680,7 +3071,9 @@
   p is Null;
 }
 ''');
-    assertHasFix(DartFixKind.USE_EQ_EQ_NULL, '''
+    assertHasFix(
+        DartFixKind.USE_EQ_EQ_NULL,
+        '''
 main(p) {
   p == null;
 }
@@ -2693,7 +3086,9 @@
   m();
 }
 ''');
-    assertHasFix(DartFixKind.MAKE_CLASS_ABSTRACT, '''
+    assertHasFix(
+        DartFixKind.MAKE_CLASS_ABSTRACT,
+        '''
 abstract class A {
   m();
 }
@@ -2708,7 +3103,9 @@
 class B extends A {
 }
 ''');
-    assertHasFix(DartFixKind.MAKE_CLASS_ABSTRACT, '''
+    assertHasFix(
+        DartFixKind.MAKE_CLASS_ABSTRACT,
+        '''
 abstract class A {
   m();
 }
@@ -2736,7 +3133,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_DEAD_CODE, '''
+    assertHasFix(
+        DartFixKind.REMOVE_DEAD_CODE,
+        '''
 main(int p) {
   if (true) {
     print(1);
@@ -2753,7 +3152,9 @@
   print(1);
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_DEAD_CODE, '''
+    assertHasFix(
+        DartFixKind.REMOVE_DEAD_CODE,
+        '''
 int main() {
   print(0);
   return 42;
@@ -2770,7 +3171,9 @@
   print(2);
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_DEAD_CODE, '''
+    assertHasFix(
+        DartFixKind.REMOVE_DEAD_CODE,
+        '''
 int main() {
   print(0);
   return 42;
@@ -2784,7 +3187,9 @@
   int get foo() => 0;
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, '''
+    assertHasFix(
+        DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION,
+        '''
 class A {
   int get foo => 0;
 }
@@ -2800,7 +3205,9 @@
   a.foo();
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION, '''
+    assertHasFix(
+        DartFixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION,
+        '''
 class A {
   int get foo => 0;
 }
@@ -2818,7 +3225,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_UNNECASSARY_CAST, '''
+    assertHasFix(
+        DartFixKind.REMOVE_UNNECASSARY_CAST,
+        '''
 main(Object p) {
   if (p is String) {
     String v = p;
@@ -2837,7 +3246,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_UNUSED_CATCH_CLAUSE, '''
+    assertHasFix(
+        DartFixKind.REMOVE_UNUSED_CATCH_CLAUSE,
+        '''
 main() {
   try {
     throw 42;
@@ -2857,7 +3268,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_UNUSED_CATCH_STACK, '''
+    assertHasFix(
+        DartFixKind.REMOVE_UNUSED_CATCH_STACK,
+        '''
 main() {
   try {
     throw 42;
@@ -2873,7 +3286,9 @@
 main() {
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_UNUSED_IMPORT, '''
+    assertHasFix(
+        DartFixKind.REMOVE_UNUSED_IMPORT,
+        '''
 main() {
 }
 ''');
@@ -2887,7 +3302,9 @@
   Future f;
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_UNUSED_IMPORT, '''
+    assertHasFix(
+        DartFixKind.REMOVE_UNUSED_IMPORT,
+        '''
 import 'dart:async';
 
 main() {
@@ -2903,7 +3320,9 @@
 main() {
 }
 ''');
-    assertHasFix(DartFixKind.REMOVE_UNUSED_IMPORT, '''
+    assertHasFix(
+        DartFixKind.REMOVE_UNUSED_IMPORT,
+        '''
 main() {
 }
 ''');
@@ -2916,7 +3335,9 @@
 import 'no/matter/lib.dart';
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.REPLACE_IMPORT_URI, '''
+    assertHasFix(
+        DartFixKind.REPLACE_IMPORT_URI,
+        '''
 import '../foo/bar/lib.dart';
 ''');
   }
@@ -2927,7 +3348,9 @@
 import 'no/matter/my_lib.dart';
 ''');
     performAllAnalysisTasks();
-    assertHasFix(DartFixKind.REPLACE_IMPORT_URI, '''
+    assertHasFix(
+        DartFixKind.REPLACE_IMPORT_URI,
+        '''
 import 'package:my_pkg/my_lib.dart';
 ''');
   }
@@ -2941,7 +3364,9 @@
   Map<String, var> m;
 }
 ''');
-    assertHasFix(DartFixKind.REPLACE_VAR_WITH_DYNAMIC, '''
+    assertHasFix(
+        DartFixKind.REPLACE_VAR_WITH_DYNAMIC,
+        '''
 class A {
   Map<String, dynamic> m;
 }
@@ -2955,7 +3380,9 @@
 }
 const a = new A();
 ''');
-    assertHasFix(DartFixKind.USE_CONST, '''
+    assertHasFix(
+        DartFixKind.USE_CONST,
+        '''
 class A {
   const A();
 }
@@ -2969,7 +3396,9 @@
   Stirng s = 'abc';
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 main() {
   String s = 'abc';
 }
@@ -2983,7 +3412,9 @@
   MyCalss v = null;
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class MyClass {}
 main() {
   MyClass v = null;
@@ -2998,7 +3429,9 @@
   test(v);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   dynamic v;
   test(v);
@@ -3015,7 +3448,9 @@
   dynamic v = test();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   dynamic v = test();
 }
@@ -3031,7 +3466,9 @@
   int v = myUndefinedFunction(1, 2.0, '3');
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   int v = myUndefinedFunction(1, 2.0, '3');
 }
@@ -3049,7 +3486,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 class A {
   main() {
     int v = myUndefinedFunction(1, 2.0, '3');
@@ -3070,7 +3509,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 class A<T> {
   Map<int, T> items;
   main() {
@@ -3092,7 +3533,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 class A {
   List<int> items;
   main() {
@@ -3106,7 +3549,9 @@
   }
 
   void test_undefinedFunction_create_importType() {
-    addSource('/lib.dart', r'''
+    addSource(
+        '/lib.dart',
+        r'''
 library lib;
 import 'dart:async';
 Future getFuture() => null;
@@ -3117,7 +3562,9 @@
   test(getFuture());
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 import 'lib.dart';
 import 'dart:async';
 main() {
@@ -3135,7 +3582,9 @@
   test(null);
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   test(null);
 }
@@ -3167,7 +3616,9 @@
   v = myUndefinedFunction();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   int v;
   v = myUndefinedFunction();
@@ -3185,7 +3636,9 @@
   v += myUndefinedFunction();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   int v;
   v += myUndefinedFunction();
@@ -3202,7 +3655,9 @@
   0 + myUndefinedFunction();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   0 + myUndefinedFunction();
 }
@@ -3218,7 +3673,9 @@
   int v = myUndefinedFunction();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   int v = myUndefinedFunction();
 }
@@ -3235,7 +3692,9 @@
   foo( myUndefinedFunction() );
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 foo(int p) {}
 main() {
   foo( myUndefinedFunction() );
@@ -3252,7 +3711,9 @@
   return myUndefinedFunction();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 int main() {
   return myUndefinedFunction();
 }
@@ -3268,7 +3729,9 @@
   myUndefinedFunction();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_FUNCTION, '''
+    assertHasFix(
+        DartFixKind.CREATE_FUNCTION,
+        '''
 main() {
   myUndefinedFunction();
 }
@@ -3284,7 +3747,9 @@
   pritn(0);
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 main() {
   print(0);
 }
@@ -3298,7 +3763,9 @@
   myFuntcion();
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 myFunction() {}
 main() {
   myFunction();
@@ -3316,7 +3783,9 @@
   print(x.myFild);
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   int myField;
 }
@@ -3336,7 +3805,9 @@
   print(a.myFild);
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   int myField;
 }
@@ -3355,7 +3826,9 @@
   A.MY_NAM;
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   static int MY_NAME = 1;
 }
@@ -3374,7 +3847,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   int myField;
   main() {
@@ -3406,7 +3881,9 @@
 class B {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A<T> {
   B b;
   Map<int, T> items;
@@ -3433,7 +3910,9 @@
 class B {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A<T> {
   main() {
     T t = new B().compute();
@@ -3460,7 +3939,9 @@
 class B {
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   B b;
   List<int> items;
@@ -3485,7 +3966,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A<T> {
   List<T> items;
   main() {
@@ -3506,7 +3989,9 @@
   A.myUndefinedMethod();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   static void myUndefinedMethod() {
   }
@@ -3526,7 +4011,9 @@
   A.myUndefinedMethod();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   foo() {}
 
@@ -3547,7 +4034,9 @@
   a.myUndefinedMethod();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   void myUndefinedMethod() {
   }
@@ -3585,7 +4074,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   main() {
     myUndefinedMethod(0, 1.0, '3');
@@ -3599,24 +4090,23 @@
     int index = 0;
     _assertLinkedGroup(
         change.linkedEditGroups[index++], ['void myUndefinedMethod(']);
-    _assertLinkedGroup(change.linkedEditGroups[index++], [
-      'myUndefinedMethod(0',
-      'myUndefinedMethod(int'
-    ]);
-    _assertLinkedGroup(change.linkedEditGroups[index++], [
-      'int i'
-    ], expectedSuggestions(
-        LinkedEditSuggestionKind.TYPE, ['int', 'num', 'Object', 'Comparable']));
+    _assertLinkedGroup(change.linkedEditGroups[index++],
+        ['myUndefinedMethod(0', 'myUndefinedMethod(int']);
+    _assertLinkedGroup(
+        change.linkedEditGroups[index++],
+        ['int i'],
+        expectedSuggestions(LinkedEditSuggestionKind.TYPE,
+            ['int', 'num', 'Object', 'Comparable']));
     _assertLinkedGroup(change.linkedEditGroups[index++], ['i,']);
-    _assertLinkedGroup(change.linkedEditGroups[index++], ['double d'],
-        expectedSuggestions(LinkedEditSuggestionKind.TYPE, [
-      'double',
-      'num',
-      'Object',
-      'Comparable'
-    ]));
+    _assertLinkedGroup(
+        change.linkedEditGroups[index++],
+        ['double d'],
+        expectedSuggestions(LinkedEditSuggestionKind.TYPE,
+            ['double', 'num', 'Object', 'Comparable']));
     _assertLinkedGroup(change.linkedEditGroups[index++], ['d,']);
-    _assertLinkedGroup(change.linkedEditGroups[index++], ['String s'],
+    _assertLinkedGroup(
+        change.linkedEditGroups[index++],
+        ['String s'],
         expectedSuggestions(
             LinkedEditSuggestionKind.TYPE, ['String', 'Object', 'Comparable']));
     _assertLinkedGroup(change.linkedEditGroups[index++], ['s)']);
@@ -3630,7 +4120,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   main() {
     int v = myUndefinedMethod();
@@ -3642,10 +4134,8 @@
 ''');
     // linked positions
     _assertLinkedGroup(change.linkedEditGroups[0], ['int myUndefinedMethod(']);
-    _assertLinkedGroup(change.linkedEditGroups[1], [
-      'myUndefinedMethod();',
-      'myUndefinedMethod() {'
-    ]);
+    _assertLinkedGroup(change.linkedEditGroups[1],
+        ['myUndefinedMethod();', 'myUndefinedMethod() {']);
   }
 
   void test_undefinedMethod_createUnqualified_staticFromField() {
@@ -3654,7 +4144,9 @@
   static var f = myUndefinedMethod();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   static var f = myUndefinedMethod();
 
@@ -3672,7 +4164,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   static main() {
     myUndefinedMethod();
@@ -3693,7 +4187,9 @@
   a.myUndefinedMethod();
 }
 ''');
-    assertHasFix(DartFixKind.CREATE_METHOD, '''
+    assertHasFix(
+        DartFixKind.CREATE_METHOD,
+        '''
 class A {
   void myUndefinedMethod() {
   }
@@ -3724,7 +4220,9 @@
   a.myMehtod();
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   myMethod() {}
 }
@@ -3746,7 +4244,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   myMethod() {}
 }
@@ -3767,7 +4267,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   myMethod() {}
   main() {
@@ -3787,7 +4289,9 @@
   x.myFild = 42;
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   int myField;
 }
@@ -3807,7 +4311,9 @@
   a.myFild = 42;
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   int myField;
 }
@@ -3826,7 +4332,9 @@
   }
 }
 ''');
-    assertHasFix(DartFixKind.CHANGE_TO, '''
+    assertHasFix(
+        DartFixKind.CHANGE_TO,
+        '''
 class A {
   int myField;
   main() {
@@ -3844,7 +4352,9 @@
   print((a / b).toInt());
 }
 ''');
-    assertHasFix(DartFixKind.USE_EFFECTIVE_INTEGER_DIVISION, '''
+    assertHasFix(
+        DartFixKind.USE_EFFECTIVE_INTEGER_DIVISION,
+        '''
 main() {
   var a = 5;
   var b = 2;
@@ -3879,7 +4389,7 @@
    * Computes fixes for the given [error] in [testUnit].
    */
   List<Fix> _computeFixes(AnalysisError error) {
-    FixProcessor processor = new FixProcessor(testUnit, error);
+    FixProcessor processor = new FixProcessor(provider, testUnit, error);
     return processor.compute();
   }
 
@@ -3891,8 +4401,9 @@
     provider.newFile('/packages/my_pkg/lib/my_lib.dart', myLibCode);
     // configure SourceFactory
     Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib');
-    UriResolver pkgResolver =
-        new PackageMapUriResolver(provider, {'my_pkg': [myPkgFolder]});
+    UriResolver pkgResolver = new PackageMapUriResolver(provider, {
+      'my_pkg': [myPkgFolder]
+    });
     context.sourceFactory = new SourceFactory(
         [AbstractContextTest.SDK_RESOLVER, resourceResolver, pkgResolver]);
     // force 'my_pkg' resolution
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
new file mode 100644
index 0000000..d9423a4
--- /dev/null
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -0,0 +1,253 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.services.refactoring.organize_directives;
+
+import 'package:analysis_server/src/protocol.dart' hide AnalysisError;
+import 'package:analysis_server/src/services/correction/organize_directives.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../abstract_single_unit.dart';
+
+main() {
+  groupSep = ' | ';
+  defineReflectiveTests(OrganizeDirectivesTest);
+}
+
+@reflectiveTest
+class OrganizeDirectivesTest extends AbstractSingleUnitTest {
+  List<AnalysisError> testErrors;
+
+  void test_remove_unresolvedDirectives() {
+    addSource('/existing_part1.dart', 'part of lib;');
+    addSource('/existing_part2.dart', 'part of lib;');
+    _computeUnitAndErrors(r'''
+library lib;
+
+import 'dart:async';
+import 'dart:noSuchImportSdkLibrary';
+import 'dart:math';
+import 'package:noSuchImportPackage/andLib.dart';
+
+export 'dart:noSuchExportSdkLibrary';
+export 'dart:async';
+export 'package:noSuchExportPackage/andLib.dart';
+export 'dart:math';
+
+part 'existing_part1.dart';
+part 'no_such_part.dart';
+part 'existing_part2.dart';
+
+main() {
+}
+''');
+    // validate change
+    _assertOrganize(
+        r'''
+library lib;
+
+import 'dart:async';
+import 'dart:math';
+
+export 'dart:async';
+export 'dart:math';
+
+part 'existing_part1.dart';
+part 'existing_part2.dart';
+
+main() {
+}
+''',
+        removeUnresolved: true);
+  }
+
+  void test_remove_unusedImports() {
+    _computeUnitAndErrors(r'''
+library lib;
+
+import 'dart:async';
+import 'dart:math';
+import 'dart:convert';
+import 'dart:collection';
+
+main() {
+  print(PI);
+  new HashMap();
+}
+''');
+    // validate change
+    _assertOrganize(
+        r'''
+library lib;
+
+import 'dart:collection';
+import 'dart:math';
+
+main() {
+  print(PI);
+  new HashMap();
+}
+''',
+        removeUnused: true);
+  }
+
+  void test_remove_unusedImports2() {
+    _computeUnitAndErrors(r'''
+import 'dart:async';
+import 'dart:math';
+
+class A {}
+
+main() {
+  Future f;
+}''');
+    // validate change
+    _assertOrganize(
+        r'''
+import 'dart:async';
+
+class A {}
+
+main() {
+  Future f;
+}''',
+        removeUnresolved: true,
+        removeUnused: true);
+  }
+
+  void test_sort() {
+    _computeUnitAndErrors(r'''
+library lib;
+
+export 'dart:bbb';
+import 'dart:bbb';
+export 'package:bbb/bbb.dart';
+export 'http://bbb.com';
+import 'bbb/bbb.dart';
+export 'http://aaa.com';
+import 'http://bbb.com';
+export 'dart:aaa';
+export 'package:aaa/aaa.dart';
+import 'package:bbb/bbb.dart';
+export 'aaa/aaa.dart';
+export 'bbb/bbb.dart';
+import 'dart:aaa';
+import 'package:aaa/aaa.dart';
+import 'aaa/aaa.dart';
+import 'http://aaa.com';
+part 'bbb/bbb.dart';
+part 'aaa/aaa.dart';
+
+main() {
+}
+''');
+    // validate change
+    _assertOrganize(r'''
+library lib;
+
+import 'dart:aaa';
+import 'dart:bbb';
+
+import 'package:aaa/aaa.dart';
+import 'package:bbb/bbb.dart';
+
+import 'http://aaa.com';
+import 'http://bbb.com';
+
+import 'aaa/aaa.dart';
+import 'bbb/bbb.dart';
+
+export 'dart:aaa';
+export 'dart:bbb';
+
+export 'package:aaa/aaa.dart';
+export 'package:bbb/bbb.dart';
+
+export 'http://aaa.com';
+export 'http://bbb.com';
+
+export 'aaa/aaa.dart';
+export 'bbb/bbb.dart';
+
+part 'aaa/aaa.dart';
+part 'bbb/bbb.dart';
+
+main() {
+}
+''');
+  }
+
+  void test_sort_hasComments() {
+    _computeUnitAndErrors(r'''
+// header
+library lib;
+
+import 'c.dart';// c
+import 'a.dart';// aa
+import 'b.dart';// bbb
+
+/** doc */
+main() {
+}
+''');
+    // validate change
+    _assertOrganize(r'''
+// header
+library lib;
+
+import 'a.dart';
+import 'b.dart';
+import 'c.dart';
+// c
+// aa
+// bbb
+
+/** doc */
+main() {
+}
+''');
+  }
+
+  void test_sort_imports_packageAndPath() {
+    _computeUnitAndErrors(r'''
+library lib;
+
+import 'package:product.ui.api.bbb/manager1.dart';
+import 'package:product.ui.api/entity2.dart';
+import 'package:product.ui/entity.dart';
+import 'package:product.ui.api.aaa/manager2.dart';
+import 'package:product.ui.api/entity1.dart';
+import 'package:product2.client/entity.dart';
+''');
+    // validate change
+    _assertOrganize(r'''
+library lib;
+
+import 'package:product.ui/entity.dart';
+import 'package:product.ui.api/entity1.dart';
+import 'package:product.ui.api/entity2.dart';
+import 'package:product.ui.api.aaa/manager2.dart';
+import 'package:product.ui.api.bbb/manager1.dart';
+import 'package:product2.client/entity.dart';
+''');
+  }
+
+  void _assertOrganize(String expectedCode,
+      {bool removeUnresolved: false, bool removeUnused: false}) {
+    DirectiveOrganizer organizer = new DirectiveOrganizer(
+        testCode, testUnit, testErrors,
+        removeUnresolved: removeUnresolved, removeUnused: removeUnused);
+    List<SourceEdit> edits = organizer.organize();
+    String result = SourceEdit.applySequence(testCode, edits);
+    expect(result, expectedCode);
+  }
+
+  void _computeUnitAndErrors(String code) {
+    addTestSource(code);
+    testUnit = context.resolveCompilationUnit2(testSource, testSource);
+    testErrors = context.computeErrors(testSource);
+  }
+}
diff --git a/pkg/analysis_server/test/services/correction/test_all.dart b/pkg/analysis_server/test/services/correction/test_all.dart
index 3f3b03e..418fa67 100644
--- a/pkg/analysis_server/test/services/correction/test_all.dart
+++ b/pkg/analysis_server/test/services/correction/test_all.dart
@@ -11,6 +11,7 @@
 import 'fix_test.dart' as fix_test;
 import 'levenshtein_test.dart' as levenshtein_test;
 import 'name_suggestion_test.dart' as name_suggestion_test;
+import 'organize_directives_test.dart' as organize_directives_test;
 import 'sort_members_test.dart' as sort_members_test;
 import 'source_range_test.dart' as source_range_test;
 import 'status_test.dart' as status_test;
@@ -25,6 +26,7 @@
     fix_test.main();
     levenshtein_test.main();
     name_suggestion_test.main();
+    organize_directives_test.main();
     sort_members_test.main();
     source_range_test.main();
     status_test.main();
diff --git a/pkg/analysis_server/test/source/optimizing_pub_package_map_provider_test.dart b/pkg/analysis_server/test/source/optimizing_pub_package_map_provider_test.dart
deleted file mode 100644
index 4f68485..0000000
--- a/pkg/analysis_server/test/source/optimizing_pub_package_map_provider_test.dart
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library test.source.optimizing_pub_package_map_provider;
-
-import 'dart:convert';
-import 'dart:io' as io;
-
-import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:path/path.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:unittest/unittest.dart';
-
-main() {
-  groupSep = ' | ';
-  defineReflectiveTests(OptimizingPubPackageMapProviderTest);
-  defineReflectiveTests(OptimizingPubPackageMapInfoTest);
-}
-
-@reflectiveTest
-class OptimizingPubPackageMapInfoTest {
-  MemoryResourceProvider resourceProvider;
-
-  int createFile(String path) {
-    return resourceProvider.newFile(path, 'contents').modificationStamp;
-  }
-
-  void createFolder(String path) {
-    resourceProvider.newFolder(path);
-  }
-
-  void modifyFile(String path) {
-    resourceProvider.modifyFile(path, 'contents');
-  }
-
-  void setUp() {
-    resourceProvider = new MemoryResourceProvider();
-  }
-
-  test_isChangedDependency_fileNotPresent() {
-    String path = '/dep';
-    int timestamp = 1;
-    OptimizingPubPackageMapInfo info =
-        new OptimizingPubPackageMapInfo({}, [path].toSet(), {path: timestamp});
-    expect(info.isChangedDependency(path, resourceProvider), isTrue);
-  }
-
-  test_isChangedDependency_matchingTimestamp() {
-    String path = '/dep';
-    int timestamp = createFile(path);
-    OptimizingPubPackageMapInfo info =
-        new OptimizingPubPackageMapInfo({}, [path].toSet(), {path: timestamp});
-    expect(info.isChangedDependency(path, resourceProvider), isFalse);
-  }
-
-  test_isChangedDependency_mismatchedTimestamp() {
-    String path = '/dep';
-    int timestamp = createFile(path);
-    OptimizingPubPackageMapInfo info =
-        new OptimizingPubPackageMapInfo({}, [path].toSet(), {path: timestamp});
-    modifyFile(path);
-    expect(info.isChangedDependency(path, resourceProvider), isTrue);
-  }
-
-  test_isChangedDependency_nonDependency() {
-    OptimizingPubPackageMapInfo info =
-        new OptimizingPubPackageMapInfo({}, ['/dep1'].toSet(), {});
-    expect(info.isChangedDependency('/dep2', resourceProvider), isFalse);
-  }
-
-  test_isChangedDependency_nonFile() {
-    String path = '/dep';
-    int timestamp = 1;
-    createFolder(path);
-    OptimizingPubPackageMapInfo info =
-        new OptimizingPubPackageMapInfo({}, [path].toSet(), {path: timestamp});
-    expect(info.isChangedDependency(path, resourceProvider), isTrue);
-  }
-
-  test_isChangedDependency_noTimestampInfo() {
-    String path = '/dep';
-    OptimizingPubPackageMapInfo info =
-        new OptimizingPubPackageMapInfo({}, [path].toSet(), {});
-    expect(info.isChangedDependency(path, resourceProvider), isTrue);
-  }
-}
-
-@reflectiveTest
-class OptimizingPubPackageMapProviderTest {
-  MemoryResourceProvider resourceProvider;
-  OptimizingPubPackageMapProvider provider;
-  Folder projectFolder;
-  io.ProcessResult pubListResult;
-
-  void setPubListError() {
-    pubListResult = new _MockProcessResult(0, 1, '', 'ERROR');
-  }
-
-  void setPubListResult({Map<String, String> packages: const {},
-      List<String> input_files: const []}) {
-    pubListResult = new _MockProcessResult(0, 0,
-        JSON.encode({'packages': packages, 'input_files': input_files}), '');
-  }
-
-  void setUp() {
-    resourceProvider = new MemoryResourceProvider();
-    provider = new OptimizingPubPackageMapProvider(
-        resourceProvider, null, _runPubList);
-    projectFolder = resourceProvider.newFolder('/my/proj');
-  }
-
-  test_computePackageMap_noPreviousInfo() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    String pkgName = 'foo';
-    String pkgPath = '/pkg/foo';
-    setPubListResult(packages: {pkgName: pkgPath}, input_files: [dep]);
-    OptimizingPubPackageMapInfo info =
-        provider.computePackageMap(projectFolder);
-    expect(info.dependencies, hasLength(1));
-    expect(info.dependencies, contains(dep));
-    expect(info.packageMap, hasLength(1));
-    expect(info.packageMap, contains(pkgName));
-    expect(info.packageMap[pkgName], hasLength(1));
-    expect(info.packageMap[pkgName][0].path, pkgPath);
-    expect(info.modificationTimes, isEmpty);
-  }
-
-  test_computePackageMap_noPreviousInfo_pubListError() {
-    String pubspecLock = posix.join(projectFolder.path, 'pubspec.lock');
-    setPubListError();
-    OptimizingPubPackageMapInfo info =
-        provider.computePackageMap(projectFolder);
-    expect(info.dependencies, hasLength(1));
-    expect(info.dependencies, contains(pubspecLock));
-    expect(info.packageMap, isNull);
-    expect(info.modificationTimes, isEmpty);
-  }
-
-  test_computePackageMap_withPreviousInfo() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    int timestamp = resourceProvider.newFile(dep, 'contents').modificationStamp;
-    setPubListResult(input_files: [dep]);
-    OptimizingPubPackageMapInfo info1 =
-        provider.computePackageMap(projectFolder);
-    OptimizingPubPackageMapInfo info2 =
-        provider.computePackageMap(projectFolder, info1);
-    expect(info2.dependencies, hasLength(1));
-    expect(info2.dependencies, contains(dep));
-    expect(info2.modificationTimes, hasLength(1));
-    expect(info2.modificationTimes, contains(dep));
-    expect(info2.modificationTimes[dep], timestamp);
-  }
-
-  test_computePackageMap_withPreviousInfo_newDependency() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    resourceProvider.newFile(dep, 'contents').modificationStamp;
-    setPubListResult(input_files: []);
-    OptimizingPubPackageMapInfo info1 =
-        provider.computePackageMap(projectFolder);
-    setPubListResult(input_files: [dep]);
-    OptimizingPubPackageMapInfo info2 =
-        provider.computePackageMap(projectFolder, info1);
-    expect(info2.modificationTimes, isEmpty);
-  }
-
-  test_computePackageMap_withPreviousInfo_oldDependencyNoLongerAFile() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    resourceProvider.newFile(dep, 'contents').modificationStamp;
-    setPubListResult(input_files: [dep]);
-    OptimizingPubPackageMapInfo info1 =
-        provider.computePackageMap(projectFolder);
-    resourceProvider.deleteFile(dep);
-    resourceProvider.newFolder(dep);
-    OptimizingPubPackageMapInfo info2 =
-        provider.computePackageMap(projectFolder, info1);
-    expect(info2.modificationTimes, isEmpty);
-  }
-
-  test_computePackageMap_withPreviousInfo_oldDependencyNoLongerPresent() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    resourceProvider.newFile(dep, 'contents').modificationStamp;
-    setPubListResult(input_files: [dep]);
-    OptimizingPubPackageMapInfo info1 =
-        provider.computePackageMap(projectFolder);
-    resourceProvider.deleteFile(dep);
-    OptimizingPubPackageMapInfo info2 =
-        provider.computePackageMap(projectFolder, info1);
-    expect(info2.modificationTimes, isEmpty);
-  }
-
-  test_computePackageMap_withPreviousInfo_oldDependencyNoLongerRelevant() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    resourceProvider.newFile(dep, 'contents').modificationStamp;
-    setPubListResult(input_files: [dep]);
-    OptimizingPubPackageMapInfo info1 =
-        provider.computePackageMap(projectFolder);
-    setPubListResult(input_files: []);
-    OptimizingPubPackageMapInfo info2 =
-        provider.computePackageMap(projectFolder, info1);
-    expect(info2.modificationTimes, isEmpty);
-  }
-
-  test_computePackageMap_withPreviousInfo_pubListError() {
-    String dep = posix.join(projectFolder.path, 'dep');
-    String pubspecLock = posix.join(projectFolder.path, 'pubspec.lock');
-    int timestamp = resourceProvider.newFile(dep, 'contents').modificationStamp;
-    setPubListResult(input_files: [dep]);
-    OptimizingPubPackageMapInfo info1 =
-        provider.computePackageMap(projectFolder);
-    setPubListError();
-    OptimizingPubPackageMapInfo info2 =
-        provider.computePackageMap(projectFolder, info1);
-    expect(info2.dependencies, hasLength(2));
-    expect(info2.dependencies, contains(dep));
-    expect(info2.dependencies, contains(pubspecLock));
-    expect(info2.modificationTimes, hasLength(1));
-    expect(info2.modificationTimes, contains(dep));
-    expect(info2.modificationTimes[dep], timestamp);
-  }
-
-  io.ProcessResult _runPubList(Folder folder) {
-    expect(folder, projectFolder);
-    return pubListResult;
-  }
-}
-
-class _MockProcessResult implements io.ProcessResult {
-  @override
-  final int pid;
-
-  @override
-  final int exitCode;
-
-  @override
-  final stdout;
-
-  @override
-  final stderr;
-
-  _MockProcessResult(this.pid, this.exitCode, this.stdout, this.stderr);
-}
diff --git a/pkg/analysis_server/test/source/test_all.dart b/pkg/analysis_server/test/source/test_all.dart
index 34a617f..3a3e709 100644
--- a/pkg/analysis_server/test/source/test_all.dart
+++ b/pkg/analysis_server/test/source/test_all.dart
@@ -5,13 +5,10 @@
 library test.source;
 
 import 'caching_put_package_map_provider_test.dart' as caching_provider_test;
-import 'optimizing_pub_package_map_provider_test.dart'
-    as optimizing_provider_test;
 import 'package:unittest/unittest.dart';
 
 /// Utility for manually running all tests.
 main() {
   groupSep = ' | ';
   caching_provider_test.main();
-  optimizing_provider_test.main();
 }
diff --git a/pkg/analysis_server/test/src/watch_manager_test.dart b/pkg/analysis_server/test/src/watch_manager_test.dart
index 8d1c4e2..a8d885d 100644
--- a/pkg/analysis_server/test/src/watch_manager_test.dart
+++ b/pkg/analysis_server/test/src/watch_manager_test.dart
@@ -96,7 +96,7 @@
     await _expectEvent(ChangeType.ADD, newFile1.path, [topToken]);
 
     File newFile2 = provider.newFile('/a/b/c/d/lib.dart', '');
-    _expectEvent(ChangeType.ADD, newFile2.path, [topToken, childToken]);
+    return _expectEvent(ChangeType.ADD, newFile2.path, [topToken, childToken]);
   }
 
   Future test_addFolder_singleFolder_multipleTokens() {
@@ -119,7 +119,7 @@
     await _expectEvent(ChangeType.ADD, newFolder.path, [token]);
 
     File newFile = provider.newFile('/a/b/c/lib.dart', '');
-    _expectEvent(ChangeType.ADD, newFile.path, [token]);
+    return _expectEvent(ChangeType.ADD, newFile.path, [token]);
   }
 
   Future test_addFolder_unrelatedFolders() async {
@@ -134,7 +134,7 @@
     await _expectEvent(ChangeType.ADD, newFile1.path, [token1]);
 
     File newFile2 = provider.newFile('/c/d/lib.dart', '');
-    _expectEvent(ChangeType.ADD, newFile2.path, [token2]);
+    return _expectEvent(ChangeType.ADD, newFile2.path, [token2]);
   }
 
   void test_creation() {
@@ -153,15 +153,6 @@
     return _expectEvent(ChangeType.ADD, newFile.path, [token1]);
   }
 
-  Future test_removeFolder_unadded() {
-    Folder folder = provider.getFolder('/a/b');
-    Token token = new Token('token');
-    expect(() => manager.removeFolder(folder, token), throws);
-
-    provider.newFile('/a/b/lib.dart', '');
-    return _expectNoEvent();
-  }
-
   Future test_removeFolder_withChildren() async {
     Folder topFolder = provider.getFolder('/a/b');
     Folder childFolder = provider.getFolder('/a/b/c/d');
@@ -175,7 +166,7 @@
     await _expectEvent(ChangeType.ADD, newFile.path, [childToken]);
 
     provider.newFile('/a/b/lib.dart', '');
-    _expectNoEvent();
+    return _expectNoEvent();
   }
 
   Future test_removeFolder_withNoChildren() {
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 9307059..77faa63 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -18,6 +18,7 @@
 import 'protocol_test.dart' as protocol_test;
 import 'search/test_all.dart' as search_all;
 import 'services/test_all.dart' as services_all;
+import 'server_options_test.dart' as server_options;
 import 'socket_server_test.dart' as socket_server_test;
 import 'source/test_all.dart' as source_all;
 import 'src/test_all.dart' as src_all;
@@ -41,6 +42,7 @@
     protocol_server_test.main();
     protocol_test.main();
     search_all.main();
+    server_options.main();
     services_all.main();
     socket_server_test.main();
     source_all.main();
diff --git a/pkg/analysis_server/tool/spec/codegen_tools.dart b/pkg/analysis_server/tool/spec/codegen_tools.dart
index f388379..078f809 100644
--- a/pkg/analysis_server/tool/spec/codegen_tools.dart
+++ b/pkg/analysis_server/tool/spec/codegen_tools.dart
@@ -102,9 +102,12 @@
   }
 
   /**
-   * Execute [callback], indenting any code it outputs by two spaces.
+   * Execute [callback], indenting any code it outputs.
    */
-  void indent(void callback()) => indentSpecial('  ', '  ', callback);
+  void indent(void callback()) {
+    indentSpecial(codeGeneratorSettings.indent, codeGeneratorSettings.indent,
+      callback);
+  }
 
   /**
    * Execute [callback], using [additionalIndent] to indent any code it outputs.
@@ -237,10 +240,15 @@
    */
   int commentLineLength;
 
+  /**
+   * String used for indenting code.
+   */
+  String indent;
+
   CodeGeneratorSettings({this.languageName: 'java',
       this.lineCommentLineLeader: '// ', this.docCommentStartMarker: '/**',
       this.docCommentLineLeader: ' * ', this.docCommentEndMarker: ' */',
-      this.commentLineLength: 99});
+      this.commentLineLength: 99, this.indent: '  '});
 }
 
 abstract class GeneratedContent {
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index c398e4d..c183dac 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -351,6 +351,23 @@
   public void edit_getRefactoring(String kind, String file, int offset, int length, boolean validateOnly, RefactoringOptions options, GetRefactoringConsumer consumer);
 
   /**
+   * {@code edit.organizeDirectives}
+   *
+   * Organizes all of the directives - removes unused imports and sorts directives of the given Dart
+   * file according to the Dart Style Guide.
+   *
+   * If a request is made for a file that does not exist, does not belong to an analysis root or is
+   * not a Dart file, FILE_NOT_ANALYZED will be generated.
+   *
+   * If directives of the Dart file cannot be organized, for example because it has scan or parse
+   * errors, or by other reasons, ORGANIZE_DIRECTIVES_ERROR will be generated. The message will
+   * provide datails about the reason.
+   *
+   * @param file The Dart file to organize directives in.
+   */
+  public void edit_organizeDirectives(String file, OrganizeDirectivesConsumer consumer);
+
+  /**
    * {@code edit.sortMembers}
    *
    * Sort all of the directives, unit and class members of the given Dart file.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java
index e46c4813..fa91052 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisOptions.java
@@ -45,27 +45,29 @@
   public static final List<AnalysisOptions> EMPTY_LIST = Lists.newArrayList();
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed async feature.
    */
   private final Boolean enableAsync;
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed deferred loading feature.
    */
   private final Boolean enableDeferredLoading;
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed enum feature.
    */
   private final Boolean enableEnums;
 
   /**
+   * Deprecated: this feature is always enabled.
+   *
    * True if the client wants to enable support for the proposed "null aware operators" feature.
    */
   private final Boolean enableNullAwareOperators;
@@ -139,7 +141,7 @@
   }
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed async feature.
    */
@@ -148,7 +150,7 @@
   }
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed deferred loading feature.
    */
@@ -157,7 +159,7 @@
   }
 
   /**
-   * Deprecated
+   * Deprecated: this feature is always enabled.
    *
    * True if the client wants to enable support for the proposed enum feature.
    */
@@ -166,6 +168,8 @@
   }
 
   /**
+   * Deprecated: this feature is always enabled.
+   *
    * True if the client wants to enable support for the proposed "null aware operators" feature.
    */
   public Boolean getEnableNullAwareOperators() {
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index 8e39aff..a8615d2 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -30,6 +30,12 @@
   public static final String CONTENT_MODIFIED = "CONTENT_MODIFIED";
 
   /**
+   * A request specified a FilePath which does not match a file in an analysis root, or the requested
+   * operation is not available for the file.
+   */
+  public static final String FILE_NOT_ANALYZED = "FILE_NOT_ANALYZED";
+
+  /**
    * An "edit.format" request specified a FilePath which does not match a Dart file in an analysis
    * root.
    */
@@ -47,7 +53,7 @@
   public static final String GET_ERRORS_INVALID_FILE = "GET_ERRORS_INVALID_FILE";
 
   /**
-   * An "analysis.getErrors" request specified a FilePath which does not match a file currently
+   * An "analysis.getNavigation" request specified a FilePath which does not match a file currently
    * subject to analysis.
    */
   public static final String GET_NAVIGATION_INVALID_FILE = "GET_NAVIGATION_INVALID_FILE";
@@ -86,6 +92,12 @@
   public static final String NO_INDEX_GENERATED = "NO_INDEX_GENERATED";
 
   /**
+   * An "edit.organizeDirectives" request specified a Dart file that cannot be analyzed. The reason
+   * is described in the message.
+   */
+  public static final String ORGANIZE_DIRECTIVES_ERROR = "ORGANIZE_DIRECTIVES_ERROR";
+
+  /**
    * Another refactoring request was received during processing of this one.
    */
   public static final String REFACTORING_REQUEST_CANCELLED = "REFACTORING_REQUEST_CANCELLED";
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 1d61cb1..6bd7e09 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1697,6 +1697,41 @@
           </field>
         </result>
       </request>
+      <request method="organizeDirectives">
+        <p>
+          Organizes all of the directives - removes unused imports and sorts
+          directives of the given Dart file according to the
+          <a href="https://www.dartlang.org/articles/style-guide/">Dart Style Guide</a>.
+        </p>
+        <p>
+          If a request is made for a file that does not exist, does not belong
+          to an analysis root or is not a Dart file,
+          <tt>FILE_NOT_ANALYZED</tt> will be generated.
+        </p>
+        <p>
+          If directives of the Dart file cannot be organized, for example
+          because it has scan or parse errors, or by other reasons,
+          <tt>ORGANIZE_DIRECTIVES_ERROR</tt> will be generated. The message
+          will provide datails about the reason.
+        </p>
+        <params>
+          <field name="file">
+            <ref>FilePath</ref>
+            <p>
+              The Dart file to organize directives in.
+            </p>
+          </field>
+        </params>
+        <result>
+          <field name="edit">
+            <ref>SourceFileEdit</ref>
+            <p>
+              The file edit that is to be applied to the given file to effect
+              the organizing.
+            </p>
+          </field>
+        </result>
+      </request>
     </domain>
     <domain name="execution">
       <p>
@@ -1988,7 +2023,7 @@
         <object>
           <field name="enableAsync" optional="true">
             <ref>bool</ref>
-            <p><b><i>Deprecated</i></b></p>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed async feature.
@@ -1996,7 +2031,7 @@
           </field>
           <field name="enableDeferredLoading" optional="true">
             <ref>bool</ref>
-            <p><b><i>Deprecated</i></b></p>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed deferred loading feature.
@@ -2004,7 +2039,7 @@
           </field>
           <field name="enableEnums" optional="true">
             <ref>bool</ref>
-            <p><b><i>Deprecated</i></b></p>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed enum feature.
@@ -2012,6 +2047,7 @@
           </field>
           <field name="enableNullAwareOperators" optional="true">
             <ref>bool</ref>
+            <p><b><i>Deprecated</i></b>: this feature is always enabled.</p>
             <p>
               True if the client wants to enable support for the
               proposed "null aware operators" feature.
@@ -3383,6 +3419,14 @@
             </p>
           </value>
           <value>
+            <code>FILE_NOT_ANALYZED</code>
+            <p>
+              A request specified a FilePath which does not match a file in
+              an analysis root, or the requested operation is not available
+              for the file.
+            </p>
+          </value>
+          <value>
             <code>FORMAT_INVALID_FILE</code>
             <p>
               An "edit.format" request specified a FilePath
@@ -3407,7 +3451,7 @@
           <value>
             <code>GET_NAVIGATION_INVALID_FILE</code>
             <p>
-              An "analysis.getErrors" request specified a FilePath
+              An "analysis.getNavigation" request specified a FilePath
               which does not match a file currently subject to
               analysis.
             </p>
@@ -3455,6 +3499,13 @@
             </p>
           </value>
           <value>
+            <code>ORGANIZE_DIRECTIVES_ERROR</code>
+            <p>
+              An "edit.organizeDirectives" request specified a Dart file that
+              cannot be analyzed. The reason is described in the message.
+            </p>
+          </value>
+          <value>
             <code>REFACTORING_REQUEST_CANCELLED</code>
             <p>
               Another refactoring request was received during processing of
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 59a9606..7c67e09 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,23 @@
+## 0.26.0
+
+* No changes from 0.26.0-alpha.2.
+
+## 0.26.0-alpha.2
+
+* Fix highlight range for missing enum constant in switch (issue 23904).
+* Fix analyzer's treatment of `ClassName?.staticMember` to match spec.
+* Implement DEP 34 (less restricted mixins).
+* Fix some implementations of `UriResolver.resolveUri(..)` that did not
+  properly handle the new `actualUri` argument.
+
+## 0.26.0-alpha.1
+
+* Change `ResolutionCopier.visitAwaitExpression` to copy *Type fields.
+
+## 0.26.0-alpha.0
+
+* API change: `UriResolver.resolveUri(..)` now takes an optional `actualUri`.
+
 ## 0.25.3-alpha.0
 
 * Add hook for listening to implicitly analyzed files
@@ -7,6 +27,7 @@
 
 ## 0.25.2
 
+* Requires Dart SDK 1.12-dev or greater
 * Enable null-aware operators (DEP 9) by default.
 * Generic method support in the element model.
 
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 899d6c5..788600b 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -181,14 +181,14 @@
   ResourceUriResolver(this._provider);
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (!_isFileUri(uri)) {
       return null;
     }
     Resource resource =
         _provider.getResource(_provider.pathContext.fromUri(uri));
     if (resource is File) {
-      return resource.createSource(uri);
+      return resource.createSource(actualUri != null ? actualUri : uri);
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/source/package_map_resolver.dart b/pkg/analyzer/lib/source/package_map_resolver.dart
index 82000b9..0fa12ae 100644
--- a/pkg/analyzer/lib/source/package_map_resolver.dart
+++ b/pkg/analyzer/lib/source/package_map_resolver.dart
@@ -44,7 +44,7 @@
   }
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (!isPackageUri(uri)) {
       return null;
     }
diff --git a/pkg/analyzer/lib/source/path_filter.dart b/pkg/analyzer/lib/source/path_filter.dart
index 9ee0070..f4123f8 100644
--- a/pkg/analyzer/lib/source/path_filter.dart
+++ b/pkg/analyzer/lib/source/path_filter.dart
@@ -5,16 +5,33 @@
 library source.path_filter;
 
 import 'package:glob/glob.dart' as glob;
-import 'package:path/path.dart' as pos;
+import 'package:path/path.dart';
 
 /// Filter paths against a set of [ignorePatterns] relative to a [root]
 /// directory. Paths outside of [root] are also ignored.
 class PathFilter {
+  /// The path context to use when manipulating paths.
+  final Context pathContext;
+
+  /// Path that all ignore patterns are relative to.
+  final String root;
+
+  /// List of ignore patterns that paths are tested against.
+  final List<glob.Glob> _ignorePatterns = new List<glob.Glob>();
+
   /// Construct a new path filter rooted at [root] with [ignorePatterns].
-  PathFilter(this.root, List<String> ignorePatterns) {
+  PathFilter(this.pathContext, this.root, List<String> ignorePatterns) {
     setIgnorePatterns(ignorePatterns);
   }
 
+  /// Returns true if [path] should be ignored. A path is ignored if it is not
+  /// contained in [root] or matches one of the ignore patterns.
+  /// [path] is absolute or relative to [root].
+  bool ignored(String path) {
+    path = _canonicalize(path);
+    return !_contained(path) || _match(path);
+  }
+
   /// Set the ignore patterns.
   void setIgnorePatterns(List<String> ignorePatterns) {
     _ignorePatterns.clear();
@@ -25,19 +42,9 @@
     }
   }
 
-  /// Returns true if [path] should be ignored. A path is ignored if it is not
-  /// contained in [root] or matches one of the ignore patterns.
-  /// [path] is absolute or relative to [root].
-  bool ignored(String path) {
-    path = _canonicalize(path);
-    return !_contained(path) || _match(path);
-  }
-
   /// Returns the absolute path of [path], relative to [root].
-  String _canonicalize(String path) => pos.normalize(pos.join(root, path));
-
-  /// Returns the relative portion of [path] from [root].
-  String _relative(String path) => pos.relative(path, from:root);
+  String _canonicalize(String path) =>
+      pathContext.normalize(pathContext.join(root, path));
 
   /// Returns true when [path] is contained inside [root].
   bool _contained(String path) => path.startsWith(root);
@@ -53,9 +60,15 @@
     return false;
   }
 
-  /// Path that all ignore patterns are relative to.
-  final String root;
+  /// Returns the relative portion of [path] from [root].
+  String _relative(String path) => pathContext.relative(path, from: root);
 
-  /// List of ignore patterns that paths are tested against.
-  final List<glob.Glob> _ignorePatterns = new List<glob.Glob>();
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    for (var pattern in _ignorePatterns) {
+      sb.write('$pattern ');
+    }
+    sb.writeln('');
+    return sb.toString();
+  }
 }
diff --git a/pkg/analyzer/lib/source/sdk_ext.dart b/pkg/analyzer/lib/source/sdk_ext.dart
index 696e181..7caad43 100644
--- a/pkg/analyzer/lib/source/sdk_ext.dart
+++ b/pkg/analyzer/lib/source/sdk_ext.dart
@@ -51,7 +51,7 @@
   }
 
   @override
-  Source resolveAbsolute(Uri importUri) {
+  Source resolveAbsolute(Uri importUri, [Uri actualUri]) {
     String libraryName = _libraryName(importUri);
     String partPath = _partPath(importUri);
     // Lookup library name in mappings.
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 1be6dfb..e48a5cc 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -247,7 +247,9 @@
         (this._options.hint && !options.hint) ||
         (this._options.lint && !options.lint) ||
         this._options.preserveComments != options.preserveComments ||
-        this._options.enableStrictCallChecks != options.enableStrictCallChecks;
+        this._options.enableStrictCallChecks !=
+            options.enableStrictCallChecks ||
+        this._options.enableSuperMixins != options.enableSuperMixins;
     int cacheSize = options.cacheSize;
     if (this._options.cacheSize != cacheSize) {
       this._options.cacheSize = cacheSize;
@@ -258,6 +260,7 @@
     this._options.generateSdkErrors = options.generateSdkErrors;
     this._options.dart2jsHint = options.dart2jsHint;
     this._options.enableStrictCallChecks = options.enableStrictCallChecks;
+    this._options.enableSuperMixins = options.enableSuperMixins;
     this._options.hint = options.hint;
     this._options.incremental = options.incremental;
     this._options.incrementalApi = options.incrementalApi;
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index c386c83..f4a8ff3 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -1617,9 +1617,10 @@
 
   @override
   VariableDeclarationList visitVariableDeclarationList(
-      VariableDeclarationList node) => new VariableDeclarationList(null,
-      cloneNodeList(node.metadata), cloneToken(node.keyword),
-      cloneNode(node.type), cloneNodeList(node.variables));
+      VariableDeclarationList node) => new VariableDeclarationList(
+      cloneNode(node.documentationComment), cloneNodeList(node.metadata),
+      cloneToken(node.keyword), cloneNode(node.type),
+      cloneNodeList(node.variables));
 
   @override
   VariableDeclarationStatement visitVariableDeclarationStatement(
@@ -10841,15 +10842,13 @@
   /**
    * The value of the literal.
    */
-  String _value;
+  String value;
 
   /**
    * Initialize a newly created string of characters that are part of a string
    * interpolation.
    */
-  InterpolationString(this.contents, String value) {
-    _value = value;
-  }
+  InterpolationString(this.contents, this.value);
 
   @override
   Token get beginToken => contents;
@@ -10877,18 +10876,6 @@
   @override
   Token get endToken => contents;
 
-  /**
-   * Return the value of the literal.
-   */
-  String get value => _value;
-
-  /**
-   * Set the value of the literal to the given [string].
-   */
-  void set value(String string) {
-    _value = string;
-  }
-
   @override
   accept(AstVisitor visitor) => visitor.visitInterpolationString(this);
 
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 572caab..742f64d 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -3526,9 +3526,7 @@
   }
 
   @deprecated // Use new EvaluationResultImpl(value, errors)
-  EvaluationResultImpl.con2(this.value, List<AnalysisError> errors) {
-    this._errors = errors;
-  }
+  EvaluationResultImpl.con2(this.value, List<AnalysisError> this._errors);
 
   List<AnalysisError> get errors => _errors;
 
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 395dc27..69beffe 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -85,7 +85,8 @@
 
   @override
   bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) => true;
+          [bool withDynamic = false, Set<Element> visitedElements]) =>
+      true;
 
   @override
   bool isSubtypeOf(DartType type) => true;
@@ -98,8 +99,9 @@
 
   @override
   BottomTypeImpl substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) => this;
+          List<DartType> argumentTypes, List<DartType> parameterTypes,
+          [List<FunctionTypeAliasElement> prune]) =>
+      this;
 }
 
 /**
@@ -1154,8 +1156,8 @@
       if (definingClass is! ClassElementImpl) {
         return null;
       }
-      getter = (definingClass as ClassElementImpl)._internalLookUpGetter(
-          getterName, library, false);
+      getter = (definingClass as ClassElementImpl)
+          ._internalLookUpGetter(getterName, library, false);
     }
     return getter;
   }
@@ -1183,8 +1185,8 @@
       if (definingClass is! ClassElementImpl) {
         return null;
       }
-      setter = (definingClass as ClassElementImpl)._internalLookUpSetter(
-          setterName, library, false);
+      setter = (definingClass as ClassElementImpl)
+          ._internalLookUpSetter(setterName, library, false);
     }
     return setter;
   }
@@ -2538,6 +2540,8 @@
   int get nameOffset;
 
   /**
+   * **DEPRECATED** Use `computeNode()` instead.
+   *
    * Return the resolved [AstNode] node that declares this element, or `null` if
    * this element is synthetic or isn't contained in a compilation unit, such as
    * a [LibraryElement].
@@ -4087,7 +4091,8 @@
  * A concrete implementation of a [FieldElement].
  */
 class FieldElementImpl extends PropertyInducingElementImpl
-    with PotentiallyConstVariableElement implements FieldElement {
+    with PotentiallyConstVariableElement
+    implements FieldElement {
   /**
    * An empty list of field elements.
    */
@@ -4961,8 +4966,8 @@
         DartType type = parameter.type;
         if (typeArguments.length != 0 &&
             typeArguments.length == typeParameters.length) {
-          type = (type as TypeImpl).substitute2(
-              typeArguments, typeParameters, newPrune);
+          type = (type as TypeImpl)
+              .substitute2(typeArguments, typeParameters, newPrune);
         } else {
           type = (type as TypeImpl).pruned(newPrune);
         }
@@ -5007,8 +5012,8 @@
         DartType type = parameter.type;
         if (typeArguments.length != 0 &&
             typeArguments.length == typeParameters.length) {
-          type = (type as TypeImpl).substitute2(
-              typeArguments, typeParameters, newPrune);
+          type = (type as TypeImpl)
+              .substitute2(typeArguments, typeParameters, newPrune);
         } else {
           type = (type as TypeImpl).pruned(newPrune);
         }
@@ -5032,8 +5037,8 @@
         DartType type = parameter.type;
         if (typeArguments.length != 0 &&
             typeArguments.length == typeParameters.length) {
-          type = (type as TypeImpl).substitute2(
-              typeArguments, typeParameters, newPrune);
+          type = (type as TypeImpl)
+              .substitute2(typeArguments, typeParameters, newPrune);
         } else {
           type = (type as TypeImpl).pruned(newPrune);
         }
@@ -5215,8 +5220,8 @@
         return false;
       } else if (t.normalParameterTypes.length > 0) {
         for (int i = 0; i < tTypes.length; i++) {
-          if (!(tTypes[i] as TypeImpl).isMoreSpecificThan(
-              sTypes[i], withDynamic)) {
+          if (!(tTypes[i] as TypeImpl)
+              .isMoreSpecificThan(sTypes[i], withDynamic)) {
             return false;
           }
         }
@@ -5236,8 +5241,8 @@
         if (typeT == null) {
           return false;
         }
-        if (!(typeT as TypeImpl).isMoreSpecificThan(
-            namedTypesS[keyS], withDynamic)) {
+        if (!(typeT as TypeImpl)
+            .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) {
           return false;
         }
       }
@@ -5257,8 +5262,8 @@
       if (tOpTypes.length == 0 && sOpTypes.length == 0) {
         // No positional arguments, don't copy contents to new array
         for (int i = 0; i < sTypes.length; i++) {
-          if (!(tTypes[i] as TypeImpl).isMoreSpecificThan(
-              sTypes[i], withDynamic)) {
+          if (!(tTypes[i] as TypeImpl)
+              .isMoreSpecificThan(sTypes[i], withDynamic)) {
             return false;
           }
         }
@@ -5280,8 +5285,8 @@
           sAllTypes[i] = sOpTypes[j];
         }
         for (int i = 0; i < sAllTypes.length; i++) {
-          if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan(
-              sAllTypes[i], withDynamic)) {
+          if (!(tAllTypes[i] as TypeImpl)
+              .isMoreSpecificThan(sAllTypes[i], withDynamic)) {
             return false;
           }
         }
@@ -6633,8 +6638,8 @@
           return false;
         }
         for (int i = 0; i < tArguments.length; i++) {
-          if (!(tArguments[i] as TypeImpl).isMoreSpecificThan(
-              sArguments[i], withDynamic)) {
+          if (!(tArguments[i] as TypeImpl)
+              .isMoreSpecificThan(sArguments[i], withDynamic)) {
             return false;
           }
         }
@@ -6664,14 +6669,14 @@
         return true;
       }
       for (InterfaceType interfaceType in interfaces) {
-        if ((interfaceType as InterfaceTypeImpl).isMoreSpecificThan(
-            type, withDynamic, visitedElements)) {
+        if ((interfaceType as InterfaceTypeImpl)
+            .isMoreSpecificThan(type, withDynamic, visitedElements)) {
           return true;
         }
       }
       for (InterfaceType mixinType in mixins) {
-        if ((mixinType as InterfaceTypeImpl).isMoreSpecificThan(
-            type, withDynamic, visitedElements)) {
+        if ((mixinType as InterfaceTypeImpl)
+            .isMoreSpecificThan(type, withDynamic, visitedElements)) {
           return true;
         }
       }
@@ -7645,8 +7650,8 @@
     for (ImportElement importElement in _imports) {
       LibraryElement importedLibrary = importElement.importedLibrary;
       if (importedLibrary != null) {
-        (importedLibrary as LibraryElementImpl)._addVisibleLibraries(
-            visibleLibraries, true);
+        (importedLibrary as LibraryElementImpl)
+            ._addVisibleLibraries(visibleLibraries, true);
       }
     }
     // add exported libraries
@@ -7654,8 +7659,8 @@
       for (ExportElement exportElement in _exports) {
         LibraryElement exportedLibrary = exportElement.exportedLibrary;
         if (exportedLibrary != null) {
-          (exportedLibrary as LibraryElementImpl)._addVisibleLibraries(
-              visibleLibraries, true);
+          (exportedLibrary as LibraryElementImpl)
+              ._addVisibleLibraries(visibleLibraries, true);
         }
       }
     }
@@ -7749,7 +7754,8 @@
  * A concrete implementation of a [LocalVariableElement].
  */
 class LocalVariableElementImpl extends VariableElementImpl
-    with PotentiallyConstVariableElement implements LocalVariableElement {
+    with PotentiallyConstVariableElement
+    implements LocalVariableElement {
   /**
    * An empty list of field elements.
    */
@@ -8659,7 +8665,8 @@
  * A concrete implementation of a [ParameterElement].
  */
 class ParameterElementImpl extends VariableElementImpl
-    with PotentiallyConstVariableElement implements ParameterElement {
+    with PotentiallyConstVariableElement
+    implements ParameterElement {
   /**
    * An empty list of parameter elements.
    */
@@ -9848,7 +9855,8 @@
  * A concrete implementation of a [TopLevelVariableElement].
  */
 class TopLevelVariableElementImpl extends PropertyInducingElementImpl
-    with PotentiallyConstVariableElement implements TopLevelVariableElement {
+    with PotentiallyConstVariableElement
+    implements TopLevelVariableElement {
   /**
    * An empty list of top-level variable elements.
    */
@@ -10091,8 +10099,8 @@
     }
     List<DartType> newTypes = new List<DartType>(length);
     for (int i = 0; i < length; i++) {
-      newTypes[i] = (types[i] as TypeImpl).substitute2(
-          argumentTypes, parameterTypes, prune);
+      newTypes[i] = (types[i] as TypeImpl)
+          .substitute2(argumentTypes, parameterTypes, prune);
     }
     return newTypes;
   }
@@ -10101,7 +10109,7 @@
 /**
  * A type parameter.
  */
-abstract class TypeParameterElement implements Element {
+abstract class TypeParameterElement implements TypeDefiningElement {
   /**
    * An empty list of type parameter elements.
    */
@@ -10695,8 +10703,9 @@
 
   @override
   VoidTypeImpl substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) => this;
+          List<DartType> argumentTypes, List<DartType> parameterTypes,
+          [List<FunctionTypeAliasElement> prune]) =>
+      this;
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index b93931f..1e5794a 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -608,7 +608,7 @@
       // does not apply to conditional method invocation (i.e. 'C?.m(...)').
       //
       bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
-      ClassElementImpl typeReference = getTypeReference(target, isConditional);
+      ClassElementImpl typeReference = getTypeReference(target);
       if (typeReference != null) {
         staticElement =
             propagatedElement = _resolveElement(typeReference, methodName);
@@ -856,7 +856,7 @@
     // Otherwise, the prefix is really an expression that happens to be a simple
     // identifier and this is really equivalent to a property access node.
     //
-    _resolvePropertyAccess(prefix, identifier, false);
+    _resolvePropertyAccess(prefix, identifier);
     return null;
   }
 
@@ -912,8 +912,7 @@
       return null;
     }
     SimpleIdentifier propertyName = node.propertyName;
-    _resolvePropertyAccess(target, propertyName,
-        node.operator.type == sc.TokenType.QUESTION_PERIOD);
+    _resolvePropertyAccess(target, propertyName);
     return null;
   }
 
@@ -2416,7 +2415,7 @@
   }
 
   void _resolvePropertyAccess(
-      Expression target, SimpleIdentifier propertyName, bool isConditional) {
+      Expression target, SimpleIdentifier propertyName) {
     DartType staticType = _getStaticType(target);
     DartType propagatedType = _getPropagatedType(target);
     Element staticElement = null;
@@ -2427,7 +2426,7 @@
     // hierarchy, instead we just look for the member in the type only.  This
     // does not apply to conditional property accesses (i.e. 'C?.m').
     //
-    ClassElementImpl typeReference = getTypeReference(target, isConditional);
+    ClassElementImpl typeReference = getTypeReference(target);
     if (typeReference != null) {
       // TODO(brianwilkerson) Why are we setting the propagated element here?
       // It looks wrong.
@@ -2640,12 +2639,10 @@
   /**
    * Checks whether the given [expression] is a reference to a class. If it is
    * then the element representing the class is returned, otherwise `null` is
-   * returned.  [isConditional] indicates whether [expression] is to the left
-   * of a '?.' opertator.
+   * returned.
    */
-  static ClassElementImpl getTypeReference(
-      Expression expression, bool isConditional) {
-    if (!isConditional && expression is Identifier) {
+  static ClassElementImpl getTypeReference(Expression expression) {
+    if (expression is Identifier) {
       Element staticElement = expression.staticElement;
       if (staticElement is ClassElementImpl) {
         return staticElement;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 649c2be..5086437 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1118,7 +1118,9 @@
         this._options.dart2jsHint != options.dart2jsHint ||
         (this._options.hint && !options.hint) ||
         this._options.preserveComments != options.preserveComments ||
-        this._options.enableStrictCallChecks != options.enableStrictCallChecks;
+        this._options.enableStrictCallChecks !=
+            options.enableStrictCallChecks ||
+        this._options.enableSuperMixins != options.enableSuperMixins;
     int cacheSize = options.cacheSize;
     if (this._options.cacheSize != cacheSize) {
       this._options.cacheSize = cacheSize;
@@ -1144,6 +1146,7 @@
     this._options.generateSdkErrors = options.generateSdkErrors;
     this._options.dart2jsHint = options.dart2jsHint;
     this._options.enableStrictCallChecks = options.enableStrictCallChecks;
+    this._options.enableSuperMixins = options.enableSuperMixins;
     this._options.hint = options.hint;
     this._options.incremental = options.incremental;
     this._options.incrementalApi = options.incrementalApi;
@@ -6149,6 +6152,12 @@
   bool get enableStrictCallChecks;
 
   /**
+   * Return `true` if mixins are allowed to inherit from types other than
+   * Object, and are allowed to reference `super`.
+   */
+  bool get enableSuperMixins;
+
+  /**
    * Return `true` if errors, warnings and hints should be generated for sources
    * that are implicitly being analyzed. The default value is `true`.
    */
@@ -6252,6 +6261,12 @@
   bool enableStrictCallChecks = false;
 
   /**
+   * A flag indicating whether mixins are allowed to inherit from types other
+   * than Object, and are allowed to reference `super`.
+   */
+  bool enableSuperMixins = false;
+
+  /**
    * A flag indicating whether errors, warnings and hints should be generated
    * for sources that are implicitly being analyzed.
    */
@@ -6317,6 +6332,7 @@
     cacheSize = options.cacheSize;
     dart2jsHint = options.dart2jsHint;
     enableStrictCallChecks = options.enableStrictCallChecks;
+    enableSuperMixins = options.enableSuperMixins;
     generateImplicitErrors = options.generateImplicitErrors;
     generateSdkErrors = options.generateSdkErrors;
     hint = options.hint;
@@ -6337,6 +6353,7 @@
     cacheSize = options.cacheSize;
     dart2jsHint = options.dart2jsHint;
     enableStrictCallChecks = options.enableStrictCallChecks;
+    enableSuperMixins = options.enableSuperMixins;
     generateImplicitErrors = options.generateImplicitErrors;
     generateSdkErrors = options.generateSdkErrors;
     hint = options.hint;
@@ -6712,8 +6729,7 @@
    * [retentionPolicy] will be used to determine which pieces of data to remove
    * from the cache.
    */
-  CachePartition(this.context, int maxCacheSize, this._retentionPolicy) {
-    this._maxCacheSize = maxCacheSize;
+  CachePartition(this.context, this._maxCacheSize, this._retentionPolicy) {
     _recentlyUsed = new List<Source>();
   }
 
@@ -7370,11 +7386,7 @@
   /**
    * Initialize a newly created pair from the given [library] and [entryPairs].
    */
-  CycleBuilder_LibraryPair(ResolvableLibrary library,
-      List<CycleBuilder_SourceEntryPair> entryPairs) {
-    this.library = library;
-    this.entryPairs = entryPairs;
-  }
+  CycleBuilder_LibraryPair(this.library, this.entryPairs);
 }
 
 /**
@@ -7396,10 +7408,7 @@
   /**
    * Initialize a newly created pair from the given [source] and [entry].
    */
-  CycleBuilder_SourceEntryPair(Source source, DartEntry entry) {
-    this.source = source;
-    this.entry = entry;
-  }
+  CycleBuilder_SourceEntryPair(this.source, this.entry);
 }
 
 /**
@@ -8397,7 +8406,8 @@
       // Use the ErrorVerifier to compute the rest of the errors.
       //
       ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
-          libraryElement, typeProvider, new InheritanceManager(libraryElement));
+          libraryElement, typeProvider, new InheritanceManager(libraryElement),
+          context.analysisOptions.enableSuperMixins);
       _unit.accept(errorVerifier);
       _errors = errorListener.getErrorsForSource(source);
     });
@@ -8956,13 +8966,8 @@
   int _newLength = 0;
 
   IncrementalAnalysisCache(this.librarySource, this.source, this.resolvedUnit,
-      this.oldContents, String newContents, int offset, int oldLength,
-      int newLength) {
-    this._newContents = newContents;
-    this._offset = offset;
-    this._oldLength = oldLength;
-    this._newLength = newLength;
-  }
+      this.oldContents, this._newContents, this._offset, this._oldLength,
+      this._newLength);
 
   /**
    * Determine if the cache contains source changes that need to be analyzed
@@ -10832,8 +10837,9 @@
     //
     PerformanceStatistics.errors.makeCurrentWhile(() {
       ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
-      ErrorVerifier errorVerifier = new ErrorVerifier(
-          errorReporter, _libraryElement, typeProvider, inheritanceManager);
+      ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
+          _libraryElement, typeProvider, inheritanceManager,
+          context.analysisOptions.enableSuperMixins);
       unit.accept(errorVerifier);
       // TODO(paulberry): as a temporary workaround for issue 21572,
       // ConstantVerifier is being run right after ConstantValueComputer, so we
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index c667af7..0964a8c 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -40,9 +40,9 @@
     ErrorCode errorCode2 = o2.errorCode;
     ErrorSeverity errorSeverity1 = errorCode1.errorSeverity;
     ErrorSeverity errorSeverity2 = errorCode2.errorSeverity;
-    ErrorType errorType1 = errorCode1.type;
-    ErrorType errorType2 = errorCode2.type;
     if (errorSeverity1 == errorSeverity2) {
+      ErrorType errorType1 = errorCode1.type;
+      ErrorType errorType2 = errorCode2.type;
       return errorType1.compareTo(errorType2);
     } else {
       return errorSeverity2.compareTo(errorSeverity1);
@@ -80,7 +80,7 @@
    * The number of characters from the offset to the end of the source which
    * encompasses the compilation error.
    */
-  int _length = 0;
+  int length = 0;
 
   /**
    * A flag indicating whether this error can be shown to be a non-issue because
@@ -94,9 +94,8 @@
    * [length]. The error will have the given [errorCode] and the list of
    * [arguments] will be used to complete the message.
    */
-  AnalysisError(this.source, this.offset, int length, this.errorCode,
+  AnalysisError(this.source, this.offset, this.length, this.errorCode,
       [List<Object> arguments]) {
-    this._length = length;
     this._message = formatList(errorCode.message, arguments);
     String correctionTemplate = errorCode.correction;
     if (correctionTemplate != null) {
@@ -141,13 +140,6 @@
   }
 
   /**
-   * Return the length of the error location, that is, the number of characters
-   * from the offset to the end of the source which encompasses the compilation
-   * error.
-   */
-  int get length => _length;
-
-  /**
    * Return the message to be displayed for this error. The message should
    * indicate what is wrong and why it is wrong.
    */
@@ -167,7 +159,7 @@
     if (!identical(errorCode, other.errorCode)) {
       return false;
     }
-    if (offset != other.offset || _length != other._length) {
+    if (offset != other.offset || length != other.length) {
       return false;
     }
     if (isStaticOnly != other.isStaticOnly) {
@@ -197,7 +189,7 @@
     buffer.write("(");
     buffer.write(offset);
     buffer.write("..");
-    buffer.write(offset + _length - 1);
+    buffer.write(offset + length - 1);
     buffer.write("): ");
     //buffer.write("(" + lineNumber + ":" + columnNumber + "): ");
     buffer.write(_message);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index e80e02a..9e25a85 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -255,10 +255,16 @@
   List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT;
 
   /**
+   * If `true`, mixins are allowed to inherit from types other than Object, and
+   * are allowed to reference `super`.
+   */
+  final bool enableSuperMixins;
+
+  /**
    * Initialize a newly created error verifier.
    */
   ErrorVerifier(this._errorReporter, this._currentLibrary, this._typeProvider,
-      this._inheritanceManager) {
+      this._inheritanceManager, this.enableSuperMixins) {
     this._isInSystemLibrary = _currentLibrary.source.isInSystemLibrary;
     this._hasExtUri = _currentLibrary.hasExtUri;
     _isEnclosingConstructorConst = false;
@@ -859,9 +865,7 @@
     Expression target = node.realTarget;
     SimpleIdentifier methodName = node.methodName;
     if (target != null) {
-      bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
-      ClassElement typeReference =
-          ElementResolver.getTypeReference(target, isConditional);
+      ClassElement typeReference = ElementResolver.getTypeReference(target);
       _checkForStaticAccessToInstanceMember(typeReference, methodName);
       _checkForInstanceAccessToStaticMember(typeReference, methodName);
     } else {
@@ -898,7 +902,7 @@
   Object visitPrefixedIdentifier(PrefixedIdentifier node) {
     if (node.parent is! Annotation) {
       ClassElement typeReference =
-          ElementResolver.getTypeReference(node.prefix, false);
+          ElementResolver.getTypeReference(node.prefix);
       SimpleIdentifier name = node.identifier;
       _checkForStaticAccessToInstanceMember(typeReference, name);
       _checkForInstanceAccessToStaticMember(typeReference, name);
@@ -923,7 +927,7 @@
   Object visitPropertyAccess(PropertyAccess node) {
     bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
     ClassElement typeReference =
-        ElementResolver.getTypeReference(node.realTarget, isConditional);
+        ElementResolver.getTypeReference(node.realTarget);
     SimpleIdentifier propertyName = node.propertyName;
     _checkForStaticAccessToInstanceMember(typeReference, propertyName);
     _checkForInstanceAccessToStaticMember(typeReference, propertyName);
@@ -1653,7 +1657,8 @@
         if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) {
           problemReported = true;
         }
-        if (_checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
+        if (!enableSuperMixins &&
+            _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
           problemReported = true;
         }
         if (_checkForMixinReferencesSuper(mixinName, mixinElement)) {
@@ -4113,9 +4118,11 @@
       return false;
     }
     for (int i = 0; i < nameCount; i++) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH, statement,
-          [constantNames[i]]);
+      int offset = statement.offset;
+      int end = statement.rightParenthesis.end;
+      _errorReporter.reportErrorForOffset(
+          CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH, offset,
+          end - offset, [constantNames[i]]);
     }
     return true;
   }
@@ -4209,7 +4216,7 @@
    */
   bool _checkForMixinReferencesSuper(
       TypeName mixinName, ClassElement mixinElement) {
-    if (mixinElement.hasReferenceToSuper) {
+    if (!enableSuperMixins && mixinElement.hasReferenceToSuper) {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.MIXIN_REFERENCES_SUPER, mixinName,
           [mixinElement.name]);
diff --git a/pkg/analyzer/lib/src/generated/html.dart b/pkg/analyzer/lib/src/generated/html.dart
index 99b0d51..3bccaab 100644
--- a/pkg/analyzer/lib/src/generated/html.dart
+++ b/pkg/analyzer/lib/src/generated/html.dart
@@ -1160,11 +1160,7 @@
 
   int length = 0;
 
-  XmlExpression_Reference(Element element, int offset, int length) {
-    this.element = element;
-    this.offset = offset;
-    this.length = length;
-  }
+  XmlExpression_Reference(this.element, this.offset, this.length);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 78481ce..2fcef7b 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -23,7 +23,7 @@
         VERIFY_ERRORS;
 import 'package:analyzer/task/dart.dart'
     show DART_ERRORS, LibrarySpecificUnit, PARSED_UNIT, TOKEN_STREAM;
-import 'package:analyzer/task/general.dart' show CONTENT;
+import 'package:analyzer/task/general.dart' show CONTENT, LINE_INFO;
 import 'package:analyzer/task/model.dart' show ResultDescriptor;
 
 import 'ast.dart';
@@ -1233,7 +1233,8 @@
       ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
       ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
           _definingLibrary, _typeProvider,
-          new InheritanceManager(_definingLibrary));
+          new InheritanceManager(_definingLibrary),
+          _context.analysisOptions.enableSuperMixins);
       if (_resolutionContext.enclosingClassDeclaration != null) {
         errorVerifier.visitClassDeclarationIncrementally(
             _resolutionContext.enclosingClassDeclaration);
@@ -1274,6 +1275,7 @@
   int _updateEndOld;
   int _updateEndNew;
 
+  LineInfo _newLineInfo;
   List<AnalysisError> _newScanErrors = <AnalysisError>[];
   List<AnalysisError> _newParseErrors = <AnalysisError>[];
 
@@ -1508,6 +1510,7 @@
     CharSequenceReader reader = new CharSequenceReader(code);
     Scanner scanner = new Scanner(_unitSource, reader, errorListener);
     Token token = scanner.tokenize();
+    _newLineInfo = new LineInfo(scanner.lineStarts);
     _newScanErrors = errorListener.errors;
     return token;
   }
@@ -1564,6 +1567,7 @@
     _newSourceEntry.setState(SCAN_ERRORS, CacheState.INVALID);
     List<TargetedResult> scanDeps =
         <TargetedResult>[new TargetedResult(_unitSource, CONTENT)];
+    _newSourceEntry.setValue(LINE_INFO, _newLineInfo, scanDeps);
     _newSourceEntry.setValue(SCAN_ERRORS, _newScanErrors, scanDeps);
     // parse results
     List<TargetedResult> parseDeps =
@@ -1574,6 +1578,7 @@
   }
 
   void _updateEntry_OLD() {
+    _oldEntry.setValue(SourceEntry.LINE_INFO, _newLineInfo);
     _oldEntry.setValue(DartEntry.SCAN_ERRORS, _newScanErrors);
     _oldEntry.setValue(DartEntry.PARSE_ERRORS, _newParseErrors);
   }
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 8581fa4..df3187b 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -9428,8 +9428,13 @@
   @override
   bool visitAwaitExpression(AwaitExpression node) {
     AwaitExpression toNode = this._toNode as AwaitExpression;
-    return _and(_isEqualTokens(node.awaitKeyword, toNode.awaitKeyword),
-        _isEqualNodes(node.expression, toNode.expression));
+    if (_and(_isEqualTokens(node.awaitKeyword, toNode.awaitKeyword),
+        _isEqualNodes(node.expression, toNode.expression))) {
+      toNode.propagatedType = node.propagatedType;
+      toNode.staticType = node.staticType;
+      return true;
+    }
+    return false;
   }
 
   @override
@@ -10033,12 +10038,16 @@
   @override
   bool visitLibraryDirective(LibraryDirective node) {
     LibraryDirective toNode = this._toNode as LibraryDirective;
-    return _and(
+    if (_and(
         _isEqualNodes(node.documentationComment, toNode.documentationComment),
         _isEqualNodeLists(node.metadata, toNode.metadata),
         _isEqualTokens(node.libraryKeyword, toNode.libraryKeyword),
         _isEqualNodes(node.name, toNode.name),
-        _isEqualTokens(node.semicolon, toNode.semicolon));
+        _isEqualTokens(node.semicolon, toNode.semicolon))) {
+      toNode.element = node.element;
+      return true;
+    }
+    return false;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 49fc6c7..8110c8c 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -293,9 +293,12 @@
    * @return `true` if and only if an hint code is generated on the passed node
    * See [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
    */
-  bool _checkForArgumentTypeNotAssignable(Expression expression,
-      DartType expectedStaticType, DartType actualStaticType,
-      DartType expectedPropagatedType, DartType actualPropagatedType,
+  bool _checkForArgumentTypeNotAssignable(
+      Expression expression,
+      DartType expectedStaticType,
+      DartType actualStaticType,
+      DartType expectedPropagatedType,
+      DartType actualPropagatedType,
       ErrorCode hintCode) {
     //
     // Warning case: test static type information
@@ -347,8 +350,10 @@
     DartType propagatedParameterType = propagatedParameterElement == null
         ? null
         : propagatedParameterElement.type;
-    return _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
-        staticParameterType, propagatedParameterType,
+    return _checkForArgumentTypeNotAssignableWithExpectedTypes(
+        argument,
+        staticParameterType,
+        propagatedParameterType,
         HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
   }
 
@@ -364,11 +369,17 @@
    * See [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
    */
   bool _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          Expression expression, DartType expectedStaticType,
-          DartType expectedPropagatedType, ErrorCode errorCode) =>
-      _checkForArgumentTypeNotAssignable(expression, expectedStaticType,
-          expression.staticType, expectedPropagatedType,
-          expression.propagatedType, errorCode);
+          Expression expression,
+          DartType expectedStaticType,
+          DartType expectedPropagatedType,
+          ErrorCode errorCode) =>
+      _checkForArgumentTypeNotAssignable(
+          expression,
+          expectedStaticType,
+          expression.staticType,
+          expectedPropagatedType,
+          expression.propagatedType,
+          errorCode);
 
   /**
    * This verifies that the passed arguments can be assigned to their corresponding parameters.
@@ -541,7 +552,8 @@
     }
     if (importedLibrary.hasLoadLibraryFunction) {
       _errorReporter.reportErrorForNode(
-          HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION, node,
+          HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION,
+          node,
           [importedLibrary.name]);
       return true;
     }
@@ -740,12 +752,16 @@
   AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
     if (existing is PropertyAccessorElement && duplicate is MethodElement) {
       if (existing.nameOffset < duplicate.nameOffset) {
-        return new AnalysisError(duplicate.source, duplicate.nameOffset,
+        return new AnalysisError(
+            duplicate.source,
+            duplicate.nameOffset,
             duplicate.displayName.length,
             CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME,
             [existing.displayName]);
       } else {
-        return new AnalysisError(existing.source, existing.nameOffset,
+        return new AnalysisError(
+            existing.source,
+            existing.nameOffset,
             existing.displayName.length,
             CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME,
             [existing.displayName]);
@@ -919,8 +935,11 @@
             new ConstantEvaluationEngine(_typeProvider, declaredVariables);
         ConstantVisitor constantVisitor =
             new ConstantVisitor(evaluationEngine, _errorReporter);
-        evaluationEngine.evaluateConstructorCall(node,
-            node.argumentList.arguments, constructor, constantVisitor,
+        evaluationEngine.evaluateConstructorCall(
+            node,
+            node.argumentList.arguments,
+            constructor,
+            constantVisitor,
             _errorReporter);
       }
     }
@@ -976,7 +995,8 @@
           if (_implementsEqualsWhenNotAllowed(type)) {
             _errorReporter.reportErrorForNode(
                 CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
-                key, [type.displayName]);
+                key,
+                [type.displayName]);
           }
         }
       } else {
@@ -1040,7 +1060,8 @@
             if (firstType != nType) {
               _errorReporter.reportErrorForNode(
                   CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
-                  expression, [expression.toSource(), firstType.displayName]);
+                  expression,
+                  [expression.toSource(), firstType.displayName]);
               foundError = true;
             }
           }
@@ -1093,7 +1114,8 @@
     // report error
     _errorReporter.reportErrorForToken(
         CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
-        node.switchKeyword, [type.displayName]);
+        node.switchKeyword,
+        [type.displayName]);
     return true;
   }
 
@@ -1299,11 +1321,13 @@
                   new ErrorReporter(errorListener, _errorReporter.source);
               DartObjectImpl result = initializer.accept(new ConstantVisitor(
                   new ConstantEvaluationEngine(
-                      _typeProvider, declaredVariables), subErrorReporter));
+                      _typeProvider, declaredVariables),
+                  subErrorReporter));
               if (result == null) {
                 _errorReporter.reportErrorForNode(
                     CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
-                    errorSite, [variableDeclaration.name.name]);
+                    errorSite,
+                    [variableDeclaration.name.name]);
               }
             }
           }
@@ -1625,10 +1649,10 @@
               int offset = catchClause.offset;
               int length = lastCatchClause.end - offset;
               _errorReporter.reportErrorForOffset(
-                  HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, offset, length, [
-                currentType.displayName,
-                type.displayName
-              ]);
+                  HintCode.DEAD_CODE_ON_CATCH_SUBTYPE,
+                  offset,
+                  length,
+                  [currentType.displayName, type.displayName]);
               return null;
             }
           }
@@ -1925,9 +1949,10 @@
     String uri = _getStringValue(node.uri);
     if (uri != null) {
       LibraryElement library = _enclosingUnit.library;
-      ExportElement exportElement = _findExport(library.exports,
-          _enclosingUnit.context.sourceFactory.resolveUri(
-              _enclosingUnit.source, uri));
+      ExportElement exportElement = _findExport(
+          library.exports,
+          _enclosingUnit.context.sourceFactory
+              .resolveUri(_enclosingUnit.source, uri));
       node.element = exportElement;
     }
     return super.visitExportDirective(node);
@@ -2031,9 +2056,11 @@
     String uri = _getStringValue(node.uri);
     if (uri != null) {
       LibraryElement library = _enclosingUnit.library;
-      ImportElement importElement = _findImport(library.imports,
-          _enclosingUnit.context.sourceFactory.resolveUri(
-              _enclosingUnit.source, uri), node.prefix);
+      ImportElement importElement = _findImport(
+          library.imports,
+          _enclosingUnit.context.sourceFactory
+              .resolveUri(_enclosingUnit.source, uri),
+          node.prefix);
       node.element = importElement;
     }
     return super.visitImportDirective(node);
@@ -2084,8 +2111,8 @@
   Object visitPartDirective(PartDirective node) {
     String uri = _getStringValue(node.uri);
     if (uri != null) {
-      Source partSource = _enclosingUnit.context.sourceFactory.resolveUri(
-          _enclosingUnit.source, uri);
+      Source partSource = _enclosingUnit.context.sourceFactory
+          .resolveUri(_enclosingUnit.source, uri);
       node.element = _findPart(_enclosingUnit.library.parts, partSource);
     }
     return super.visitPartDirective(node);
@@ -3012,8 +3039,8 @@
       } else {
         String message =
             "Exception caught in ElementBuilder.visitMethodDeclaration()";
-        AnalysisEngine.instance.logger.logError(
-            message, new CaughtException(exception, stackTrace));
+        AnalysisEngine.instance.logger
+            .logError(message, new CaughtException(exception, stackTrace));
       }
     } finally {
       if (node.name.staticElement == null) {
@@ -3025,7 +3052,8 @@
         buffer.write(" in ");
         buffer.write(classNode.name);
         buffer.write(" was not set while trying to resolve types.");
-        AnalysisEngine.instance.logger.logError(buffer.toString(),
+        AnalysisEngine.instance.logger.logError(
+            buffer.toString(),
             new CaughtException(
                 new AnalysisException(buffer.toString()), null));
       }
@@ -3726,8 +3754,10 @@
     if (_hasHiddenName) {
       Element hiddenElement = _hiddenElements[name];
       if (hiddenElement != null) {
-        errorListener.onError(new AnalysisError(getSource(identifier),
-            identifier.offset, identifier.length,
+        errorListener.onError(new AnalysisError(
+            getSource(identifier),
+            identifier.offset,
+            identifier.length,
             CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
         return hiddenElement;
       }
@@ -4758,12 +4788,7 @@
    * @param classToTagsMap a table mapping the classes defined in the HTML file to an array
    *          containing the names of tags with that class
    */
-  HtmlTagInfo(List<String> allTags, HashMap<String, String> idToTagMap,
-      HashMap<String, List<String>> classToTagsMap) {
-    this.allTags = allTags;
-    this.idToTagMap = idToTagMap;
-    this.classToTagsMap = classToTagsMap;
-  }
+  HtmlTagInfo(this.allTags, this.idToTagMap, this.classToTagsMap);
 
   /**
    * Return an array containing the tags that have the given class, or {@code null} if there are no
@@ -5678,7 +5703,8 @@
    * @return the passed function type with any parameterized types substituted
    */
   FunctionType substituteTypeArgumentsInMemberFromInheritance(
-      FunctionType baseFunctionType, String memberName,
+      FunctionType baseFunctionType,
+      String memberName,
       InterfaceType definingType) {
     // if the baseFunctionType is null, or does not have any parameters,
     // return it.
@@ -6235,12 +6261,12 @@
               if (!classHasMember) {
                 String firstTwoFuntionTypesStr =
                     "${executableElementTypes[0]}, ${executableElementTypes[1]}";
-                _reportError(classElt, classElt.nameOffset,
+                _reportError(
+                    classElt,
+                    classElt.nameOffset,
                     classElt.displayName.length,
-                    StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE, [
-                  key,
-                  firstTwoFuntionTypesStr
-                ]);
+                    StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE,
+                    [key, firstTwoFuntionTypesStr]);
               }
             } else {
               //
@@ -6252,9 +6278,8 @@
               // Tests: test_getMapOfMembersInheritedFromInterfaces_
               // union_multipleSubtypes_*
               //
-              List<ExecutableElement> elementArrayToMerge =
-                  new List<ExecutableElement>(
-                      subtypesOfAllOtherTypesIndexes.length);
+              List<ExecutableElement> elementArrayToMerge = new List<
+                  ExecutableElement>(subtypesOfAllOtherTypesIndexes.length);
               for (int i = 0; i < elementArrayToMerge.length; i++) {
                 elementArrayToMerge[i] =
                     elements[subtypesOfAllOtherTypesIndexes[i]];
@@ -6265,7 +6290,9 @@
             }
           }
         } else {
-          _reportError(classElt, classElt.nameOffset,
+          _reportError(
+              classElt,
+              classElt.nameOffset,
               classElt.displayName.length,
               StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD,
               [key]);
@@ -6388,8 +6415,11 @@
       }
       namedParametersList.addAll(_getNamedParameterNames(element));
     }
-    return _createSyntheticExecutableElement(elementArrayToMerge,
-        elementArrayToMerge[0].displayName, r, h - r,
+    return _createSyntheticExecutableElement(
+        elementArrayToMerge,
+        elementArrayToMerge[0].displayName,
+        r,
+        h - r,
         new List.from(namedParametersList));
   }
 
@@ -6405,8 +6435,10 @@
    * @return the created synthetic element
    */
   static ExecutableElement _createSyntheticExecutableElement(
-      List<ExecutableElement> elementArrayToMerge, String name,
-      int numOfRequiredParameters, int numOfPositionalParameters,
+      List<ExecutableElement> elementArrayToMerge,
+      String name,
+      int numOfRequiredParameters,
+      int numOfPositionalParameters,
       List<String> namedParameters) {
     DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
     SimpleIdentifier nameIdentifier = new SimpleIdentifier(
@@ -6788,8 +6820,8 @@
   LibraryElementImpl get libraryElement {
     if (_libraryElement == null) {
       try {
-        _libraryElement = _analysisContext
-            .computeLibraryElement(librarySource) as LibraryElementImpl;
+        _libraryElement = _analysisContext.computeLibraryElement(librarySource)
+            as LibraryElementImpl;
       } on AnalysisException catch (exception, stackTrace) {
         AnalysisEngine.instance.logger.logError(
             "Could not compute library element for ${librarySource.fullName}",
@@ -6866,9 +6898,12 @@
       Source source =
           _analysisContext.sourceFactory.resolveUri(librarySource, uriContent);
       if (!_analysisContext.exists(source)) {
-        errorListener.onError(new AnalysisError(librarySource,
-            uriLiteral.offset, uriLiteral.length,
-            CompileTimeErrorCode.URI_DOES_NOT_EXIST, [uriContent]));
+        errorListener.onError(new AnalysisError(
+            librarySource,
+            uriLiteral.offset,
+            uriLiteral.length,
+            CompileTimeErrorCode.URI_DOES_NOT_EXIST,
+            [uriContent]));
       }
       return source;
     } on URISyntaxException {
@@ -6973,21 +7008,24 @@
           String partLibraryName =
               _getPartLibraryName(partSource, partUnit, directivesToResolve);
           if (partLibraryName == null) {
-            _errorListener.onError(new AnalysisError(librarySource,
-                partUri.offset, partUri.length,
-                CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSource()]));
+            _errorListener.onError(new AnalysisError(
+                librarySource,
+                partUri.offset,
+                partUri.length,
+                CompileTimeErrorCode.PART_OF_NON_PART,
+                [partUri.toSource()]));
           } else if (libraryNameNode == null) {
             // TODO(brianwilkerson) Collect the names declared by the part.
             // If they are all the same then we can use that name as the
             // inferred name of the library and present it in a quick-fix.
             // partLibraryNames.add(partLibraryName);
           } else if (libraryNameNode.name != partLibraryName) {
-            _errorListener.onError(new AnalysisError(librarySource,
-                partUri.offset, partUri.length,
-                StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [
-              libraryNameNode.name,
-              partLibraryName
-            ]));
+            _errorListener.onError(new AnalysisError(
+                librarySource,
+                partUri.offset,
+                partUri.length,
+                StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
+                [libraryNameNode.name, partLibraryName]));
           }
           if (entryPoint == null) {
             entryPoint = _findEntryPoint(part);
@@ -7077,21 +7115,24 @@
             String partLibraryName =
                 _getPartLibraryName(partSource, partUnit, directivesToResolve);
             if (partLibraryName == null) {
-              _errorListener.onError(new AnalysisError(librarySource,
-                  partUri.offset, partUri.length,
-                  CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSource()]));
+              _errorListener.onError(new AnalysisError(
+                  librarySource,
+                  partUri.offset,
+                  partUri.length,
+                  CompileTimeErrorCode.PART_OF_NON_PART,
+                  [partUri.toSource()]));
             } else if (libraryNameNode == null) {
               // TODO(brianwilkerson) Collect the names declared by the part.
               // If they are all the same then we can use that name as the
               // inferred name of the library and present it in a quick-fix.
               // partLibraryNames.add(partLibraryName);
             } else if (libraryNameNode.name != partLibraryName) {
-              _errorListener.onError(new AnalysisError(librarySource,
-                  partUri.offset, partUri.length,
-                  StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [
-                libraryNameNode.name,
-                partLibraryName
-              ]));
+              _errorListener.onError(new AnalysisError(
+                  librarySource,
+                  partUri.offset,
+                  partUri.length,
+                  StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
+                  [libraryNameNode.name, partLibraryName]));
             }
             if (entryPoint == null) {
               entryPoint = _findEntryPoint(part);
@@ -7296,8 +7337,10 @@
         libraryNames[i] = _getLibraryName(conflictingMembers[i]);
       }
       libraryNames.sort();
-      errorListener.onError(new AnalysisError(getSource(identifier),
-          identifier.offset, identifier.length,
+      errorListener.onError(new AnalysisError(
+          getSource(identifier),
+          identifier.offset,
+          identifier.length,
           StaticWarningCode.AMBIGUOUS_IMPORT, [
         foundEltName,
         StringUtilities.printListOfQuotedNames(libraryNames)
@@ -7398,13 +7441,12 @@
     if (sdkElement != null && nonSdkElements.length > 0) {
       String sdkLibName = _getLibraryName(sdkElement);
       String otherLibName = _getLibraryName(nonSdkElements[0]);
-      errorListener.onError(new AnalysisError(getSource(identifier),
-          identifier.offset, identifier.length,
-          StaticWarningCode.CONFLICTING_DART_IMPORT, [
-        name,
-        sdkLibName,
-        otherLibName
-      ]));
+      errorListener.onError(new AnalysisError(
+          getSource(identifier),
+          identifier.offset,
+          identifier.length,
+          StaticWarningCode.CONFLICTING_DART_IMPORT,
+          [name, sdkLibName, otherLibName]));
     }
     if (nonSdkElements.length == conflictingElements.length) {
       // None of the members were removed
@@ -7753,7 +7795,8 @@
    * @param visitedLibraries the libraries that have already been visited, used to prevent infinite
    *          recursion
    */
-  void _addToDependencyMap(Library library,
+  void _addToDependencyMap(
+      Library library,
       HashMap<Library, List<Library>> dependencyMap,
       Set<Library> visitedLibraries) {
     if (visitedLibraries.add(library)) {
@@ -7858,8 +7901,11 @@
                 ErrorCode errorCode = (importElement.isDeferred
                     ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
                     : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY);
-                _errorListener.onError(new AnalysisError(library.librarySource,
-                    uriLiteral.offset, uriLiteral.length, errorCode,
+                _errorListener.onError(new AnalysisError(
+                    library.librarySource,
+                    uriLiteral.offset,
+                    uriLiteral.length,
+                    errorCode,
                     [uriLiteral.toSource()]));
               }
             }
@@ -7888,8 +7934,10 @@
               exports.add(exportElement);
               if (analysisContext.computeKindOf(exportedSource) !=
                   SourceKind.LIBRARY) {
-                _errorListener.onError(new AnalysisError(library.librarySource,
-                    uriLiteral.offset, uriLiteral.length,
+                _errorListener.onError(new AnalysisError(
+                    library.librarySource,
+                    uriLiteral.offset,
+                    uriLiteral.length,
                     CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
                     [uriLiteral.toSource()]));
               }
@@ -8046,7 +8094,8 @@
    */
   void _computeLibraryDependencies(Library library) {
     Source librarySource = library.librarySource;
-    _computeLibraryDependenciesFromDirectives(library,
+    _computeLibraryDependenciesFromDirectives(
+        library,
         analysisContext.computeImportedLibraries(librarySource),
         analysisContext.computeExportedLibraries(librarySource));
   }
@@ -8200,7 +8249,9 @@
             ErrorReporter errorReporter =
                 new ErrorReporter(_errorListener, source);
             ConstantVerifier constantVerifier = new ConstantVerifier(
-                errorReporter, library.libraryElement, _typeProvider,
+                errorReporter,
+                library.libraryElement,
+                _typeProvider,
                 analysisContext.declaredVariables);
             unit.accept(constantVerifier);
           } on AnalysisException catch (exception, stackTrace) {
@@ -8503,8 +8554,11 @@
                 ErrorCode errorCode = (importElement.isDeferred
                     ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
                     : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY);
-                _errorListener.onError(new AnalysisError(library.librarySource,
-                    uriLiteral.offset, uriLiteral.length, errorCode,
+                _errorListener.onError(new AnalysisError(
+                    library.librarySource,
+                    uriLiteral.offset,
+                    uriLiteral.length,
+                    errorCode,
                     [uriLiteral.toSource()]));
               }
             }
@@ -8536,8 +8590,10 @@
               exports.add(exportElement);
               if (analysisContext.computeKindOf(exportedSource) !=
                   SourceKind.LIBRARY) {
-                _errorListener.onError(new AnalysisError(library.librarySource,
-                    uriLiteral.offset, uriLiteral.length,
+                _errorListener.onError(new AnalysisError(
+                    library.librarySource,
+                    uriLiteral.offset,
+                    uriLiteral.length,
                     CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
                     [uriLiteral.toSource()]));
               }
@@ -8631,7 +8687,9 @@
           Source source = unit.source;
           CompilationUnit ast = unit.compilationUnit;
           TypeResolverVisitor visitor = new TypeResolverVisitor(
-              library.libraryElement, source, _typeProvider,
+              library.libraryElement,
+              source,
+              _typeProvider,
               library.libraryScope.errorListener,
               nameScope: library.libraryScope);
           ast.accept(visitor);
@@ -8681,7 +8739,9 @@
           ErrorReporter errorReporter =
               new ErrorReporter(_errorListener, unit.source);
           ConstantVerifier constantVerifier = new ConstantVerifier(
-              errorReporter, library.libraryElement, _typeProvider,
+              errorReporter,
+              library.libraryElement,
+              _typeProvider,
               analysisContext.declaredVariables);
           ast.accept(constantVerifier);
         }
@@ -8819,7 +8879,9 @@
           offset = accessor.variable.nameOffset;
         }
       }
-      return new AnalysisError(duplicate.source, offset,
+      return new AnalysisError(
+          duplicate.source,
+          offset,
           duplicate.displayName.length,
           CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER,
           [existing.displayName]);
@@ -9301,7 +9363,8 @@
           definedNames.addAll(exportedNames);
         }
       }
-      _addAllFromNamespace(definedNames,
+      _addAllFromNamespace(
+          definedNames,
           (library.context as InternalAnalysisContext)
               .getPublicNamespace(library));
       return definedNames;
@@ -10025,10 +10088,11 @@
    */
   ResolverVisitor(LibraryElement definingLibrary, Source source,
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
-      {Scope nameScope, InheritanceManager inheritanceManager,
+      {Scope nameScope,
+      InheritanceManager inheritanceManager,
       StaticTypeAnalyzerFactory typeAnalyzerFactory})
       : super(definingLibrary, source, typeProvider, errorListener,
-          nameScope: nameScope) {
+            nameScope: nameScope) {
     if (inheritanceManager == null) {
       this._inheritanceManager = new InheritanceManager(definingLibrary);
     } else {
@@ -10056,10 +10120,10 @@
       Library library, Source source, TypeProvider typeProvider,
       {StaticTypeAnalyzerFactory typeAnalyzerFactory})
       : this(
-          library.libraryElement, source, typeProvider, library.errorListener,
-          nameScope: library.libraryScope,
-          inheritanceManager: library.inheritanceManager,
-          typeAnalyzerFactory: typeAnalyzerFactory);
+            library.libraryElement, source, typeProvider, library.errorListener,
+            nameScope: library.libraryScope,
+            inheritanceManager: library.inheritanceManager,
+            typeAnalyzerFactory: typeAnalyzerFactory);
 
   /**
    * Return the element representing the function containing the current node, or `null` if
@@ -10715,9 +10779,16 @@
         if (loopVariable != null && iterable != null) {
           LocalVariableElement loopElement = loopVariable.element;
           if (loopElement != null) {
-            DartType iteratorElementType = _getIteratorElementType(iterable);
-            overrideVariable(loopElement, iteratorElementType, true);
-            _recordPropagatedType(loopVariable.identifier, iteratorElementType);
+            DartType propagatedType = null;
+            if (node.awaitKeyword == null) {
+              propagatedType = _getIteratorElementType(iterable);
+            } else {
+              propagatedType = _getStreamElementType(iterable);
+            }
+            if (propagatedType != null) {
+              overrideVariable(loopElement, propagatedType, true);
+              _recordPropagatedType(loopVariable.identifier, propagatedType);
+            }
           }
         } else if (identifier != null && iterable != null) {
           Element identifierElement = identifier.staticElement;
@@ -11099,12 +11170,11 @@
   }
 
   /**
-   * The given expression is the expression used to compute the iterator for a for-each statement.
-   * Attempt to compute the type of objects that will be assigned to the loop variable and return
-   * that type. Return `null` if the type could not be determined.
-   *
-   * @param iterator the iterator for a for-each statement
-   * @return the type of objects that will be assigned to the loop variable
+   * The given expression is the expression used to compute the iterator for a
+   * for-each statement. Attempt to compute the type of objects that will be
+   * assigned to the loop variable and return that type. Return `null` if the
+   * type could not be determined. The [iteratorExpression] is the expression
+   * that will return the Iterable being iterated over.
    */
   DartType _getIteratorElementType(Expression iteratorExpression) {
     DartType expressionType = iteratorExpression.bestType;
@@ -11132,6 +11202,40 @@
   }
 
   /**
+   * The given expression is the expression used to compute the stream for an
+   * asyncronous for-each statement. Attempt to compute the type of objects that
+   * will be assigned to the loop variable and return that type. Return `null`
+   * if the type could not be determined. The [streamExpression] is the
+   * expression that will return the stream being iterated over.
+   */
+  DartType _getStreamElementType(Expression streamExpression) {
+    DartType streamType = streamExpression.bestType;
+    if (streamType is InterfaceType) {
+      FunctionType listenFunction =
+          _inheritanceManager.lookupMemberType(streamType, "listen");
+      if (listenFunction == null) {
+        return null;
+      }
+      List<ParameterElement> listenParameters = listenFunction.parameters;
+      if (listenParameters == null || listenParameters.length < 1) {
+        return null;
+      }
+      DartType onDataType = listenParameters[0].type;
+      if (onDataType is FunctionType) {
+        List<ParameterElement> onDataParameters = onDataType.parameters;
+        if (onDataParameters == null || onDataParameters.length < 1) {
+          return null;
+        }
+        DartType eventType = onDataParameters[0].type;
+        if (eventType.element == streamType.typeParameters[0]) {
+          return streamType.typeArguments[0];
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
    * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its
    * required type is [FunctionType], then infer parameters types from [FunctionType].
    */
@@ -11150,7 +11254,7 @@
     // If the expectedClosureType is not more specific than the static type,
     // return.
     DartType staticClosureType =
-        (closure.element != null ? closure.element.type : null) as DartType;
+        closure.element != null ? closure.element.type : null;
     if (staticClosureType != null &&
         !expectedClosureType.isMoreSpecificThan(staticClosureType)) {
       return;
@@ -11540,8 +11644,11 @@
     // TODO(jwren) There are 4 error codes for duplicate, but only 1 is being
     // generated.
     Source source = duplicate.source;
-    return new AnalysisError(source, duplicate.nameOffset,
-        duplicate.displayName.length, CompileTimeErrorCode.DUPLICATE_DEFINITION,
+    return new AnalysisError(
+        source,
+        duplicate.nameOffset,
+        duplicate.displayName.length,
+        CompileTimeErrorCode.DUPLICATE_DEFINITION,
         [existing.displayName]);
   }
 
@@ -11640,7 +11747,7 @@
   /**
    * The element for the library containing the compilation unit being visited.
    */
-  LibraryElement _definingLibrary;
+  final LibraryElement definingLibrary;
 
   /**
    * The source representing the compilation unit being visited.
@@ -11650,7 +11757,7 @@
   /**
    * The error listener that will be informed of any errors that are found during resolution.
    */
-  AnalysisErrorListener _errorListener;
+  final AnalysisErrorListener errorListener;
 
   /**
    * The scope used to resolve identifiers.
@@ -11694,10 +11801,9 @@
    * first be visited.  If `null` or unspecified, a new [LibraryScope] will be
    * created based on [definingLibrary] and [typeProvider].
    */
-  ScopedVisitor(LibraryElement definingLibrary, this.source, this.typeProvider,
-      AnalysisErrorListener errorListener, {Scope nameScope}) {
-    this._definingLibrary = definingLibrary;
-    this._errorListener = errorListener;
+  ScopedVisitor(
+      this.definingLibrary, this.source, this.typeProvider, this.errorListener,
+      {Scope nameScope}) {
     if (nameScope == null) {
       this.nameScope = new LibraryScope(definingLibrary, errorListener);
     } else {
@@ -11706,13 +11812,6 @@
   }
 
   /**
-   * Return the library element for the library containing the compilation unit being resolved.
-   *
-   * @return the library element for the library containing the compilation unit being resolved
-   */
-  LibraryElement get definingLibrary => _definingLibrary;
-
-  /**
    * Return the implicit label scope in which the current node is being
    * resolved.
    */
@@ -11748,7 +11847,7 @@
    */
   void reportErrorForNode(ErrorCode errorCode, AstNode node,
       [List<Object> arguments]) {
-    _errorListener.onError(new AnalysisError(
+    errorListener.onError(new AnalysisError(
         source, node.offset, node.length, errorCode, arguments));
   }
 
@@ -11762,7 +11861,7 @@
    */
   void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
       [List<Object> arguments]) {
-    _errorListener.onError(
+    errorListener.onError(
         new AnalysisError(source, offset, length, errorCode, arguments));
   }
 
@@ -11775,7 +11874,7 @@
    */
   void reportErrorForToken(ErrorCode errorCode, sc.Token token,
       [List<Object> arguments]) {
-    _errorListener.onError(new AnalysisError(
+    errorListener.onError(new AnalysisError(
         source, token.offset, token.length, errorCode, arguments));
   }
 
@@ -13243,13 +13342,13 @@
 
   @override
   List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
-    nullType,
-    numType,
-    intType,
-    doubleType,
-    boolType,
-    stringType
-  ];
+        nullType,
+        numType,
+        intType,
+        doubleType,
+        boolType,
+        stringType
+      ];
 
   @override
   DartObjectImpl get nullObject {
@@ -13380,7 +13479,7 @@
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
       {Scope nameScope})
       : super(definingLibrary, source, typeProvider, errorListener,
-          nameScope: nameScope) {
+            nameScope: nameScope) {
     _dynamicType = typeProvider.dynamicType;
     _undefinedType = typeProvider.undefinedType;
   }
@@ -13776,13 +13875,15 @@
                 (parent.parent as InstanceCreationExpression).isConst) {
               // If, if this is a const expression, then generate a
               // CompileTimeErrorCode.CONST_WITH_NON_TYPE error.
-              reportErrorForNode(CompileTimeErrorCode.CONST_WITH_NON_TYPE,
+              reportErrorForNode(
+                  CompileTimeErrorCode.CONST_WITH_NON_TYPE,
                   prefixedIdentifier.identifier,
                   [prefixedIdentifier.identifier.name]);
             } else {
               // Else, if this expression is a new expression, report a
               // NEW_WITH_NON_TYPE warning.
-              reportErrorForNode(StaticWarningCode.NEW_WITH_NON_TYPE,
+              reportErrorForNode(
+                  StaticWarningCode.NEW_WITH_NON_TYPE,
                   prefixedIdentifier.identifier,
                   [prefixedIdentifier.identifier.name]);
             }
@@ -13960,11 +14061,8 @@
           typeArguments[i] = argumentType;
         }
       } else {
-        reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node, [
-          typeName.name,
-          parameterCount,
-          argumentCount
-        ]);
+        reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node,
+            [typeName.name, parameterCount, argumentCount]);
         for (int i = 0; i < parameterCount; i++) {
           typeArguments[i] = _dynamicType;
         }
@@ -14328,7 +14426,8 @@
   void _resolve(ClassElementImpl classElement, WithClause withClause,
       ImplementsClause implementsClause) {
     if (withClause != null) {
-      List<InterfaceType> mixinTypes = _resolveTypes(withClause.mixinTypes,
+      List<InterfaceType> mixinTypes = _resolveTypes(
+          withClause.mixinTypes,
           CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
           CompileTimeErrorCode.MIXIN_OF_ENUM,
           CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
@@ -14340,7 +14439,8 @@
     }
     if (implementsClause != null) {
       NodeList<TypeName> interfaces = implementsClause.interfaces;
-      List<InterfaceType> interfaceTypes = _resolveTypes(interfaces,
+      List<InterfaceType> interfaceTypes = _resolveTypes(
+          interfaces,
           CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
           CompileTimeErrorCode.IMPLEMENTS_ENUM,
           CompileTimeErrorCode.IMPLEMENTS_DYNAMIC);
@@ -14415,8 +14515,10 @@
    * @param dynamicTypeError the error to produce if the type name is "dynamic"
    * @return an array containing all of the types that were resolved.
    */
-  List<InterfaceType> _resolveTypes(NodeList<TypeName> typeNames,
-      ErrorCode nonTypeError, ErrorCode enumTypeError,
+  List<InterfaceType> _resolveTypes(
+      NodeList<TypeName> typeNames,
+      ErrorCode nonTypeError,
+      ErrorCode enumTypeError,
       ErrorCode dynamicTypeError) {
     List<InterfaceType> types = new List<InterfaceType>();
     for (TypeName typeName in typeNames) {
@@ -14648,10 +14750,8 @@
   @override
   visitClassElement(ClassElement element) {
     if (!_isUsedElement(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element,
+          [element.kind.displayName, element.displayName]);
     }
     super.visitClassElement(element);
   }
@@ -14668,10 +14768,8 @@
   @override
   visitFunctionElement(FunctionElement element) {
     if (!_isUsedElement(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element,
+          [element.kind.displayName, element.displayName]);
     }
     super.visitFunctionElement(element);
   }
@@ -14679,10 +14777,8 @@
   @override
   visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
     if (!_isUsedElement(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element,
+          [element.kind.displayName, element.displayName]);
     }
     super.visitFunctionTypeAliasElement(element);
   }
@@ -14705,10 +14801,8 @@
   @override
   visitMethodElement(MethodElement element) {
     if (!_isUsedMember(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element,
+          [element.kind.displayName, element.displayName]);
     }
     super.visitMethodElement(element);
   }
@@ -14716,10 +14810,8 @@
   @override
   visitPropertyAccessorElement(PropertyAccessorElement element) {
     if (!_isUsedMember(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element,
+          [element.kind.displayName, element.displayName]);
     }
     super.visitPropertyAccessorElement(element);
   }
@@ -14779,8 +14871,11 @@
   void _reportErrorForElement(
       ErrorCode errorCode, Element element, List<Object> arguments) {
     if (element != null) {
-      _errorListener.onError(new AnalysisError(element.source,
-          element.nameOffset, element.displayName.length, errorCode,
+      _errorListener.onError(new AnalysisError(
+          element.source,
+          element.nameOffset,
+          element.displayName.length,
+          errorCode,
           arguments));
     }
   }
@@ -14908,7 +15003,7 @@
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
       {Scope nameScope})
       : super(definingLibrary, source, typeProvider, errorListener,
-          nameScope: nameScope);
+            nameScope: nameScope);
 
   /**
    * Initialize a newly created visitor to resolve the nodes in a compilation unit.
@@ -14923,8 +15018,8 @@
   VariableResolverVisitor.con1(
       Library library, Source source, TypeProvider typeProvider)
       : this(
-          library.libraryElement, source, typeProvider, library.errorListener,
-          nameScope: library.libraryScope);
+            library.libraryElement, source, typeProvider, library.errorListener,
+            nameScope: library.libraryScope);
 
   @override
   Object visitExportDirective(ExportDirective node) => null;
@@ -15033,11 +15128,14 @@
 
   List<ParameterElement> parameterElements;
 
-  _ConstantVerifier_validateInitializerExpression(TypeProvider typeProvider,
-      ErrorReporter errorReporter, this.verifier, this.parameterElements,
+  _ConstantVerifier_validateInitializerExpression(
+      TypeProvider typeProvider,
+      ErrorReporter errorReporter,
+      this.verifier,
+      this.parameterElements,
       DeclaredVariables declaredVariables)
       : super(new ConstantEvaluationEngine(typeProvider, declaredVariables),
-          errorReporter);
+            errorReporter);
 
   @override
   DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
diff --git a/pkg/analyzer/lib/src/generated/scanner.dart b/pkg/analyzer/lib/src/generated/scanner.dart
index 9e028ca..0a9fa2a 100644
--- a/pkg/analyzer/lib/src/generated/scanner.dart
+++ b/pkg/analyzer/lib/src/generated/scanner.dart
@@ -1501,8 +1501,8 @@
         }
         recordStartOfLine();
       } else if (next == 0xA) {
-        recordStartOfLine();
         next = _reader.advance();
+        recordStartOfLine();
       } else {
         next = _reader.advance();
       }
@@ -2010,9 +2010,7 @@
   /**
    * Initialize a newly created token to have the given [type] and [offset].
    */
-  Token(this.type, int offset) {
-    this.offset = offset;
-  }
+  Token(this.type, this.offset);
 
   /**
    * Return the offset from the beginning of the file to the character after the
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index 81c8a88..2b4fc6e 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -303,7 +303,7 @@
    * The short name of the library. This is the name used after 'dart:' in a
    * URI.
    */
-  String _shortName = null;
+  final String shortName;
 
   /**
    * The path to the file defining the library. The path is relative to the
@@ -337,9 +337,7 @@
    * Initialize a newly created library to represent the library with the given
    * [name].
    */
-  SdkLibraryImpl(String name) {
-    this._shortName = name;
-  }
+  SdkLibraryImpl(this.shortName);
 
   /**
    * Set whether the library is documented.
@@ -373,9 +371,6 @@
   @override
   bool get isVmLibrary => (_platforms & VM_PLATFORM) != 0;
 
-  @override
-  String get shortName => _shortName;
-
   /**
    * Record that this library can be compiled to JavaScript by dart2js.
    */
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 5b96dbd..7db8cbe 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -109,7 +109,7 @@
   CustomUriResolver(this._urlMappings);
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     String mapping = _urlMappings[uri.toString()];
     if (mapping == null) return null;
 
@@ -117,7 +117,7 @@
     if (!fileUri.isAbsolute) return null;
 
     JavaFile javaFile = new JavaFile.fromUri(fileUri);
-    return new FileBasedSource(javaFile);
+    return new FileBasedSource(javaFile, actualUri != null ? actualUri : uri);
   }
 }
 
@@ -156,7 +156,7 @@
   DartSdk get dartSdk => _sdk;
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (!isDartUri(uri)) {
       return null;
     }
@@ -814,22 +814,30 @@
       }
       containedUri = containingSource.resolveRelativeUri(containedUri);
     }
-    // Now check .packages.
+
+    Uri actualUri = containedUri;
+
+    // Check .packages and update target and actual URIs as appropriate.
     if (_packages != null && containedUri.scheme == 'package') {
       Uri packageUri =
           _packages.resolve(containedUri, notFound: (Uri packageUri) => null);
-      // Ensure scheme is set.
-      if (packageUri != null && packageUri.scheme == '') {
-        packageUri = packageUri.replace(scheme: 'file');
+
+      if (packageUri != null) {
+        // Ensure scheme is set.
+        if (packageUri.scheme == '') {
+          packageUri = packageUri.replace(scheme: 'file');
+        }
+        containedUri = packageUri;
       }
-      containedUri = packageUri;
     }
+
     for (UriResolver resolver in _resolvers) {
-      Source result = resolver.resolveAbsolute(containedUri);
+      Source result = resolver.resolveAbsolute(containedUri, actualUri);
       if (result != null) {
         return result;
       }
     }
+
     return null;
   }
 }
@@ -1062,9 +1070,10 @@
    * resolved because the URI is invalid.
    *
    * @param uri the URI to be resolved
+   * @param actualUri the actual uri for this source -- if `null`, the value of [uri] will be used
    * @return a [Source] representing the file to which given URI was resolved
    */
-  Source resolveAbsolute(Uri uri);
+  Source resolveAbsolute(Uri uri, [Uri actualUri]);
 
   /**
    * Return an absolute URI that represents the given source, or `null` if a valid URI cannot
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 9c40d74..fa32b4b 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -276,11 +276,12 @@
   static String FILE_SCHEME = "file";
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (!isFileUri(uri)) {
       return null;
     }
-    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
+    return new FileBasedSource(
+        new JavaFile.fromUri(uri), actualUri != null ? actualUri : uri);
   }
 
   @override
@@ -290,7 +291,7 @@
     }
     return null;
   }
-  
+
   /**
    * Return `true` if the given URI is a `file` URI.
    *
@@ -425,7 +426,7 @@
   }
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (!isPackageUri(uri)) {
       return null;
     }
@@ -459,11 +460,13 @@
         if (_isSelfReference(packagesDirectory, canonicalFile)) {
           uri = canonicalFile.toURI();
         }
-        return new FileBasedSource(canonicalFile, uri);
+        return new FileBasedSource(
+            canonicalFile, actualUri != null ? actualUri : uri);
       }
     }
     return new FileBasedSource(
-        getCanonicalFile(_packagesDirectories[0], pkgName, relPath), uri);
+        getCanonicalFile(_packagesDirectories[0], pkgName, relPath),
+        actualUri != null ? actualUri : uri);
   }
 
   @override
@@ -537,7 +540,7 @@
       : super();
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     String rootPath = _rootDirectory.toURI().path;
     String uriPath = uri.path;
     if (uriPath != null && uriPath.startsWith(rootPath)) {
@@ -545,7 +548,7 @@
       for (JavaFile dir in _relativeDirectories) {
         JavaFile file = new JavaFile.relative(dir, filePath);
         if (file.exists()) {
-          return new FileBasedSource(file, uri);
+          return new FileBasedSource(file, actualUri != null ? actualUri : uri);
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 4c2a537..d6a4c78 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -197,7 +197,8 @@
   }
 
   static ExportElementImpl exportFor(LibraryElement exportedLibrary,
-      [List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST]) {
+      [List<NamespaceCombinator> combinators =
+          NamespaceCombinator.EMPTY_LIST]) {
     ExportElementImpl spec = new ExportElementImpl(-1);
     spec.exportedLibrary = exportedLibrary;
     spec.combinators = combinators;
@@ -226,8 +227,9 @@
       setter.setter = true;
       setter.synthetic = true;
       setter.variable = field;
-      setter.parameters =
-          <ParameterElement>[requiredParameter2("_$name", type)];
+      setter.parameters = <ParameterElement>[
+        requiredParameter2("_$name", type)
+      ];
       setter.returnType = VoidTypeImpl.instance;
       setter.type = new FunctionTypeImpl(setter);
       field.setter = setter;
@@ -236,7 +238,8 @@
   }
 
   static FieldFormalParameterElementImpl fieldFormalParameter(
-      Identifier name) => new FieldFormalParameterElementImpl(name);
+          Identifier name) =>
+      new FieldFormalParameterElementImpl(name);
 
   static FunctionElementImpl functionElement(String functionName) =>
       functionElement4(functionName, null, null, null, null);
@@ -245,9 +248,11 @@
           String functionName, ClassElement returnElement) =>
       functionElement3(functionName, returnElement, null, null);
 
-  static FunctionElementImpl functionElement3(String functionName,
-      ClassElement returnElement, List<ClassElement> normalParameters,
-      List<ClassElement> optionalParameters) {
+  static FunctionElementImpl functionElement3(
+      String functionName,
+      ClassElement returnElement,
+      List<TypeDefiningElement> normalParameters,
+      List<TypeDefiningElement> optionalParameters) {
     // We don't create parameter elements because we don't have parameter names
     FunctionElementImpl functionElement =
         new FunctionElementImpl(functionName, 0);
@@ -281,9 +286,12 @@
     return functionElement;
   }
 
-  static FunctionElementImpl functionElement4(String functionName,
-      ClassElement returnElement, List<ClassElement> normalParameters,
-      List<String> names, List<ClassElement> namedParameters) {
+  static FunctionElementImpl functionElement4(
+      String functionName,
+      ClassElement returnElement,
+      List<ClassElement> normalParameters,
+      List<String> names,
+      List<ClassElement> namedParameters) {
     FunctionElementImpl functionElement =
         new FunctionElementImpl(functionName, 0);
     FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement);
@@ -326,14 +334,19 @@
           String functionName, List<ClassElement> normalParameters) =>
       functionElement3(functionName, null, normalParameters, null);
 
-  static FunctionElementImpl functionElement6(String functionName,
-      List<ClassElement> normalParameters,
-      List<ClassElement> optionalParameters) => functionElement3(
+  static FunctionElementImpl functionElement6(
+          String functionName,
+          List<ClassElement> normalParameters,
+          List<ClassElement> optionalParameters) =>
+      functionElement3(
           functionName, null, normalParameters, optionalParameters);
 
-  static FunctionElementImpl functionElement7(String functionName,
-      List<ClassElement> normalParameters, List<String> names,
-      List<ClassElement> namedParameters) => functionElement4(
+  static FunctionElementImpl functionElement7(
+          String functionName,
+          List<ClassElement> normalParameters,
+          List<String> names,
+          List<ClassElement> namedParameters) =>
+      functionElement4(
           functionName, null, normalParameters, names, namedParameters);
 
   static FunctionElementImpl functionElementWithParameters(String functionName,
@@ -384,7 +397,8 @@
 
   static ImportElementImpl importFor(
       LibraryElement importedLibrary, PrefixElement prefix,
-      [List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST]) {
+      [List<NamespaceCombinator> combinators =
+          NamespaceCombinator.EMPTY_LIST]) {
     ImportElementImpl spec = new ImportElementImpl(0);
     spec.importedLibrary = importedLibrary;
     spec.prefix = prefix;
@@ -430,8 +444,10 @@
     return method;
   }
 
-  static MethodElementImpl methodElementWithParameters(String methodName,
-      List<DartType> typeArguments, DartType returnType,
+  static MethodElementImpl methodElementWithParameters(
+      String methodName,
+      List<DartType> typeArguments,
+      DartType returnType,
       List<ParameterElement> parameters) {
     MethodElementImpl method = new MethodElementImpl(methodName, 0);
     method.parameters = parameters;
@@ -548,8 +564,9 @@
       setter.static = true;
       setter.synthetic = true;
       setter.variable = variable;
-      setter.parameters =
-          <ParameterElement>[requiredParameter2("_$name", type)];
+      setter.parameters = <ParameterElement>[
+        requiredParameter2("_$name", type)
+      ];
       setter.returnType = VoidTypeImpl.instance;
       setter.type = new FunctionTypeImpl(setter);
       variable.setter = setter;
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index fa8daec..6e3f7a4 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -3219,7 +3219,8 @@
     // Use the ErrorVerifier to compute errors.
     //
     ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
-        libraryElement, typeProvider, new InheritanceManager(libraryElement));
+        libraryElement, typeProvider, new InheritanceManager(libraryElement),
+        context.analysisOptions.enableSuperMixins);
     unit.accept(errorVerifier);
     //
     // Record outputs.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 32c8bf7..77b064e 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.25.3-alpha.1
+version: 0.26.0
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index d941fcf..29e0b67 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -4,7 +4,6 @@
 
 library engine.compile_time_error_code_test;
 
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index af6dac3..13c0b66 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -2263,6 +2263,7 @@
       options.cacheSize = i;
       options.dart2jsHint = booleanValue;
       options.enableStrictCallChecks = booleanValue;
+      options.enableSuperMixins = booleanValue;
       options.generateImplicitErrors = booleanValue;
       options.generateSdkErrors = booleanValue;
       options.hint = booleanValue;
@@ -2274,6 +2275,7 @@
       expect(copy.cacheSize, options.cacheSize);
       expect(copy.dart2jsHint, options.dart2jsHint);
       expect(copy.enableStrictCallChecks, options.enableStrictCallChecks);
+      expect(copy.enableSuperMixins, options.enableSuperMixins);
       expect(copy.generateImplicitErrors, options.generateImplicitErrors);
       expect(copy.generateSdkErrors, options.generateSdkErrors);
       expect(copy.hint, options.hint);
@@ -2305,11 +2307,11 @@
     expect(options.dart2jsHint, value);
   }
 
-  void test_strongMode() {
+  void test_enableSuperMixins() {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    bool value = !options.strongMode;
-    options.strongMode = value;
-    expect(options.strongMode, value);
+    bool value = !options.enableSuperMixins;
+    options.enableSuperMixins = value;
+    expect(options.enableSuperMixins, value);
   }
 
   void test_generateImplicitErrors() {
@@ -2346,6 +2348,13 @@
     options.preserveComments = value;
     expect(options.preserveComments, value);
   }
+
+  void test_strongMode() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    bool value = !options.strongMode;
+    options.strongMode = value;
+    expect(options.strongMode, value);
+  }
 }
 
 class AnalysisTask_test_perform_exception extends AnalysisTask {
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index ed41b59..7af5e3ab 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -3872,6 +3872,20 @@
 ''');
   }
 
+  void _assertEqualLineInfo(LineInfo incrLineInfo, LineInfo fullLineInfo) {
+    for (int offset = 0; offset < 1000; offset++) {
+      LineInfo_Location incrLocation = incrLineInfo.getLocation(offset);
+      LineInfo_Location fullLocation = fullLineInfo.getLocation(offset);
+      if (incrLocation.lineNumber != fullLocation.lineNumber ||
+          incrLocation.columnNumber != fullLocation.columnNumber) {
+        fail('At offset $offset ' +
+            '(${incrLocation.lineNumber}, ${incrLocation.columnNumber})' +
+            ' != ' +
+            '(${fullLocation.lineNumber}, ${fullLocation.columnNumber})');
+      }
+    }
+  }
+
   /**
    * Reset the analysis context to have the 'incremental' option set to the
    * given value.
@@ -3910,6 +3924,7 @@
     analysisContext2.setContents(source, newCode);
     CompilationUnit newUnit = resolveCompilationUnit(source, oldLibrary);
     List<AnalysisError> newErrors = analysisContext.computeErrors(source);
+    LineInfo newLineInfo = analysisContext.getLineInfo(source);
     // check for expected failure
     if (!expectedSuccess) {
       expect(newUnit.element, isNot(same(oldUnitElement)));
@@ -3932,6 +3947,8 @@
       CompilationUnit fullNewUnit = resolveCompilationUnit(source, library);
       // Validate tokens.
       _assertEqualTokens(newUnit, fullNewUnit);
+      // Validate LineInfo
+      _assertEqualLineInfo(newLineInfo, analysisContext.getLineInfo(source));
       // Validate that "incremental" and "full" units have the same resolution.
       try {
         assertSameResolution(newUnit, fullNewUnit, validateTypes: true);
@@ -3941,7 +3958,6 @@
       List<AnalysisError> newFullErrors =
           analysisContext.getErrors(source).errors;
       _assertEqualErrors(newErrors, newFullErrors);
-      // TODO(scheglov) check line info
     }
   }
 
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index c77d424..64da228 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -3140,6 +3140,19 @@
     verify([source]);
   }
 
+  void test_mixinInheritsFromNotObject_classDeclaration_extends() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    resetWithOptions(options);
+    Source source = addSource(r'''
+class A {}
+class B extends A {}
+class C extends Object with B {}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_mixinInheritsFromNotObject_classDeclaration_mixTypeAlias() {
     Source source = addSource(r'''
 class A {}
@@ -3150,6 +3163,45 @@
     verify([source]);
   }
 
+  void test_mixinInheritsFromNotObject_classDeclaration_with() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    resetWithOptions(options);
+    Source source = addSource(r'''
+class A {}
+class B extends Object with A {}
+class C extends Object with B {}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_mixinInheritsFromNotObject_typeAlias_extends() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    resetWithOptions(options);
+    Source source = addSource(r'''
+class A {}
+class B extends A {}
+class C = Object with B;''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_mixinInheritsFromNotObject_typeAlias_with() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    resetWithOptions(options);
+    Source source = addSource(r'''
+class A {}
+class B extends Object with A {}
+class C = Object with B;''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_mixinInheritsFromNotObject_typedef_mixTypeAlias() {
     Source source = addSource(r'''
 class A {}
@@ -3160,6 +3212,20 @@
     verify([source]);
   }
 
+  void test_mixinReferencesSuper() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    resetWithOptions(options);
+    Source source = addSource(r'''
+class A {
+  toString() => super.toString();
+}
+class B extends Object with A {}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_multipleSuperInitializers_no() {
     Source source = addSource(r'''
 class A {}
@@ -5002,12 +5068,14 @@
     verify([source]);
   }
 
-  void test_undefinedGetter_typeLiteral_conditionalAccess() {
-    // When applied to a type literal, the conditional access operator '?.' can
-    // be used to access instance getters of Type.
+  void test_undefinedGetter_static_conditionalAccess() {
+    // The conditional access operator '?.' can be used to access static
+    // fields.
     Source source = addSource('''
-class A {}
-f() => A?.hashCode;
+class A {
+  static var x;
+}
+var a = A?.x;
 ''');
     computeLibrarySourceErrors(source);
     assertNoErrors(source);
@@ -5089,12 +5157,14 @@
     // A call to verify(source) fails as '(() => null)()' isn't resolved.
   }
 
-  void test_undefinedMethod_typeLiteral_conditionalAccess() {
-    // When applied to a type literal, the conditional access operator '?.' can
-    // be used to access instance methods of Type.
+  void test_undefinedMethod_static_conditionalAccess() {
+    // The conditional access operator '?.' can be used to access static
+    // methods.
     Source source = addSource('''
-class A {}
-f() => A?.toString();
+class A {
+  static void m() {}
+}
+f() { A?.m(); }
 ''');
     computeLibrarySourceErrors(source);
     assertNoErrors(source);
@@ -5139,6 +5209,20 @@
     verify([source]);
   }
 
+  void test_undefinedSetter_static_conditionalAccess() {
+    // The conditional access operator '?.' can be used to access static
+    // fields.
+    Source source = addSource('''
+class A {
+  static var x;
+}
+f() { A?.x = 1; }
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_undefinedSuperMethod_field() {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 89242b9..4034068 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -165,7 +165,8 @@
         ElementFactory.topLevelVariableElement3(
             "deprecated", true, false, provider.deprecatedType);
     deprecatedTopLevelVariableElt.constantInitializer = AstFactory
-        .instanceCreationExpression2(Keyword.CONST,
+        .instanceCreationExpression2(
+            Keyword.CONST,
             AstFactory.typeName(provider.deprecatedType.element),
             [AstFactory.string2('next release')]);
     coreUnit.accessors = <PropertyAccessorElement>[
@@ -229,10 +230,29 @@
     (completerConstructor.type as FunctionTypeImpl).typeArguments =
         completerElement.type.typeArguments;
     completerElement.constructors = <ConstructorElement>[completerConstructor];
+    // StreamSubscription
+    ClassElementImpl streamSubscriptionElement =
+        ElementFactory.classElement2("StreamSubscription", ["T"]);
+    // Stream
+    ClassElementImpl streamElement =
+        ElementFactory.classElement2("Stream", ["T"]);
+    DartType returnType = streamSubscriptionElement.type
+        .substitute4(streamElement.type.typeArguments);
+    List<DartType> parameterTypes = <DartType>[
+      ElementFactory
+          .functionElement3('onData', VoidTypeImpl.instance.element,
+              <TypeDefiningElement>[streamElement.typeParameters[0]], null)
+          .type,
+    ];
+    // TODO(brianwilkerson) This is missing the optional parameters.
+    MethodElementImpl listenMethod =
+        ElementFactory.methodElement('listen', returnType, parameterTypes);
+    streamElement.methods = <MethodElement>[listenMethod];
+
     asyncUnit.types = <ClassElement>[
       completerElement,
       futureElement,
-      ElementFactory.classElement2("Stream", ["T"])
+      streamElement
     ];
     LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
         coreContext, AstFactory.libraryIdentifier2(["dart", "async"]));
@@ -306,8 +326,10 @@
     Source mathSource = sourceFactory.forUri(_DART_MATH);
     coreContext.setContents(mathSource, "");
     mathUnit.librarySource = mathUnit.source = mathSource;
-    FunctionElement cosElement = ElementFactory.functionElement3("cos",
-        provider.doubleType.element, <ClassElement>[provider.numType.element],
+    FunctionElement cosElement = ElementFactory.functionElement3(
+        "cos",
+        provider.doubleType.element,
+        <ClassElement>[provider.numType.element],
         ClassElement.EMPTY_LIST);
     TopLevelVariableElement ln10Element = ElementFactory
         .topLevelVariableElement3("LN10", true, false, provider.doubleType);
@@ -323,11 +345,15 @@
     seedParam.type = provider.intType;
     randomConstructor.parameters = <ParameterElement>[seedParam];
     randomElement.constructors = <ConstructorElement>[randomConstructor];
-    FunctionElement sinElement = ElementFactory.functionElement3("sin",
-        provider.doubleType.element, <ClassElement>[provider.numType.element],
+    FunctionElement sinElement = ElementFactory.functionElement3(
+        "sin",
+        provider.doubleType.element,
+        <ClassElement>[provider.numType.element],
         ClassElement.EMPTY_LIST);
-    FunctionElement sqrtElement = ElementFactory.functionElement3("sqrt",
-        provider.doubleType.element, <ClassElement>[provider.numType.element],
+    FunctionElement sqrtElement = ElementFactory.functionElement3(
+        "sqrt",
+        provider.doubleType.element,
+        <ClassElement>[provider.numType.element],
         ClassElement.EMPTY_LIST);
     mathUnit.accessors = <PropertyAccessorElement>[
       ln10Element.getter,
@@ -1208,8 +1234,9 @@
     fail("Not yet tested");
     // Need to set up the exported library so that the identifier can be
     // resolved.
-    ExportDirective directive =
-        AstFactory.exportDirective2(null, [AstFactory.hideCombinator2(["A"])]);
+    ExportDirective directive = AstFactory.exportDirective2(null, [
+      AstFactory.hideCombinator2(["A"])
+    ]);
     _resolveNode(directive);
     _listener.assertNoErrors();
   }
@@ -1223,8 +1250,9 @@
     fail("Not yet tested");
     // Need to set up the imported library so that the identifier can be
     // resolved.
-    ImportDirective directive = AstFactory.importDirective3(
-        null, null, [AstFactory.showCombinator2(["A"])]);
+    ImportDirective directive = AstFactory.importDirective3(null, null, [
+      AstFactory.showCombinator2(["A"])
+    ]);
     _resolveNode(directive);
     _listener.assertNoErrors();
   }
@@ -1324,8 +1352,10 @@
     _resolveNode(expression);
     var stringElement = stringType.element;
     expect(expression.staticElement, isNotNull);
-    expect(expression.staticElement, stringElement.lookUpMethod(
-        TokenType.EQ_EQ.lexeme, stringElement.library));
+    expect(
+        expression.staticElement,
+        stringElement.lookUpMethod(
+            TokenType.EQ_EQ.lexeme, stringElement.library));
     expect(expression.propagatedElement, isNull);
     _listener.assertNoErrors();
   }
@@ -1341,8 +1371,10 @@
         left, TokenType.EQ_EQ, AstFactory.identifier3("j"));
     _resolveNode(expression);
     var stringElement = stringType.element;
-    expect(expression.staticElement, stringElement.lookUpMethod(
-        TokenType.EQ_EQ.lexeme, stringElement.library));
+    expect(
+        expression.staticElement,
+        stringElement.lookUpMethod(
+            TokenType.EQ_EQ.lexeme, stringElement.library));
     expect(expression.propagatedElement, isNull);
     _listener.assertNoErrors();
   }
@@ -1613,12 +1645,17 @@
         AstFactory.typeName(classA), constructorName);
     name.staticElement = constructor;
     InstanceCreationExpression creation = AstFactory.instanceCreationExpression(
-        Keyword.NEW, name,
+        Keyword.NEW,
+        name,
         [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]);
     _resolveNode(creation);
     expect(creation.staticElement, same(constructor));
-    expect((creation.argumentList.arguments[
-        0] as NamedExpression).name.label.staticElement, same(parameter));
+    expect(
+        (creation.argumentList.arguments[0] as NamedExpression)
+            .name
+            .label
+            .staticElement,
+        same(parameter));
     _listener.assertNoErrors();
   }
 
@@ -1648,8 +1685,12 @@
         [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]);
     _resolveNode(invocation);
     expect(invocation.methodName.staticElement, same(method));
-    expect((invocation.argumentList.arguments[
-        0] as NamedExpression).name.label.staticElement, same(parameter));
+    expect(
+        (invocation.argumentList.arguments[0] as NamedExpression)
+            .name
+            .label
+            .staticElement,
+        same(parameter));
     _listener.assertNoErrors();
   }
 
@@ -1808,8 +1849,13 @@
     SuperExpression target = AstFactory.superExpression();
     target.staticType = ElementFactory.classElement("B", classA.type).type;
     PropertyAccess access = AstFactory.propertyAccess2(target, getterName);
-    AstFactory.methodDeclaration2(null, null, null, null,
-        AstFactory.identifier3("m"), AstFactory.formalParameterList(),
+    AstFactory.methodDeclaration2(
+        null,
+        null,
+        null,
+        null,
+        AstFactory.identifier3("m"),
+        AstFactory.formalParameterList(),
         AstFactory.expressionFunctionBody(access));
     _resolveNode(access);
     expect(access.propertyName.staticElement, same(getter));
@@ -1910,8 +1956,12 @@
     ]);
     _resolveInClass(invocation, subclass);
     expect(invocation.staticElement, superConstructor);
-    expect((invocation.argumentList.arguments[
-        0] as NamedExpression).name.label.staticElement, same(parameter));
+    expect(
+        (invocation.argumentList.arguments[0] as NamedExpression)
+            .name
+            .label
+            .staticElement,
+        same(parameter));
     _listener.assertNoErrors();
   }
 
@@ -2241,10 +2291,14 @@
 import 'lib1.dart' as one;
 import 'lib2.dart' as one;
 one.A a;''');
-    Source source2 = addNamedSource("/lib1.dart", r'''
+    Source source2 = addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
-    Source source3 = addNamedSource("/lib2.dart", r'''
+    Source source3 = addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 class B {}''');
     computeLibrarySourceErrors(source);
@@ -2717,7 +2771,9 @@
 
   void test_deprecatedAnnotationUse_export() {
     Source source = addSource("export 'deprecated_library.dart';");
-    addNamedSource("/deprecated_library.dart", r'''
+    addNamedSource(
+        "/deprecated_library.dart",
+        r'''
 @deprecated
 library deprecated_library;
 class A {}''');
@@ -2744,7 +2800,9 @@
     Source source = addSource(r'''
 import 'deprecated_library.dart';
 f(A a) {}''');
-    addNamedSource("/deprecated_library.dart", r'''
+    addNamedSource(
+        "/deprecated_library.dart",
+        r'''
 @deprecated
 library deprecated_library;
 class A {}''');
@@ -2901,7 +2959,9 @@
 import 'lib1.dart';
 import 'lib1.dart';
 A a;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
     computeLibrarySourceErrors(source);
@@ -2916,7 +2976,9 @@
 import 'lib1.dart';
 import 'lib1.dart';
 A a;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
     computeLibrarySourceErrors(source);
@@ -2931,7 +2993,9 @@
 import 'lib1.dart' as M show A hide B;
 import 'lib1.dart' as M show A hide B;
 M.A a;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}''');
@@ -2950,7 +3014,9 @@
 library root;
 import 'lib1.dart' deferred as lib1;
 main() { lib1.f(); }'''
-    ], <ErrorCode>[HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION]);
+    ], <ErrorCode>[
+      HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION
+    ]);
   }
 
   void test_invalidAssignment_instanceVariable() {
@@ -4221,7 +4287,9 @@
 import 'lib1.dart';
 import 'lib1.dart' as one;
 one.A a;''');
-    Source source2 = addNamedSource("/lib1.dart", r'''
+    Source source2 = addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
     computeLibrarySourceErrors(source);
@@ -4236,7 +4304,9 @@
 import 'lib1.dart';
 import 'lib1.dart' hide A;
 A a;''');
-    Source source2 = addNamedSource("/lib1.dart", r'''
+    Source source2 = addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
     computeLibrarySourceErrors(source);
@@ -4251,7 +4321,9 @@
 import 'lib1.dart' show A;
 import 'lib1.dart' show B;
 A a;''');
-    Source source2 = addNamedSource("/lib1.dart", r'''
+    Source source2 = addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}''');
@@ -5787,14 +5859,20 @@
   }
 
   void test_accessorsAcrossFiles() {
-    Source librarySource = addSource("/lib.dart", r'''
+    Source librarySource = addSource(
+        "/lib.dart",
+        r'''
 library lib;
 part 'first.dart';
 part 'second.dart';''');
-    addSource("/first.dart", r'''
+    addSource(
+        "/first.dart",
+        r'''
 part of lib;
 int get V => 0;''');
-    addSource("/second.dart", r'''
+    addSource(
+        "/second.dart",
+        r'''
 part of lib;
 void set V(int v) {}''');
     LibraryElement element = _buildLibrary(librarySource);
@@ -5840,7 +5918,9 @@
 
   void test_missingPartOfDirective() {
     addSource("/a.dart", "class A {}");
-    Source librarySource = addSource("/lib.dart", r'''
+    Source librarySource = addSource(
+        "/lib.dart",
+        r'''
 library lib;
 
 part 'a.dart';''');
@@ -5850,16 +5930,22 @@
   }
 
   void test_multipleFiles() {
-    Source librarySource = addSource("/lib.dart", r'''
+    Source librarySource = addSource(
+        "/lib.dart",
+        r'''
 library lib;
 part 'first.dart';
 part 'second.dart';
 
 class A {}''');
-    addSource("/first.dart", r'''
+    addSource(
+        "/first.dart",
+        r'''
 part of lib;
 class B {}''');
-    addSource("/second.dart", r'''
+    addSource(
+        "/second.dart",
+        r'''
 part of lib;
 class C {}''');
     LibraryElement element = _buildLibrary(librarySource);
@@ -5877,7 +5963,9 @@
   }
 
   void test_singleFile() {
-    Source librarySource = addSource("/lib.dart", r'''
+    Source librarySource = addSource(
+        "/lib.dart",
+        r'''
 library lib;
 
 class A {}''');
@@ -5946,13 +6034,13 @@
     ClassElement typeB2 = ElementFactory.classElement2(typeNameB);
     ClassElement typeC = ElementFactory.classElement2(typeNameC);
     LibraryElement importedLibrary1 = createTestLibrary(context, "imported1");
-    (importedLibrary1.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[typeA, typeB1];
+    (importedLibrary1.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[typeA, typeB1];
     ImportElementImpl import1 =
         ElementFactory.importFor(importedLibrary1, null);
     LibraryElement importedLibrary2 = createTestLibrary(context, "imported2");
-    (importedLibrary2.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[typeB2, typeC];
+    (importedLibrary2.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[typeB2, typeC];
     ImportElementImpl import2 =
         ElementFactory.importFor(importedLibrary2, null);
     LibraryElementImpl importingLibrary =
@@ -6008,8 +6096,8 @@
     ClassElement importedType =
         new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName));
     LibraryElement importedLibrary = createTestLibrary(context, "imported");
-    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[importedType];
+    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[importedType];
     LibraryElementImpl definingLibrary =
         createTestLibrary(context, "importing");
     ImportElementImpl importElement = new ImportElementImpl(0);
@@ -6035,8 +6123,8 @@
     String typeName = "List";
     ClassElement type = ElementFactory.classElement2(typeName);
     LibraryElement importedLibrary = createTestLibrary(context, "lib");
-    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[type];
+    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[type];
     ImportElementImpl importCore = ElementFactory.importFor(
         context.getLibraryElement(context.sourceFactory.forUri("dart:core")),
         null);
@@ -6060,8 +6148,8 @@
     ClassElement typeA = ElementFactory.classElement2(typeNameA);
     ClassElement typeB = ElementFactory.classElement2(typeNameB);
     LibraryElement importedLibrary = createTestLibrary(context, "imported");
-    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[typeA, typeB];
+    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[typeA, typeB];
     ImportElementImpl import1 = ElementFactory.importFor(importedLibrary, null);
     ImportElementImpl import2 = ElementFactory.importFor(importedLibrary, null);
     LibraryElementImpl importingLibrary =
@@ -6085,14 +6173,14 @@
     ClassElement nonPrefixedType = ElementFactory.classElement2(typeName);
     LibraryElement prefixedLibrary =
         createTestLibrary(context, "import.prefixed");
-    (prefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[prefixedType];
+    (prefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[prefixedType];
     ImportElementImpl prefixedImport = ElementFactory.importFor(
         prefixedLibrary, ElementFactory.prefix(prefixName));
     LibraryElement nonPrefixedLibrary =
         createTestLibrary(context, "import.nonPrefixed");
-    (nonPrefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[nonPrefixedType];
+    (nonPrefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[nonPrefixedType];
     ImportElementImpl nonPrefixedImport =
         ElementFactory.importFor(nonPrefixedLibrary, null);
     LibraryElementImpl importingLibrary =
@@ -6137,7 +6225,9 @@
 library libA;
 import 'libB.dart';
 class A {}''');
-    Source sourceB = addNamedSource("/libB.dart", r'''
+    Source sourceB = addNamedSource(
+        "/libB.dart",
+        r'''
 library libB;
 import 'test.dart
 class B {}''');
@@ -6224,8 +6314,8 @@
     ClassElement importedType =
         new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName));
     LibraryElement importedLibrary = createTestLibrary(context, "imported");
-    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl).types =
-        <ClassElement>[importedType];
+    (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
+        .types = <ClassElement>[importedType];
     LibraryElementImpl definingLibrary =
         createTestLibrary(context, "importing");
     ImportElementImpl importElement = new ImportElementImpl(0);
@@ -6346,7 +6436,9 @@
   }
 
   Library _createLibrary(String definingCompilationUnitPath) => new Library(
-      _analysisContext, _errorListener, new FileBasedSource(
+      _analysisContext,
+      _errorListener,
+      new FileBasedSource(
           FileUtilities2.createFile(definingCompilationUnitPath)));
 }
 
@@ -6506,7 +6598,9 @@
 f() {
   if(A.DEBUG) {}
 }''');
-    addNamedSource("/lib2.dart", r'''
+    addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 class A {
   static const bool DEBUG = false;
@@ -6523,7 +6617,9 @@
 f() {
   if(LIB.A.DEBUG) {}
 }''');
-    addNamedSource("/lib2.dart", r'''
+    addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 class A {
   static const bool DEBUG = false;
@@ -6629,7 +6725,9 @@
 import 'lib1.dart' as one;
 A a;
 one.A a2;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
     computeLibrarySourceErrors(source);
@@ -6644,7 +6742,9 @@
 import 'lib1.dart' hide A;
 A a;
 B b;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}''');
@@ -6660,7 +6760,9 @@
 import 'lib1.dart' show A;
 A a;
 B b;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}''');
@@ -7208,7 +7310,9 @@
 library L;
 @A()
 import 'lib1.dart';''');
-    Source source2 = addNamedSource("/lib1.dart", r'''
+    Source source2 = addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {
   const A() {}
@@ -7226,10 +7330,14 @@
 import 'lib2.dart' as one;
 one.A a;
 one.B b;''');
-    Source source2 = addNamedSource("/lib1.dart", r'''
+    Source source2 = addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}''');
-    Source source3 = addNamedSource("/lib2.dart", r'''
+    Source source3 = addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 class B {}''');
     computeLibrarySourceErrors(source);
@@ -7253,11 +7361,15 @@
 library L;
 import 'lib1.dart';
 Two two;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 export 'lib2.dart';
 class One {}''');
-    addNamedSource("/lib2.dart", r'''
+    addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 class Two {}''');
     computeLibrarySourceErrors(source);
@@ -7270,15 +7382,21 @@
 library L;
 import 'lib1.dart';
 Three three;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 export 'lib2.dart';
 class One {}''');
-    addNamedSource("/lib2.dart", r'''
+    addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 export 'lib3.dart';
 class Two {}''');
-    addNamedSource("/lib3.dart", r'''
+    addNamedSource(
+        "/lib3.dart",
+        r'''
 library lib3;
 class Three {}''');
     computeLibrarySourceErrors(source);
@@ -7291,15 +7409,21 @@
 library L;
 import 'lib1.dart';
 Two two;''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 export 'lib2.dart';
 class One {}''');
-    addNamedSource("/lib2.dart", r'''
+    addNamedSource(
+        "/lib2.dart",
+        r'''
 library lib2;
 export 'lib3.dart';
 class Two {}''');
-    addNamedSource("/lib3.dart", r'''
+    addNamedSource(
+        "/lib3.dart",
+        r'''
 library lib3;
 export 'lib2.dart';
 class Three {}''');
@@ -7317,7 +7441,9 @@
   final int value;
   const A(this.value);
 }''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 const x = 0;''');
     computeLibrarySourceErrors(source);
@@ -7336,7 +7462,9 @@
     one.topLevelFunction();
   }
 }''');
-    addNamedSource("/lib1.dart", r'''
+    addNamedSource(
+        "/lib1.dart",
+        r'''
 library lib1;
 class One {}
 topLevelFunction() {}''');
@@ -7860,7 +7988,8 @@
    * @return the library element that was created
    */
   LibraryElementImpl createTestLibrary(
-      AnalysisContext context, String libraryName, [List<String> typeNames]) {
+      AnalysisContext context, String libraryName,
+      [List<String> typeNames]) {
     String fileName = "$libraryName.dart";
     FileBasedSource definingCompilationUnitSource =
         _createNamedSource(fileName);
@@ -7976,7 +8105,8 @@
     return null;
   }
 
-  void resolveWithAndWithoutExperimental(List<String> strSources,
+  void resolveWithAndWithoutExperimental(
+      List<String> strSources,
       List<ErrorCode> codesWithoutExperimental,
       List<ErrorCode> codesWithExperimental) {
     // Setup analysis context as non-experimental
@@ -8052,7 +8182,8 @@
 
   @override
   Element internalLookup(Identifier identifier, String name,
-      LibraryElement referencingLibrary) => null;
+          LibraryElement referencingLibrary) =>
+      null;
 }
 
 class Scope_EnclosedScopeTest_test_define_normal extends Scope {
@@ -8065,7 +8196,8 @@
 
   @override
   Element internalLookup(Identifier identifier, String name,
-      LibraryElement referencingLibrary) => null;
+          LibraryElement referencingLibrary) =>
+      null;
 }
 
 @reflectiveTest
@@ -8161,7 +8293,8 @@
     expect(
         propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
     expect(
-        propertyAccess.propertyName.auxiliaryElements.staticElement.enclosingElement.name,
+        propertyAccess
+            .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
         'M2');
   }
 
@@ -8736,10 +8869,14 @@
   }
 
   void test_entryPoint_exported() {
-    addNamedSource("/two.dart", r'''
+    addNamedSource(
+        "/two.dart",
+        r'''
 library two;
 main() {}''');
-    Source source = addNamedSource("/one.dart", r'''
+    Source source = addNamedSource(
+        "/one.dart",
+        r'''
 library one;
 export 'two.dart';''');
     LibraryElement library = resolve2(source);
@@ -8752,7 +8889,9 @@
   }
 
   void test_entryPoint_local() {
-    Source source = addNamedSource("/one.dart", r'''
+    Source source = addNamedSource(
+        "/one.dart",
+        r'''
 library one;
 main() {}''');
     LibraryElement library = resolve2(source);
@@ -8774,7 +8913,9 @@
   }
 
   void test_enum_externalLibrary() {
-    addNamedSource("/my_lib.dart", r'''
+    addNamedSource(
+        "/my_lib.dart",
+        r'''
 library my_lib;
 enum EEE {A, B, C}''');
     Source source = addSource(r'''
@@ -8972,14 +9113,20 @@
   }
 
   void test_import_hide() {
-    addNamedSource("lib1.dart", r'''
+    addNamedSource(
+        "lib1.dart",
+        r'''
 library lib1;
 set foo(value) {}
 class A {}''');
-    addNamedSource("lib2.dart", r'''
+    addNamedSource(
+        "lib2.dart",
+        r'''
 library lib2;
 set foo(value) {}''');
-    Source source = addNamedSource("lib3.dart", r'''
+    Source source = addNamedSource(
+        "lib3.dart",
+        r'''
 import 'lib1.dart' hide foo;
 import 'lib2.dart';
 
@@ -8993,12 +9140,16 @@
   }
 
   void test_import_prefix() {
-    addNamedSource("/two.dart", r'''
+    addNamedSource(
+        "/two.dart",
+        r'''
 library two;
 f(int x) {
   return x * x;
 }''');
-    Source source = addNamedSource("/one.dart", r'''
+    Source source = addNamedSource(
+        "/one.dart",
+        r'''
 library one;
 import 'two.dart' as _two;
 main() {
@@ -9010,10 +9161,14 @@
   }
 
   void test_import_spaceInUri() {
-    addNamedSource("sub folder/lib.dart", r'''
+    addNamedSource(
+        "sub folder/lib.dart",
+        r'''
 library lib;
 foo() {}''');
-    Source source = addNamedSource("app.dart", r'''
+    Source source = addNamedSource(
+        "app.dart",
+        r'''
 import 'sub folder/lib.dart';
 
 main() {
@@ -9205,9 +9360,9 @@
     CompilationUnit unit = resolveCompilationUnit(source, library);
     NodeList<CompilationUnitMember> declarations = unit.declarations;
     expect(declarations, hasLength(2));
-    Element expectedElement = (declarations[
-            0] as TopLevelVariableDeclaration).variables.variables[
-        0].name.staticElement;
+    Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
+        .variables
+        .variables[0].name.staticElement;
     EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
         PropertyInducingElement, expectedElement);
     expectedElement = (expectedElement as PropertyInducingElement).getter;
@@ -9396,9 +9551,9 @@
     CompilationUnit unit = resolveCompilationUnit(source, library);
     NodeList<CompilationUnitMember> declarations = unit.declarations;
     expect(declarations, hasLength(2));
-    Element expectedElement = (declarations[
-            0] as TopLevelVariableDeclaration).variables.variables[
-        0].name.staticElement;
+    Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
+        .variables
+        .variables[0].name.staticElement;
     EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
         PropertyInducingElement, expectedElement);
     expectedElement = (expectedElement as PropertyInducingElement).getter;
@@ -9919,11 +10074,15 @@
     // class A extends Derived<int> implements Derived<num> { ... }
     ClassElementImpl classA =
         ElementFactory.classElement('A', derivedType.substitute4([intType]));
-    classA.interfaces = <InterfaceType>[derivedType.substitute4([numType])];
+    classA.interfaces = <InterfaceType>[
+      derivedType.substitute4([numType])
+    ];
     // class B extends Future<num> implements Future<int> { ... }
     ClassElementImpl classB =
         ElementFactory.classElement('B', derivedType.substitute4([numType]));
-    classB.interfaces = <InterfaceType>[derivedType.substitute4([intType])];
+    classB.interfaces = <InterfaceType>[
+      derivedType.substitute4([intType])
+    ];
     // flatten(A) = flatten(B) = int, since int is more specific than num.
     // The code in flatten() that inhibits infinite recursion shouldn't be
     // fooled by the fact that Derived appears twice in the type hierarchy.
@@ -9938,11 +10097,15 @@
     // class A extends Future<int> implements Future<num> { ... }
     ClassElementImpl classA =
         ElementFactory.classElement('A', futureType.substitute4([intType]));
-    classA.interfaces = <InterfaceType>[futureType.substitute4([numType])];
+    classA.interfaces = <InterfaceType>[
+      futureType.substitute4([numType])
+    ];
     // class B extends Future<num> implements Future<int> { ... }
     ClassElementImpl classB =
         ElementFactory.classElement('B', futureType.substitute4([numType]));
-    classB.interfaces = <InterfaceType>[futureType.substitute4([intType])];
+    classB.interfaces = <InterfaceType>[
+      futureType.substitute4([intType])
+    ];
     // flatten(A) = flatten(B) = int, since int is more specific than num.
     expect(_flatten(classA.type), intType);
     expect(_flatten(classB.type), intType);
@@ -9979,11 +10142,15 @@
     // class A extends Future<int> implements Future<String> { ... }
     ClassElementImpl classA =
         ElementFactory.classElement('A', futureType.substitute4([intType]));
-    classA.interfaces = <InterfaceType>[futureType.substitute4([stringType])];
+    classA.interfaces = <InterfaceType>[
+      futureType.substitute4([stringType])
+    ];
     // class B extends Future<String> implements Future<int> { ... }
     ClassElementImpl classB =
         ElementFactory.classElement('B', futureType.substitute4([stringType]));
-    classB.interfaces = <InterfaceType>[futureType.substitute4([intType])];
+    classB.interfaces = <InterfaceType>[
+      futureType.substitute4([intType])
+    ];
     // flatten(A) = A and flatten(B) = B, since neither string nor int is more
     // specific than the other.
     expect(_flatten(classA.type), classA.type);
@@ -10026,7 +10193,8 @@
     // double d; d ??= 0
     Expression node = AstFactory.assignmentExpression(
         _resolvedVariable(_typeProvider.doubleType, 'd'),
-        TokenType.QUESTION_QUESTION_EQ, _resolvedInteger(0));
+        TokenType.QUESTION_QUESTION_EQ,
+        _resolvedInteger(0));
     expect(_analyze(node), same(_typeProvider.numType));
     _listener.assertNoErrors();
   }
@@ -10035,7 +10203,8 @@
     // int i; i ??= 0
     Expression node = AstFactory.assignmentExpression(
         _resolvedVariable(_typeProvider.intType, 'i'),
-        TokenType.QUESTION_QUESTION_EQ, _resolvedInteger(0));
+        TokenType.QUESTION_QUESTION_EQ,
+        _resolvedInteger(0));
     expect(_analyze(node), same(_typeProvider.intType));
     _listener.assertNoErrors();
   }
@@ -10092,7 +10261,8 @@
   void test_visitBinaryExpression_logicalAnd() {
     // false && true
     Expression node = AstFactory.binaryExpression(
-        AstFactory.booleanLiteral(false), TokenType.AMPERSAND_AMPERSAND,
+        AstFactory.booleanLiteral(false),
+        TokenType.AMPERSAND_AMPERSAND,
         AstFactory.booleanLiteral(true));
     expect(_analyze(node), same(_typeProvider.boolType));
     _listener.assertNoErrors();
@@ -10101,7 +10271,8 @@
   void test_visitBinaryExpression_logicalOr() {
     // false || true
     Expression node = AstFactory.binaryExpression(
-        AstFactory.booleanLiteral(false), TokenType.BAR_BAR,
+        AstFactory.booleanLiteral(false),
+        TokenType.BAR_BAR,
         AstFactory.booleanLiteral(true));
     expect(_analyze(node), same(_typeProvider.boolType));
     _listener.assertNoErrors();
@@ -10110,7 +10281,8 @@
   void test_visitBinaryExpression_minusID_propagated() {
     // a - b
     BinaryExpression node = AstFactory.binaryExpression(
-        _propagatedVariable(_typeProvider.intType, 'a'), TokenType.MINUS,
+        _propagatedVariable(_typeProvider.intType, 'a'),
+        TokenType.MINUS,
         _propagatedVariable(_typeProvider.doubleType, 'b'));
     node.propagatedElement = getMethod(_typeProvider.numType, "+");
     _analyze(node);
@@ -10147,7 +10319,8 @@
   void test_visitBinaryExpression_plusII_propagated() {
     // a + b
     BinaryExpression node = AstFactory.binaryExpression(
-        _propagatedVariable(_typeProvider.intType, 'a'), TokenType.PLUS,
+        _propagatedVariable(_typeProvider.intType, 'a'),
+        TokenType.PLUS,
         _propagatedVariable(_typeProvider.intType, 'b'));
     node.propagatedElement = getMethod(_typeProvider.numType, "+");
     _analyze(node);
@@ -10174,9 +10347,11 @@
     MethodElement operator =
         ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]);
     classA.methods = <MethodElement>[operator];
-    BinaryExpression node = AstFactory.binaryExpression(AstFactory.asExpression(
+    BinaryExpression node = AstFactory.binaryExpression(
+        AstFactory.asExpression(
             AstFactory.identifier3("a"), AstFactory.typeName(classA)),
-        TokenType.PLUS, _resolvedDouble(2.0));
+        TokenType.PLUS,
+        _resolvedDouble(2.0));
     node.staticElement = operator;
     expect(_analyze(node), same(typeA));
     _listener.assertNoErrors();
@@ -10216,7 +10391,8 @@
   void test_visitConditionalExpression_differentTypes() {
     // true ? 1.0 : 0
     Expression node = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), _resolvedDouble(1.0),
+        AstFactory.booleanLiteral(true),
+        _resolvedDouble(1.0),
         _resolvedInteger(0));
     expect(_analyze(node), same(_typeProvider.numType));
     _listener.assertNoErrors();
@@ -10225,7 +10401,8 @@
   void test_visitConditionalExpression_sameTypes() {
     // true ? 1 : 0
     Expression node = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), _resolvedInteger(1),
+        AstFactory.booleanLiteral(true),
+        _resolvedInteger(1),
         _resolvedInteger(0));
     expect(_analyze(node), same(_typeProvider.intType));
     _listener.assertNoErrors();
@@ -10377,10 +10554,8 @@
     _analyze5(p1);
     _analyze5(p2);
     DartType resultType = _analyze(node);
-    _assertFunctionType(dynamicType, <DartType>[
-      dynamicType,
-      dynamicType
-    ], null, null, resultType);
+    _assertFunctionType(dynamicType, <DartType>[dynamicType, dynamicType], null,
+        null, resultType);
     _listener.assertNoErrors();
   }
 
@@ -10492,10 +10667,8 @@
     _analyze5(p1);
     _analyze5(p2);
     DartType resultType = _analyze(node);
-    _assertFunctionType(dynamicType, null, <DartType>[
-      dynamicType,
-      dynamicType
-    ], null, resultType);
+    _assertFunctionType(dynamicType, null, <DartType>[dynamicType, dynamicType],
+        null, resultType);
     _listener.assertNoErrors();
   }
 
@@ -10598,7 +10771,8 @@
     constructor.type = constructorType;
     classElement.constructors = <ConstructorElement>[constructor];
     InstanceCreationExpression node = AstFactory.instanceCreationExpression2(
-        null, AstFactory.typeName(classElement),
+        null,
+        AstFactory.typeName(classElement),
         [AstFactory.identifier3(constructorName)]);
     node.staticElement = constructor;
     expect(_analyze(node), same(classElement.type));
@@ -10671,8 +10845,10 @@
     // []
     Expression node = AstFactory.listLiteral();
     DartType resultType = _analyze(node);
-    _assertType2(_typeProvider.listType
-        .substitute4(<DartType>[_typeProvider.dynamicType]), resultType);
+    _assertType2(
+        _typeProvider.listType
+            .substitute4(<DartType>[_typeProvider.dynamicType]),
+        resultType);
     _listener.assertNoErrors();
   }
 
@@ -10680,8 +10856,10 @@
     // [0]
     Expression node = AstFactory.listLiteral([_resolvedInteger(0)]);
     DartType resultType = _analyze(node);
-    _assertType2(_typeProvider.listType
-        .substitute4(<DartType>[_typeProvider.dynamicType]), resultType);
+    _assertType2(
+        _typeProvider.listType
+            .substitute4(<DartType>[_typeProvider.dynamicType]),
+        resultType);
     _listener.assertNoErrors();
   }
 
@@ -10689,7 +10867,8 @@
     // {}
     Expression node = AstFactory.mapLiteral2();
     DartType resultType = _analyze(node);
-    _assertType2(_typeProvider.mapType.substitute4(
+    _assertType2(
+        _typeProvider.mapType.substitute4(
             <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]),
         resultType);
     _listener.assertNoErrors();
@@ -10700,7 +10879,8 @@
     Expression node = AstFactory
         .mapLiteral2([AstFactory.mapLiteralEntry("k", _resolvedInteger(0))]);
     DartType resultType = _analyze(node);
-    _assertType2(_typeProvider.mapType.substitute4(
+    _assertType2(
+        _typeProvider.mapType.substitute4(
             <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]),
         resultType);
     _listener.assertNoErrors();
@@ -10926,8 +11106,9 @@
 
   void test_visitThisExpression() {
     // this
-    InterfaceType thisType = ElementFactory.classElement(
-        "B", ElementFactory.classElement2("A").type).type;
+    InterfaceType thisType = ElementFactory
+        .classElement("B", ElementFactory.classElement2("A").type)
+        .type;
     Expression node = AstFactory.thisExpression();
     expect(_analyze3(node, thisType), same(thisType));
     _listener.assertNoErrors();
@@ -11026,9 +11207,12 @@
    * @param expectedNamedTypes the expected types of the named parameters
    * @param actualType the type being tested
    */
-  void _assertFunctionType(DartType expectedReturnType,
-      List<DartType> expectedNormalTypes, List<DartType> expectedOptionalTypes,
-      Map<String, DartType> expectedNamedTypes, DartType actualType) {
+  void _assertFunctionType(
+      DartType expectedReturnType,
+      List<DartType> expectedNormalTypes,
+      List<DartType> expectedOptionalTypes,
+      Map<String, DartType> expectedNamedTypes,
+      DartType actualType) {
     EngineTestCase.assertInstanceOf(
         (obj) => obj is FunctionType, FunctionType, actualType);
     FunctionType functionType = actualType as FunctionType;
@@ -11781,7 +11965,9 @@
 @reflectiveTest
 class TypePropagationTest extends ResolverTestCase {
   void fail_finalPropertyInducingVariable_classMember_instance() {
-    addNamedSource("/lib.dart", r'''
+    addNamedSource(
+        "/lib.dart",
+        r'''
 class A {
   final v = 0;
 }''');
@@ -11795,7 +11981,9 @@
   }
 
   void fail_finalPropertyInducingVariable_classMember_instance_inherited() {
-    addNamedSource("/lib.dart", r'''
+    addNamedSource(
+        "/lib.dart",
+        r'''
 class A {
   final v = 0;
 }''');
@@ -11811,7 +11999,9 @@
   }
 
   void fail_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
-    addNamedSource("/lib.dart", r'''
+    addNamedSource(
+        "/lib.dart",
+        r'''
 class A {
   final v = 0;
 }''');
@@ -11827,7 +12017,9 @@
   }
 
   void fail_finalPropertyInducingVariable_classMember_static() {
-    addNamedSource("/lib.dart", r'''
+    addNamedSource(
+        "/lib.dart",
+        r'''
 class A {
   static final V = 0;
 }''');
@@ -11864,7 +12056,8 @@
 
   void fail_mergePropagatedTypesAtJoinPoint_1() {
     // https://code.google.com/p/dart/issues/detail?id=19929
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f1(x) {
   var y = [];
   if (x) {
@@ -11875,12 +12068,15 @@
   // Propagated type is [List] here: incorrect.
   // Best we can do is [Object]?
   return y; // marker
-}''', null, typeProvider.dynamicType);
+}''',
+        null,
+        typeProvider.dynamicType);
   }
 
   void fail_mergePropagatedTypesAtJoinPoint_2() {
     // https://code.google.com/p/dart/issues/detail?id=19929
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f2(x) {
   var y = [];
   if (x) {
@@ -11890,12 +12086,15 @@
   // Propagated type is [List] here: incorrect.
   // Best we can do is [Object]?
   return y; // marker
-}''', null, typeProvider.dynamicType);
+}''',
+        null,
+        typeProvider.dynamicType);
   }
 
   void fail_mergePropagatedTypesAtJoinPoint_3() {
     // https://code.google.com/p/dart/issues/detail?id=19929
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f4(x) {
   var y = [];
   if (x) {
@@ -11907,12 +12106,15 @@
   // A correct answer is the least upper bound of [int] and [double],
   // i.e. [num].
   return y; // marker
-}''', null, typeProvider.numType);
+}''',
+        null,
+        typeProvider.numType);
   }
 
   void fail_mergePropagatedTypesAtJoinPoint_5() {
     // https://code.google.com/p/dart/issues/detail?id=19929
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f6(x,y) {
   var z = [];
   if (x || (z = y) < 0) {
@@ -11922,7 +12124,9 @@
   // Propagated type is [List] here: incorrect.
   // Best we can do is [Object]?
   return z; // marker
-}''', null, typeProvider.dynamicType);
+}''',
+        null,
+        typeProvider.dynamicType);
   }
 
   void fail_mergePropagatedTypesAtJoinPoint_7() {
@@ -12162,6 +12366,34 @@
     }
   }
 
+  void test_forEach_async() {
+    String code = r'''
+import 'dart:async';
+f(Stream<String> stream) async {
+  await for (var e in stream) {
+    e;
+  }
+}''';
+    Source source = addSource(code);
+    LibraryElement library = resolve2(source);
+    assertNoErrors(source);
+    verify([source]);
+    CompilationUnit unit = resolveCompilationUnit(source, library);
+    InterfaceType stringType = typeProvider.stringType;
+    // in the declaration
+    {
+      SimpleIdentifier identifier = EngineTestCase.findNode(
+          unit, code, "e in", (node) => node is SimpleIdentifier);
+      expect(identifier.propagatedType, same(stringType));
+    }
+    // in the loop body
+    {
+      SimpleIdentifier identifier = EngineTestCase.findNode(
+          unit, code, "e;", (node) => node is SimpleIdentifier);
+      expect(identifier.propagatedType, same(stringType));
+    }
+  }
+
   void test_functionExpression_asInvocationArgument() {
     String code = r'''
 class MyMap<K, V> {
@@ -12984,18 +13216,22 @@
   }
 
   void test_mergePropagatedTypes_afterIfThen_same() {
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 main() {
   var v = 1;
   if (v != null) {
     v = 2;
   }
   return v; // marker
-}''', null, typeProvider.intType);
+}''',
+        null,
+        typeProvider.intType);
   }
 
   void test_mergePropagatedTypes_afterIfThenElse_different() {
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 main() {
   var v = 1;
   if (v != null) {
@@ -13004,11 +13240,14 @@
     v = '3';
   }
   return v; // marker
-}''', null, null);
+}''',
+        null,
+        null);
   }
 
   void test_mergePropagatedTypes_afterIfThenElse_same() {
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 main() {
   var v = 1;
   if (v != null) {
@@ -13017,12 +13256,15 @@
     v = 3;
   }
   return v; // marker
-}''', null, typeProvider.intType);
+}''',
+        null,
+        typeProvider.intType);
   }
 
   void test_mergePropagatedTypesAtJoinPoint_4() {
     // https://code.google.com/p/dart/issues/detail?id=19929
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f5(x) {
   var y = [];
   if (x) {
@@ -13032,7 +13274,9 @@
   }
   // Propagated type is [int] here: correct.
   return y; // marker
-}''', null, typeProvider.intType);
+}''',
+        null,
+        typeProvider.intType);
   }
 
   void test_mutatedOutsideScope() {
@@ -13073,38 +13317,50 @@
     // static type of [bool] for [==] comparison and the implementation
     // was already consistent with the spec there. But, it's another
     // [Object] method, so it's included here.
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f1(x) {
   var v = (x == x);
   return v; // marker
-}''', null, typeProvider.boolType);
+}''',
+        null,
+        typeProvider.boolType);
   }
 
   void test_objectMethodOnDynamicExpression_hashCode() {
     // https://code.google.com/p/dart/issues/detail?id=20342
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f1(x) {
   var v = x.hashCode;
   return v; // marker
-}''', null, typeProvider.intType);
+}''',
+        null,
+        typeProvider.intType);
   }
 
   void test_objectMethodOnDynamicExpression_runtimeType() {
     // https://code.google.com/p/dart/issues/detail?id=20342
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f1(x) {
   var v = x.runtimeType;
   return v; // marker
-}''', null, typeProvider.typeType);
+}''',
+        null,
+        typeProvider.typeType);
   }
 
   void test_objectMethodOnDynamicExpression_toString() {
     // https://code.google.com/p/dart/issues/detail?id=20342
-    _assertTypeOfMarkedExpression(r'''
+    _assertTypeOfMarkedExpression(
+        r'''
 f1(x) {
   var v = x.toString();
   return v; // marker
-}''', null, typeProvider.stringType);
+}''',
+        null,
+        typeProvider.stringType);
   }
 
   void test_propagatedReturnType_function_hasReturnType_returnsNull() {
@@ -13728,10 +13984,14 @@
     ClassElement elementP = ElementFactory.classElement2('P');
     FunctionElement elementF = ElementFactory.functionElement('f');
     FunctionDeclaration declaration = AstFactory.functionDeclaration(
-        AstFactory.typeName4('R'), null, 'f', AstFactory.functionExpression2(
+        AstFactory.typeName4('R'),
+        null,
+        'f',
+        AstFactory.functionExpression2(
             AstFactory.formalParameterList([
-      AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
-    ]), null));
+              AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
+            ]),
+            null));
     declaration.name.staticElement = elementF;
     _resolveNode(declaration, [elementR, elementP]);
     expect(declaration.returnType.type, elementR.type);
@@ -13747,10 +14007,14 @@
     FunctionElementImpl elementF = ElementFactory.functionElement('f');
     elementF.typeParameters = <TypeParameterElement>[elementE];
     FunctionDeclaration declaration = AstFactory.functionDeclaration(
-        AstFactory.typeName4('E'), null, 'f', AstFactory.functionExpression2(
+        AstFactory.typeName4('E'),
+        null,
+        'f',
+        AstFactory.functionExpression2(
             AstFactory.formalParameterList([
-      AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
-    ]), null));
+              AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
+            ]),
+            null));
     declaration.name.staticElement = elementF;
     _resolveNode(declaration, []);
     expect(declaration.returnType.type, elementE.type);
@@ -13775,7 +14039,10 @@
     ]);
     parameterDeclaration.identifier.staticElement = requiredParameter;
     FunctionDeclaration declaration = AstFactory.functionDeclaration(
-        AstFactory.typeName4('R'), null, 'f', AstFactory.functionExpression2(
+        AstFactory.typeName4('R'),
+        null,
+        'f',
+        AstFactory.functionExpression2(
             AstFactory.formalParameterList([parameterDeclaration]), null));
     declaration.name.staticElement = elementF;
     _resolveNode(declaration, [elementR, elementP]);
@@ -13803,7 +14070,10 @@
     ]);
     parameterDeclaration.identifier.staticElement = requiredParameter;
     FunctionDeclaration declaration = AstFactory.functionDeclaration(
-        AstFactory.typeName4('R'), null, 'f', AstFactory.functionExpression2(
+        AstFactory.typeName4('R'),
+        null,
+        'f',
+        AstFactory.functionExpression2(
             AstFactory.formalParameterList([parameterDeclaration]), null));
     declaration.name.staticElement = elementF;
     _resolveNode(declaration, [elementR]);
@@ -13827,11 +14097,15 @@
     ClassElement elementP = ElementFactory.classElement2('P');
     MethodElement elementM = ElementFactory.methodElement('m', null);
     elementA.methods = <MethodElement>[elementM];
-    MethodDeclaration declaration = AstFactory.methodDeclaration(null,
-        AstFactory.typeName4('R'), null, null, AstFactory.identifier3('m'),
+    MethodDeclaration declaration = AstFactory.methodDeclaration(
+        null,
+        AstFactory.typeName4('R'),
+        null,
+        null,
+        AstFactory.identifier3('m'),
         AstFactory.formalParameterList([
-      AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
-    ]));
+          AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
+        ]));
     declaration.name.staticElement = elementM;
     _resolveNode(declaration, [elementA, elementR, elementP]);
     expect(declaration.returnType.type, elementR.type);
@@ -13849,11 +14123,15 @@
     MethodElementImpl elementM = ElementFactory.methodElement('m', null);
     elementM.typeParameters = <TypeParameterElement>[elementE];
     elementA.methods = <MethodElement>[elementM];
-    MethodDeclaration declaration = AstFactory.methodDeclaration(null,
-        AstFactory.typeName4('E'), null, null, AstFactory.identifier3('m'),
+    MethodDeclaration declaration = AstFactory.methodDeclaration(
+        null,
+        AstFactory.typeName4('E'),
+        null,
+        null,
+        AstFactory.identifier3('m'),
         AstFactory.formalParameterList([
-      AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
-    ]));
+          AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
+        ]));
     declaration.name.staticElement = elementM;
     _resolveNode(declaration, [elementA]);
     expect(declaration.returnType.type, elementE.type);
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index c1a6603..296be46 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -266,6 +266,25 @@
     _assertComment(TokenType.MULTI_LINE_COMMENT, "/* comment */");
   }
 
+  void test_comment_multi_lineEnds() {
+    String code = r'''
+/**
+ * aa
+ * bbb
+ * c
+ */''';
+    GatheringErrorListener listener = new GatheringErrorListener();
+    Scanner scanner = new Scanner(null, new CharSequenceReader(code), listener);
+    scanner.tokenize();
+    expect(scanner.lineStarts, equals(<int>[
+      code.indexOf('/**'),
+      code.indexOf(' * aa'),
+      code.indexOf(' * bbb'),
+      code.indexOf(' * c'),
+      code.indexOf(' */')
+    ]));
+  }
+
   void test_comment_multi_unterminated() {
     _assertError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, 3, "/* x");
   }
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index 7ff5572..36ec73e 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -33,6 +33,12 @@
   runPackageMapTests();
 }
 
+Source createSource({String path, String uri}) =>
+    //TODO(pquitslund): find some way to pass an actual URI into source creation
+    new MemoryResourceProvider()
+        .getFile(path)
+        .createSource(uri != null ? Uri.parse(uri) : null);
+
 void runPackageMapTests() {
   final Uri baseUri = new Uri.file('test/base');
   final List<UriResolver> testResolvers = [new FileUriResolver()];
@@ -170,16 +176,13 @@
   });
 }
 
-Source createSource({String path, String uri}) => new MemoryResourceProvider()
-    .getFile(path)
-    .createSource(uri != null ? Uri.parse(uri) : null);
-
 class CustomUriResolver extends UriResolver {
   String uriPath;
   CustomUriResolver({this.uriPath});
 
   @override
-  Source resolveAbsolute(Uri uri) => createSource(path: uriPath);
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) =>
+      createSource(path: uriPath);
 }
 
 @reflectiveTest
@@ -282,7 +285,7 @@
   UriResolver_absolute();
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     invoked = true;
     return null;
   }
@@ -290,15 +293,15 @@
 
 class UriResolver_nonAbsolute_absolute extends UriResolver {
   @override
-  Source resolveAbsolute(Uri uri) {
-    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    return new FileBasedSource(new JavaFile.fromUri(uri), actualUri);
   }
 }
 
 class UriResolver_nonAbsolute_relative extends UriResolver {
   @override
-  Source resolveAbsolute(Uri uri) {
-    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    return new FileBasedSource(new JavaFile.fromUri(uri), actualUri);
   }
 }
 
@@ -308,7 +311,7 @@
   UriResolver_restoreUri(this.source1, this.expected1);
 
   @override
-  Source resolveAbsolute(Uri uri) => null;
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) => null;
 
   @override
   Uri restoreAbsolute(Source source) {
@@ -325,7 +328,7 @@
   UriResolver_SourceFactoryTest_test_fromEncoding_valid(this.encoding);
 
   @override
-  Source resolveAbsolute(Uri uri) {
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (uri.toString() == encoding) {
       return new TestSource();
     }
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 a346a87..b49a115 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -1391,14 +1391,12 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
-  void test_undefinedGetter_static_conditionalAccess() {
-    // The conditional access operator '?.' cannot be used to access static
-    // fields.
+  void test_undefinedGetter_typeLiteral_conditionalAccess() {
+    // When applied to a type literal, the conditional access operator '?.'
+    // cannot be used to access instance getters of Type.
     Source source = addSource('''
-class A {
-  static var x;
-}
-var a = A?.x;
+class A {}
+f() => A?.hashCode;
 ''');
     computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
@@ -1562,14 +1560,12 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
-  void test_undefinedMethod_static_conditionalAccess() {
-    // The conditional access operator '?.' cannot be used to access static
-    // methods.
+  void test_undefinedMethod_typeLiteral_conditionalAccess() {
+    // When applied to a type literal, the conditional access operator '?.'
+    // cannot be used to access instance methods of Type.
     Source source = addSource('''
-class A {
-  static void m() {}
-}
-f() { A?.m(); }
+class A {}
+f() => A?.toString();
 ''');
     computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
@@ -1651,19 +1647,6 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
-  void test_undefinedSetter_static_conditionalAccess() {
-    // The conditional access operator '?.' cannot be used to access static
-    // fields.
-    Source source = addSource('''
-class A {
-  static var x;
-}
-f() { A?.x = 1; }
-''');
-    computeLibrarySourceErrors(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
-  }
-
   void test_undefinedSetter_void() {
     Source source = addSource(r'''
 class T {
diff --git a/pkg/analyzer/test/source/path_filter_test.dart b/pkg/analyzer/test/source/path_filter_test.dart
index 6b0131a..4542e99 100644
--- a/pkg/analyzer/test/source/path_filter_test.dart
+++ b/pkg/analyzer/test/source/path_filter_test.dart
@@ -4,46 +4,47 @@
 
 library test.source.path_filter;
 
-import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/path_filter.dart';
+import 'package:path/path.dart';
 import 'package:unittest/unittest.dart';
 
 main() {
   groupSep = ' | ';
   group('PathFilterTest', () {
-    setUp(() { });
-    tearDown(() { });
+    setUp(() {});
+    tearDown(() {});
     test('test_ignoreEverything', () {
-      var filter = new PathFilter('/', ['*']);
+      var filter = new PathFilter(context, '/', ['*']);
       expect(filter.ignored('a'), isTrue);
     });
     test('test_ignoreFile', () {
-      var filter = new PathFilter('/', ['apple']);
+      var filter = new PathFilter(context, '/', ['apple']);
       expect(filter.ignored('apple'), isTrue);
       expect(filter.ignored('banana'), isFalse);
     });
     test('test_ignoreMultipleFiles', () {
-      var filter = new PathFilter('/', ['apple', 'banana']);
+      var filter = new PathFilter(context, '/', ['apple', 'banana']);
       expect(filter.ignored('apple'), isTrue);
       expect(filter.ignored('banana'), isTrue);
     });
     test('test_ignoreSubDir', () {
-      var filter = new PathFilter('/', ['apple/*']);
+      var filter = new PathFilter(context, '/', ['apple/*']);
       expect(filter.ignored('apple/banana'), isTrue);
       expect(filter.ignored('apple/banana/cantaloupe'), isFalse);
     });
     test('test_ignoreTree', () {
-      var filter = new PathFilter('/', ['apple/**']);
+      var filter = new PathFilter(context, '/', ['apple/**']);
       expect(filter.ignored('apple/banana'), isTrue);
       expect(filter.ignored('apple/banana/cantaloupe'), isTrue);
     });
     test('test_ignoreSdkExt', () {
-      var filter = new PathFilter('/', ['sdk_ext/**']);
+      var filter = new PathFilter(context, '/', ['sdk_ext/**']);
       expect(filter.ignored('sdk_ext/entry.dart'), isTrue);
       expect(filter.ignored('sdk_ext/lib/src/part.dart'), isTrue);
     });
     test('test_outsideRoot', () {
-      var filter = new PathFilter('/workspace/dart/sdk', ['sdk_ext/**']);
+      var filter =
+          new PathFilter(context, '/workspace/dart/sdk', ['sdk_ext/**']);
       expect(filter.ignored('/'), isTrue);
       expect(filter.ignored('/workspace'), isTrue);
       expect(filter.ignored('/workspace/dart'), isTrue);
@@ -51,7 +52,8 @@
       expect(filter.ignored('/workspace/dart/../dart/sdk'), isFalse);
     });
     test('test_relativePaths', () {
-      var filter = new PathFilter('/workspace/dart/sdk', ['sdk_ext/**']);
+      var filter =
+          new PathFilter(context, '/workspace/dart/sdk', ['sdk_ext/**']);
       expect(filter.ignored('../apple'), isTrue);
       expect(filter.ignored('../sdk/main.dart'), isFalse);
       expect(filter.ignored('../sdk/sdk_ext/entry.dart'), isTrue);
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index 3ec05ec..7d4ef18 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -67,7 +67,12 @@
   /// zero-based character offsets from the beginning of the compilation unit.
   /// [message] is the diagnostic message, and [kind] indicates indicates what
   /// kind of diagnostic it is.
-  void report(Uri uri, int begin, int end, String message, Diagnostic kind);
+  ///
+  /// 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);
 }
 
 /// Information resulting from the compilation.
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index cac25b1..808f88f1 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -196,7 +196,8 @@
   }
 
   void log(message) {
-    callUserHandler(null, null, null, message, api.Diagnostic.VERBOSE_INFO);
+    callUserHandler(
+        null, null, null, null, message, api.Diagnostic.VERBOSE_INFO);
   }
 
   /// See [leg.Compiler.translateResolvedUri].
@@ -427,9 +428,10 @@
     // [:span.uri:] might be [:null:] in case of a [Script] with no [uri]. For
     // instance in the [Types] constructor in typechecker.dart.
     if (span == null || span.uri == null) {
-      callUserHandler(null, null, null, '$message', kind);
+      callUserHandler(message, null, null, null, '$message', kind);
     } else {
-      callUserHandler(span.uri, span.begin, span.end, '$message', kind);
+      callUserHandler(
+          message, span.uri, span.begin, span.end, '$message', kind);
     }
   }
 
@@ -438,11 +440,11 @@
       && (options.indexOf('--allow-mock-compilation') != -1);
   }
 
-  void callUserHandler(Uri uri, int begin, int end,
-                       String message, api.Diagnostic kind) {
+  void callUserHandler(leg.Message message, Uri uri, int begin, int end,
+                       String text, api.Diagnostic kind) {
     try {
       userHandlerTask.measure(() {
-        handler.report(uri, begin, end, message, kind);
+        handler.report(message, uri, begin, end, text, kind);
       });
     } catch (ex, s) {
       diagnoseCrashInUserCode(
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 4b0be2d..b203ec1 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -336,6 +336,8 @@
   ConstantSystem get constantSystem => handler.constantSystem;
 
   AstConstant evaluate(Node node) {
+    // TODO(johnniwinther): should there be a visitErrorNode?
+    if (node is ErrorNode) return new ErroneousAstConstant(context, node);
     return node.accept(this);
   }
 
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index d35e501..1ed9781 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1162,14 +1162,17 @@
   void unhandledExceptionOnElement(Element element) {
     if (hasCrashed) return;
     hasCrashed = true;
-    reportDiagnostic(element,
-                     MessageKind.COMPILER_CRASHED.message(),
-                     api.Diagnostic.CRASH);
+    reportDiagnostic(
+        element,
+        MessageTemplate.TEMPLATES[MessageKind.COMPILER_CRASHED].message(),
+        api.Diagnostic.CRASH);
     pleaseReportCrash();
   }
 
   void pleaseReportCrash() {
-    print(MessageKind.PLEASE_REPORT_THE_CRASH.message({'buildId': buildId}));
+    print(
+        MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
+            .message({'buildId': buildId}));
   }
 
   SourceSpan spanFromSpannable(Spannable node) {
@@ -1225,7 +1228,8 @@
 
   void log(message) {
     reportDiagnostic(null,
-        MessageKind.GENERIC.message({'text': '$message'}),
+        MessageTemplate.TEMPLATES[MessageKind.GENERIC]
+            .message({'text': '$message'}),
         api.Diagnostic.VERBOSE_INFO);
   }
 
@@ -1239,9 +1243,11 @@
           if (error is SpannableAssertionFailure) {
             reportAssertionFailure(error);
           } else {
-            reportDiagnostic(new SourceSpan(uri, 0, 0),
-                             MessageKind.COMPILER_CRASHED.message(),
-                             api.Diagnostic.CRASH);
+            reportDiagnostic(
+                new SourceSpan(uri, 0, 0),
+                MessageTemplate.TEMPLATES[MessageKind.COMPILER_CRASHED]
+                    .message(),
+                api.Diagnostic.CRASH);
           }
           pleaseReportCrash();
         }
@@ -1379,7 +1385,7 @@
           reportWarning(NO_LOCATION_SPANNABLE,
              MessageKind.IMPORT_EXPERIMENTAL_MIRRORS,
               {'importChain': importChains.join(
-                   MessageKind.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)});
+                   MessageTemplate.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)});
         }
       }
 
@@ -1615,11 +1621,13 @@
         } else if (info.hints == 0) {
           kind = MessageKind.HIDDEN_WARNINGS;
         }
+        MessageTemplate template = MessageTemplate.TEMPLATES[kind];
         reportDiagnostic(null,
-            kind.message({'warnings': info.warnings,
-                          'hints': info.hints,
-                          'uri': uri},
-                         terseDiagnostics),
+            template.message(
+                {'warnings': info.warnings,
+                 'hints': info.hints,
+                 'uri': uri},
+                terseDiagnostics),
             api.Diagnostic.HINT);
       });
     }
@@ -1897,8 +1905,11 @@
       }
     }
     lastDiagnosticWasFiltered = false;
+    MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
     reportDiagnostic(
-        node, messageKind.message(arguments, terseDiagnostics), kind);
+        node,
+        template.message(arguments, terseDiagnostics),
+        kind);
   }
 
   void reportDiagnostic(Spannable span,
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
index db1ea0b..0c8e027 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -109,7 +109,7 @@
 
   /// Invoke a built-in operator.
   Primitive applyBuiltin(BuiltinOperator op, List<Primitive> args) {
-    return letPrim(new ApplyBuiltinOperator(op, args));
+    return letPrim(new ApplyBuiltinOperator(op, args, sourceInformation));
   }
 
   /// Inserts an invocation. binds its continuation, and returns the
@@ -258,10 +258,10 @@
   }
 
   /// Puts the given fragment into this one.
-  /// 
+  ///
   /// If [other] was an open fragment, its hole becomes the new hole
   /// in this fragment.
-  /// 
+  ///
   /// [other] is reset to an empty fragment after this.
   void append(CpsFragment other) {
     if (other.root == null) return;
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 7117c80..4ec13ad 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -638,7 +638,7 @@
                                    Selector selector,
                                    TypeMask mask,
                                    List<ir.Primitive> arguments,
-                                   {SourceInformation sourceInformation}) {
+                                   SourceInformation sourceInformation) {
     assert(isOpen);
     return _continueWithExpression(
         (k) => new ir.InvokeMethod(receiver, selector, mask, arguments, k,
@@ -651,8 +651,8 @@
                                 List<ir.Definition> arguments,
                                 {SourceInformation sourceInformation}) {
     Selector selector = callStructure.callSelector;
-    return _buildInvokeDynamic(target, selector, mask, arguments,
-        sourceInformation: sourceInformation);
+    return _buildInvokeDynamic(
+        target, selector, mask, arguments, sourceInformation);
   }
 
 
@@ -877,15 +877,15 @@
                                       List<ir.Primitive> arguments,
                                       {SourceInformation sourceInformation}) {
     return _buildInvokeDynamic(
-        receiver, selector, mask, arguments,
-        sourceInformation: sourceInformation);
+        receiver, selector, mask, arguments, sourceInformation);
   }
 
   /// Create a dynamic getter invocation on [receiver] where the getter name is
   /// defined by [selector].
   ir.Primitive buildDynamicGet(ir.Primitive receiver,
                                Selector selector,
-                               TypeMask mask) {
+                               TypeMask mask,
+                               SourceInformation sourceInformation) {
     assert(selector.isGetter);
     FieldElement field = program.locateSingleField(selector, mask);
     if (field != null) {
@@ -894,7 +894,7 @@
       return buildFieldGet(receiver, field);
     } else {
       return _buildInvokeDynamic(
-          receiver, selector, mask, const <ir.Primitive>[]);
+          receiver, selector, mask, const <ir.Primitive>[], sourceInformation);
     }
   }
 
@@ -903,7 +903,8 @@
   ir.Primitive buildDynamicSet(ir.Primitive receiver,
                                Selector selector,
                                TypeMask mask,
-                               ir.Primitive value) {
+                               ir.Primitive value,
+                               {SourceInformation sourceInformation}) {
     assert(selector.isSetter);
     FieldElement field = program.locateSingleField(selector, mask);
     if (field != null) {
@@ -911,19 +912,22 @@
       // treated as a field access, since the setter might not be emitted.
       buildFieldSet(receiver, field, value);
     } else {
-      _buildInvokeDynamic(receiver, selector, mask, <ir.Primitive>[value]);
+      _buildInvokeDynamic(receiver, selector, mask, <ir.Primitive>[value],
+                          sourceInformation);
     }
     return value;
   }
 
   /// Create a dynamic index set invocation on [receiver] with the provided
   /// [index] and [value].
-  ir.Primitive  buildDynamicIndexSet(ir.Primitive receiver,
-                                     TypeMask mask,
-                                     ir.Primitive index,
-                                     ir.Primitive value) {
+  ir.Primitive buildDynamicIndexSet(ir.Primitive receiver,
+                                    TypeMask mask,
+                                    ir.Primitive index,
+                                    ir.Primitive value,
+                                    {SourceInformation sourceInformation}) {
     _buildInvokeDynamic(
-        receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value]);
+        receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value],
+        sourceInformation);
     return value;
   }
 
@@ -1043,11 +1047,13 @@
   ///
   /// The arguments must be strings; usually a call to [buildStringify] is
   /// needed to ensure the proper conversion takes places.
-  ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) {
+  ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments,
+                                        {SourceInformation sourceInformation}) {
     assert(isOpen);
     return addPrimitive(new ir.ApplyBuiltinOperator(
         ir.BuiltinOperator.StringConcatenate,
-        arguments));
+        arguments,
+        sourceInformation));
   }
 
   /// Create an invocation of the `call` method of [functionExpression], where
@@ -1829,8 +1835,10 @@
 
       ir.Expression buildCatchClause(CatchClauseInfo clause) {
         IrBuilder clauseBuilder = builder.makeDelimitedBuilder();
-        clauseBuilder.declareLocalVariable(clause.exceptionVariable,
-            initialValue: exceptionParameter);
+        if (clause.exceptionVariable != null) {
+          clauseBuilder.declareLocalVariable(clause.exceptionVariable,
+              initialValue: exceptionParameter);
+        }
         if (clause.stackTraceVariable != null) {
           clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
               initialValue: traceParameter);
@@ -2098,7 +2106,10 @@
 
   ir.Primitive buildNonTailThrow(ir.Primitive value) {
     assert(isOpen);
-    return addPrimitive(new ir.NonTailThrow(value));
+    ir.Parameter param = new ir.Parameter(null);
+    ir.Continuation cont = new ir.Continuation(<ir.Parameter>[param]);
+    add(new ir.LetCont(cont, new ir.Throw(value)));
+    return param;
   }
 
   void buildRethrow() {
@@ -2215,9 +2226,11 @@
     return environment.discard(1);
   }
 
-  ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y) {
+  ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y,
+                              {SourceInformation sourceInformation}) {
     return addPrimitive(new ir.ApplyBuiltinOperator(
-        ir.BuiltinOperator.Identical, <ir.Primitive>[x, y]));
+        ir.BuiltinOperator.Identical, <ir.Primitive>[x, y],
+        sourceInformation));
   }
 
   /// Called when entering a nested function with free variables.
@@ -2659,8 +2672,10 @@
   /// `right` if [value] is null. Only when [value] is null, [buildRight] is
   /// evaluated to produce the `right` value.
   ir.Primitive buildIfNull(ir.Primitive value,
-                           ir.Primitive buildRight(IrBuilder builder)) {
-    ir.Primitive condition = _buildCheckNull(value);
+                           ir.Primitive buildRight(IrBuilder builder),
+                           {SourceInformation sourceInformation}) {
+    ir.Primitive condition =
+        _buildCheckNull(value, sourceInformation: sourceInformation);
     return buildConditional(condition, buildRight, (_) => value);
   }
 
@@ -2668,15 +2683,19 @@
   /// that checks if [receiver] is null, if so, it returns null, otherwise it
   /// evaluates the [buildSend] expression.
   ir.Primitive buildIfNotNullSend(ir.Primitive receiver,
-                                  ir.Primitive buildSend(IrBuilder builder)) {
-    ir.Primitive condition = _buildCheckNull(receiver);
+                                  ir.Primitive buildSend(IrBuilder builder),
+                                  {SourceInformation sourceInformation}) {
+    ir.Primitive condition =
+        _buildCheckNull(receiver, sourceInformation: sourceInformation);
     return buildConditional(condition, (_) => receiver, buildSend);
   }
 
   /// Creates a type test checking whether [value] is null.
-  ir.Primitive _buildCheckNull(ir.Primitive value) {
+  ir.Primitive _buildCheckNull(ir.Primitive value,
+                               {SourceInformation sourceInformation}) {
     assert(isOpen);
-    return buildIdentical(value, buildNullConstant());
+    return buildIdentical(value, buildNullConstant(),
+        sourceInformation: sourceInformation);
   }
 
   /// Convert the given value to a string.
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 2ce1b01..238a3fc 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
@@ -95,6 +95,7 @@
     with IrBuilderMixin<ast.Node>,
          SemanticSendResolvedMixin<ir.Primitive, dynamic>,
          SendResolverMixin,
+         ErrorBulkMixin<ir.Primitive, dynamic>,
          BaseImplementationOfStaticsMixin<ir.Primitive, dynamic>,
          BaseImplementationOfLocalsMixin<ir.Primitive, dynamic>,
          BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>,
@@ -453,8 +454,10 @@
   visitTryStatement(ast.TryStatement node) {
     List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[];
     for (ast.CatchBlock catchClause in node.catchBlocks.nodes) {
-      assert(catchClause.exception != null);
-      LocalVariableElement exceptionVariable = elements[catchClause.exception];
+      LocalVariableElement exceptionVariable;
+      if (catchClause.exception != null) {
+        exceptionVariable = elements[catchClause.exception];
+      }
       LocalVariableElement stackTraceVariable;
       if (catchClause.trace != null) {
         stackTraceVariable = elements[catchClause.trace];
@@ -606,7 +609,7 @@
     } else {
       // The call to assert and its argument expression must be ignored
       // in production mode.
-      // Assertions can onl)y occur in expression statements, so no value needs
+      // Assertions can only occur in expression statements, so no value needs
       // to be returned.
       return null;
     }
@@ -665,7 +668,8 @@
     return irBuilder.buildDynamicGet(
         translateReceiver(receiver),
         selector,
-        elements.getTypeMask(node));
+        elements.getTypeMask(node),
+        sourceInformationBuilder.buildGet(node));
   }
 
   @override
@@ -678,7 +682,8 @@
     return irBuilder.buildIfNotNullSend(
         target,
         nested(() => irBuilder.buildDynamicGet(
-            target, selector, elements.getTypeMask(node))));
+            target, selector, elements.getTypeMask(node),
+            sourceInformationBuilder.buildGet(node))));
   }
 
   @override
@@ -886,7 +891,9 @@
     List<ir.Primitive> arguments = <ir.Primitive>[visit(index)];
     arguments = normalizeDynamicArguments(selector.callStructure, arguments);
     return irBuilder.buildDynamicInvocation(
-        target, selector, elements.getTypeMask(node), arguments);
+        target, selector, elements.getTypeMask(node), arguments,
+        sourceInformation:
+            sourceInformationBuilder.buildCall(receiver, node.selector));
   }
 
   ir.Primitive translateSuperBinary(FunctionElement function,
@@ -971,7 +978,9 @@
     Selector selector = operator.selector;
     ir.Primitive receiver = translateReceiver(expression);
     return irBuilder.buildDynamicInvocation(
-        receiver, selector, elements.getTypeMask(node), const []);
+        receiver, selector, elements.getTypeMask(node), const [],
+        sourceInformation: sourceInformationBuilder.buildCall(
+            expression, node));
   }
 
   @override
@@ -1254,10 +1263,10 @@
   }
 
   ir.Primitive translateCompounds(
+      ast.SendSet node,
       {ir.Primitive getValue(),
        CompoundRhs rhs,
-       void setValue(ir.Primitive value),
-       TypeMask operatorTypeMask}) {
+       void setValue(ir.Primitive value)}) {
     ir.Primitive value = getValue();
     op.BinaryOperator operator = rhs.operator;
     if (operator.kind == op.BinaryOperatorKind.IF_NULL) {
@@ -1281,9 +1290,13 @@
     List<ir.Primitive> arguments = <ir.Primitive>[rhsValue];
     arguments = normalizeDynamicArguments(
         operatorSelector.callStructure, arguments);
-    ir.Primitive result =
-        irBuilder.buildDynamicInvocation(
-            value, operatorSelector, operatorTypeMask, arguments);
+    TypeMask operatorTypeMask =
+        elements.getOperatorTypeMaskInComplexSendSet(node);
+    SourceInformation operatorSourceInformation =
+        sourceInformationBuilder.buildCall(node, node.assignmentOperator);
+    ir.Primitive result = irBuilder.buildDynamicInvocation(
+        value, operatorSelector, operatorTypeMask, arguments,
+            sourceInformation: operatorSourceInformation);
     setValue(result);
     return rhs.kind == CompoundKind.POSTFIX ? value : result;
   }
@@ -1378,13 +1391,13 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
+        node,
         getValue: () {
           return buildConstantExpression(constant,
             sourceInformationBuilder.buildGet(node));
         },
         rhs: rhs,
-        setValue: (value) {}, // The binary operator will throw before this.
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        setValue: (value) {}); // The binary operator will throw before this.
   }
 
   @override
@@ -1398,16 +1411,17 @@
     ir.Primitive target = translateReceiver(receiver);
     ir.Primitive helper() {
       return translateCompounds(
+          node,
           getValue: () => irBuilder.buildDynamicGet(
               target,
               getterSelector,
-              elements.getGetterTypeMaskInComplexSendSet(node)),
+              elements.getGetterTypeMaskInComplexSendSet(node),
+              sourceInformationBuilder.buildGet(node)),
           rhs: rhs,
           setValue: (ir.Primitive result) {
             irBuilder.buildDynamicSet(
                 target, setterSelector, elements.getTypeMask(node), result);
-          },
-          operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+          });
     }
     return node.isConditional
         ? irBuilder.buildIfNotNullSend(target, nested(helper))
@@ -1427,6 +1441,7 @@
       arg,
       {bool isSetterValid}) {
     return translateCompounds(
+        node,
         getValue: () {
           if (local.isFunction) {
             return irBuilder.buildLocalFunctionGet(local);
@@ -1441,8 +1456,7 @@
           } else {
             return buildLocalNoSuchSetter(local, result);
           }
-        },
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        });
   }
 
   ir.Primitive buildStaticNoSuchGetter(Element element) {
@@ -1467,6 +1481,7 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
+        node,
         getValue: () {
           switch (getterKind) {
             case CompoundGetter.FIELD:
@@ -1493,8 +1508,7 @@
               return buildStaticNoSuchSetter(
                   setter != null ? setter : getter, result);
           }
-        },
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        });
   }
 
   ir.Primitive buildSuperNoSuchGetter(Element element, TypeMask mask) {
@@ -1523,6 +1537,7 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
+        node,
         getValue: () {
           switch (getterKind) {
             case CompoundGetter.FIELD:
@@ -1550,8 +1565,7 @@
               return buildSuperNoSuchSetter(
                   setter, elements.getTypeMask(node), result);
           }
-        },
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        });
   }
 
   @override
@@ -1561,14 +1575,14 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
+        node,
         getValue: () {
           return irBuilder.buildReifyTypeVariable(
             typeVariable.type,
             sourceInformationBuilder.buildGet(node));
         },
         rhs: rhs,
-        setValue: (value) {}, // The binary operator will throw before this.
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        setValue: (value) {}); // The binary operator will throw before this.
   }
 
   @override
@@ -1581,6 +1595,7 @@
     ir.Primitive target = visit(receiver);
     ir.Primitive indexValue = visit(index);
     return translateCompounds(
+        node,
         getValue: () {
           Selector selector = new Selector.index();
           List<ir.Primitive> arguments = <ir.Primitive>[indexValue];
@@ -1590,7 +1605,9 @@
               target,
               selector,
               elements.getGetterTypeMaskInComplexSendSet(node),
-              arguments);
+              arguments,
+              sourceInformation:
+                  sourceInformationBuilder.buildCall(receiver, node));
         },
         rhs: rhs,
         setValue: (ir.Primitive result) {
@@ -1599,8 +1616,7 @@
               elements.getTypeMask(node),
               indexValue,
               result);
-        },
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        });
   }
 
   @override
@@ -1615,6 +1631,7 @@
        bool isSetterValid}) {
     ir.Primitive indexValue = visit(index);
     return translateCompounds(
+        node,
         getValue: () {
           if (isGetterValid) {
             return irBuilder.buildSuperIndex(indexFunction, indexValue);
@@ -1635,8 +1652,7 @@
                 elements.getTypeMask(node),
                 <ir.Primitive>[indexValue, result]);
           }
-        },
-        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+        });
   }
 
   /// Evaluates a string interpolation and appends each part to [accumulator]
@@ -1707,17 +1723,6 @@
   ir.Primitive buildAbstractClassInstantiationError(ClassElement element);
 
   @override
-  ir.Primitive errorInvalidAssert(
-      ast.Send node,
-      ast.NodeList arguments, _) {
-    if (compiler.enableUserAssertions) {
-      return giveup(node, 'Assert');
-    } else {
-      return irBuilder.buildNullConstant();
-    }
-  }
-
-  @override
   ir.Primitive visitUnresolvedCompound(
       ast.Send node,
       Element element,
@@ -1763,17 +1768,6 @@
   }
 
   @override
-  ir.Primitive errorNonConstantConstructorInvoke(
-      ast.NewExpression node,
-      Element element,
-      DartType type,
-      ast.NodeList arguments,
-      CallStructure callStructure, _) {
-    assert(compiler.compilationFailed);
-    return irBuilder.buildNullConstant();
-  }
-
-  @override
   ir.Primitive visitUnresolvedGet(
       ast.Send node,
       Element element, _) {
@@ -1844,20 +1838,12 @@
   }
 
   @override
-  ir.Primitive errorUndefinedBinaryExpression(
-      ast.Send node,
-      ast.Node left,
-      ast.Operator operator,
-      ast.Node right, _) {
-    assert(compiler.compilationFailed);
-    return irBuilder.buildNullConstant();
+  ir.Primitive bulkHandleNode(ast.Node node, String message, _) {
+    return giveup(node, "Unhandled node: ${message.replaceAll('#', '$node')}");
   }
 
   @override
-  ir.Primitive errorUndefinedUnaryExpression(
-      ast.Send node,
-      ast.Operator operator,
-      ast.Node expression, _) {
+  ir.Primitive bulkHandleError(ast.Send node, ErroneousElement error, _) {
     assert(compiler.compilationFailed);
     return irBuilder.buildNullConstant();
   }
@@ -2422,7 +2408,6 @@
         default:
           compiler.internalError(element, "Unexpected element type $element");
       }
-      new CleanupPass().visit(root);
       return root;
     });
   }
@@ -3357,49 +3342,3 @@
     }
   }
 }
-
-/// Perform simple post-processing on the initial CPS-translated root term.
-///
-/// This pass performs backend-independent post-processing on the translated
-/// term.  It is implemented separately from the optimization passes because
-/// it is required for correctness of the implementation.
-///
-/// It performs the following translations:
-///   - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw]
-///     expression.
-class CleanupPass extends ir.RecursiveVisitor {
-  ir.Expression replacementFor(ir.Expression expression) {
-    if (expression != null && expression is ir.LetPrim) {
-      ir.Primitive primitive = expression.primitive;
-      if (primitive is ir.NonTailThrow) {
-        ir.RemovalVisitor.remove(expression);
-        return new ir.Throw(primitive.value.definition);
-      }
-    }
-    return expression;
-  }
-
-  processFunctionDefinition(ir.FunctionDefinition node) {
-    node.body = replacementFor(node.body);
-  }
-
-  processLetPrim(ir.LetPrim node) {
-    node.body = replacementFor(node.body);
-  }
-
-  processLetCont(ir.LetCont node) {
-    node.body = replacementFor(node.body);
-  }
-
-  processLetHandler(ir.LetHandler node) {
-    node.body = replacementFor(node.body);
-  }
-
-  processLetMutable(ir.LetMutable node) {
-    node.body = replacementFor(node.body);
-  }
-
-  processContinuation(ir.Continuation node) {
-    node.body = replacementFor(node.body);
-  }
-}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
index 0d7c066..88faa4d 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
@@ -32,19 +32,9 @@
   Map<Definition, Set<Reference>> seenReferences =
       <Definition, Set<Reference>>{};
 
-  Map<Definition, Node> bindings = <Definition, Node>{};
+  Set<Definition> inScope = new Set<Definition>();
   Set<Continuation> insideContinuations = new Set<Continuation>();
 
-  doInScope(Iterable<Definition> defs, Node binding, action()) {
-    for (Definition def in defs) {
-      bindings[def] = binding;
-    }
-    action();
-    for (Definition def in defs) {
-      bindings.remove(def);
-    }
-  }
-
   void markAsSeen(Definition def) {
     if (!seenDefinitions.add(def)) {
       error('Redeclared $def', def);
@@ -52,70 +42,92 @@
     seenReferences[def] = new Set<Reference>();
   }
 
-  @override
-  visitLetCont(LetCont node) {
-    // Analyze each continuation separately without the others in scope.
-    for (Continuation continuation in node.continuations) {
-      // We always consider a continuation to be in scope of itself.
-      // The isRecursive flag is checked explicitly to give more useful
-      // error messages.
-      doInScope([continuation], node, () => visit(continuation));
-    }
-    // Analyze the body with all continuations in scope.
-    doInScope(node.continuations, node, () => visit(node.body));
+  void enterScope(Iterable<Definition> definitions) {
+    inScope.addAll(definitions);
+    pushAction(() => inScope.removeAll(definitions));
+  }
+
+  void enterContinuation(Continuation cont) {
+    insideContinuations.add(cont);
+    pushAction(() => insideContinuations.remove(cont));
+  }
+
+  void check(FunctionDefinition node) {
+    topLevelNode = node;
+    visit(node);
+    // Check for broken reference chains. We check this last, so out-of-scope
+    // references are not classified as a broken reference chain.
+    seenDefinitions.forEach(checkReferenceChain);
   }
 
   @override
-  visitContinuation(Continuation node) {
-    markAsSeen(node);
-    if (node.isReturnContinuation) {
-      error('Non-return continuation missing body', node);
-    }
-    node.parameters.forEach(markAsSeen);
-    insideContinuations.add(node);
-    doInScope(node.parameters, node, () => visit(node.body));
-    insideContinuations.remove(node);
+  Expression traverseLetCont(LetCont node) {
+    node.continuations.forEach(markAsSeen);
+    node.continuations.forEach(push);
+
+    // Put all continuations in scope when visiting the body.
+    enterScope(node.continuations);
+
+    return node.body;
   }
 
   @override
-  visitLetPrim(LetPrim node) {
+  Expression traverseLetPrim(LetPrim node) {
     markAsSeen(node.primitive);
+
+    // Process references in the primitive.
     visit(node.primitive);
-    doInScope([node.primitive], node, () => visit(node.body));
+
+    // Put the primitive in scope when visiting the body.
+    enterScope([node.primitive]);
+
+    return node.body;
   }
 
   @override
-  visitLetMutable(LetMutable node) {
+  Expression traverseLetMutable(LetMutable node) {
     markAsSeen(node.variable);
     processReference(node.value);
-    doInScope([node.variable], node, () => visit(node.body));
+    
+    // Put the primitive in scope when visiting the body.
+    enterScope([node.variable]);
+
+    return node.body;
+  }
+
+  @override
+  Expression traverseContinuation(Continuation cont) {
+    if (cont.isReturnContinuation) {
+      error('Non-return continuation missing body', cont);
+    }
+    cont.parameters.forEach(markAsSeen);
+    enterScope(cont.parameters);
+    // Put every continuation in scope at its own body. The isRecursive
+    // flag is checked explicitly using [insideContinuations].
+    enterScope([cont]);
+    enterContinuation(cont);
+    return cont.body;
   }
 
   @override
   visitFunctionDefinition(FunctionDefinition node) {
     if (node.thisParameter != null) {
       markAsSeen(node.thisParameter);
+      enterScope([node.thisParameter]);
     }
     node.parameters.forEach(markAsSeen);
+    enterScope(node.parameters);
     markAsSeen(node.returnContinuation);
+    enterScope([node.returnContinuation]);
     if (!node.returnContinuation.isReturnContinuation) {
       error('Return continuation with a body', node);
     }
-    doInOptionalScope(node.thisParameter, node,
-        () => doInScope(node.parameters, node,
-            () => doInScope([node.returnContinuation], node,
-                () => visit(node.body))));
-  }
-
-  doInOptionalScope(Parameter parameter, Node node, action) {
-    return (parameter == null)
-        ? action()
-        : doInScope([parameter], node, action);
+    visit(node.body);
   }
 
   @override
   processReference(Reference reference) {
-    if (!bindings.containsKey(reference.definition)) {
+    if (!inScope.contains(reference.definition)) {
       error('Referenced out of scope: ${reference.definition}', reference);
     }
     if (!seenReferences[reference.definition].add(reference)) {
@@ -181,13 +193,4 @@
           '$sexpr\n';
   }
 
-  void check(FunctionDefinition node) {
-    topLevelNode = node;
-    visit(node);
-
-    // Check this last, so out-of-scope references are not classified as
-    // a broken reference chain.
-    seenDefinitions.forEach(checkReferenceChain);
-  }
-
 }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 98d9a35..53960b5 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -45,7 +45,7 @@
   Expression plug(Expression expr) => throw 'impossible';
 
   /// The next expression in the basic block.
-  /// 
+  ///
   /// For [InteriorExpression]s this is the body, for [CallExpressions] it is
   /// the body of the continuation, and for [TailExpressions] it is `null`.
   Expression get next;
@@ -66,7 +66,7 @@
 
 /// An expression that creates new bindings and continues evaluation in
 /// a subexpression.
-/// 
+///
 /// The interior expressions are [LetPrim], [LetCont], [LetHandler], and
 /// [LetMutable].
 abstract class InteriorExpression extends Expression implements InteriorNode {
@@ -145,6 +145,10 @@
   /// True if time-of-evaluation is irrelevant for the given primitive,
   /// assuming its inputs are the same values.
   bool get isSafeForReordering;
+
+  /// The source information associated with this primitive.
+  // TODO(johnniwinther): Require source information for all primitives.
+  SourceInformation get sourceInformation => null;
 }
 
 /// Operands to invocations and primitives are always variables.  They point to
@@ -351,7 +355,7 @@
                            this.mask,
                            this.arguments,
                            this.continuation,
-                           [this.sourceInformation]);
+                           this.sourceInformation);
 
   accept(Visitor visitor) => visitor.visitInvokeMethod(this);
 }
@@ -502,8 +506,11 @@
 class ApplyBuiltinOperator extends Primitive {
   BuiltinOperator operator;
   List<Reference<Primitive>> arguments;
+  final SourceInformation sourceInformation;
 
-  ApplyBuiltinOperator(this.operator, List<Primitive> arguments)
+  ApplyBuiltinOperator(this.operator,
+                       List<Primitive> arguments,
+                       this.sourceInformation)
       : this.arguments = _referenceList(arguments);
 
   accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this);
@@ -533,23 +540,6 @@
   accept(Visitor visitor) => visitor.visitRethrow(this);
 }
 
-/// A throw occurring in non-tail position.
-///
-/// The CPS translation of an expression produces a primitive as the value
-/// of the expression.  For convenience in the implementation of the
-/// translation, a [NonTailThrow] is used as that value.  A cleanup pass
-/// removes these and replaces them with [Throw] expressions.
-class NonTailThrow extends Primitive {
-  final Reference<Primitive> value;
-
-  NonTailThrow(Primitive value) : value = new Reference<Primitive>(value);
-
-  accept(Visitor visitor) => visitor.visitNonTailThrow(this);
-
-  bool get isSafeForElimination => false;
-  bool get isSafeForReordering => false;
-}
-
 /// An expression that is known to be unreachable.
 ///
 /// This can be placed as the body of a call continuation, when the caller is
@@ -673,7 +663,7 @@
         this.value = new Reference<Primitive>(value);
 
   accept(Visitor visitor) => visitor.visitSetField(this);
-  
+
   bool get isSafeForElimination => false;
   bool get isSafeForReordering => false;
 }
@@ -850,10 +840,11 @@
 class Interceptor extends Primitive {
   final Reference<Primitive> input;
   final Set<ClassElement> interceptedClasses = new Set<ClassElement>();
+  final SourceInformation sourceInformation;
 
-  Interceptor(Primitive input)
+  Interceptor(Primitive input, this.sourceInformation)
       : this.input = new Reference<Primitive>(input);
-  
+
   accept(Visitor visitor) => visitor.visitInterceptor(this);
 
   bool get isSafeForElimination => true;
@@ -1137,7 +1128,6 @@
   T visitParameter(Parameter node);
   T visitContinuation(Continuation node);
   T visitMutableVariable(MutableVariable node);
-  T visitNonTailThrow(NonTailThrow node);
   T visitGetStatic(GetStatic node);
   T visitInterceptor(Interceptor node);
   T visitCreateInstance(CreateInstance node);
@@ -1160,10 +1150,16 @@
   T visitForeignCode(ForeignCode node);
 }
 
-/// Recursively visits the entire CPS term, and calls abstract `process*`
-/// (i.e. `processLetPrim`) functions in pre-order.
-class RecursiveVisitor implements Visitor {
-  const RecursiveVisitor();
+/// Visits all non-recursive children of a CPS term, i.e. anything
+/// not of type [Expression] or [Continuation].
+/// 
+/// Note that the non-recursive nodes can contain other nodes inside of them,
+/// e.g. [Branch] contains an [IsTrue] which contains a [Reference].
+/// 
+/// The `process*` methods are called in pre-order for every node visited.
+/// These can be overridden without disrupting the visitor traversal.
+class LeafVisitor implements Visitor {
+  const LeafVisitor();
 
   visit(Node node) => node.accept(this);
 
@@ -1175,7 +1171,6 @@
     if (node.thisParameter != null) visit(node.thisParameter);
     node.parameters.forEach(visit);
     visit(node.returnContinuation);
-    visit(node.body);
   }
 
   // Expressions.
@@ -1184,21 +1179,17 @@
   visitLetPrim(LetPrim node) {
     processLetPrim(node);
     visit(node.primitive);
-    visit(node.body);
   }
 
   processLetCont(LetCont node) {}
   visitLetCont(LetCont node) {
     processLetCont(node);
     node.continuations.forEach(visit);
-    visit(node.body);
   }
 
   processLetHandler(LetHandler node) {}
   visitLetHandler(LetHandler node) {
     processLetHandler(node);
-    visit(node.handler);
-    visit(node.body);
   }
 
   processLetMutable(LetMutable node) {}
@@ -1206,7 +1197,6 @@
     processLetMutable(node);
     visit(node.variable);
     processReference(node.value);
-    visit(node.body);
   }
 
   processInvokeStatic(InvokeStatic node) {}
@@ -1339,7 +1329,6 @@
   visitContinuation(Continuation node) {
     processContinuation(node);
     node.parameters.forEach(visitParameter);
-    if (node.body != null) visit(node.body);
   }
 
   processIsTrue(IsTrue node) {}
@@ -1408,12 +1397,6 @@
     node.arguments.forEach(processReference);
   }
 
-  processNonTailThrow(NonTailThrow node) {}
-  visitNonTailThrow(NonTailThrow node) {
-    processNonTailThrow(node);
-    processReference(node.value);
-  }
-
   processCreateInvocationMirror(CreateInvocationMirror node) {}
   visitCreateInvocationMirror(CreateInvocationMirror node) {
     processCreateInvocationMirror(node);
@@ -1462,15 +1445,132 @@
   }
 }
 
+typedef void StackAction();
+
+/// Calls `process*` for all nodes in a tree.
+/// For simple usage, only override the `process*` methods.
+/// 
+/// To avoid deep recursion, this class uses an "action stack" containing
+/// callbacks to be invoked after the processing of some term has finished.
+/// 
+/// To avoid excessive overhead from the action stack, basic blocks of
+/// interior nodes are iterated in a loop without using the action stack.
+/// 
+/// The iteration order can be controlled by overriding the `traverse*`
+/// methods for [LetCont], [LetPrim], [LetMutable], [LetHandler] and
+/// [Continuation].
+/// 
+/// The `traverse*` methods return the expression to visit next, and may
+/// push other subterms onto the stack using [push] or [pushAction] to visit
+/// them later. Actions pushed onto the stack will be executed after the body
+/// has been processed (and the stack actions it pushed have been executed).
+/// 
+/// By default, the `traverse` methods visit all non-recursive subterms, 
+/// push all bound continuations on the stack, and return the body of the term.
+/// 
+/// Subclasses should not override the `visit` methods for the nodes that have
+/// a `traverse` method.
+class RecursiveVisitor extends LeafVisitor {
+  List<StackAction> _stack = <StackAction>[];
+
+  void pushAction(StackAction callback) {
+    _stack.add(callback);
+  }
+
+  void push(Continuation cont) {
+    _stack.add(() {
+      if (cont.isReturnContinuation) {
+        traverseContinuation(cont);
+      } else {
+        _processBlock(traverseContinuation(cont));
+      }
+    });
+  }
+
+  visitFunctionDefinition(FunctionDefinition node) {
+    processFunctionDefinition(node);
+    if (node.thisParameter != null) visit(node.thisParameter);
+    node.parameters.forEach(visit);
+    visit(node.returnContinuation);
+    visit(node.body);
+  }
+
+  visitContinuation(Continuation cont) {
+    if (cont.isReturnContinuation) {
+      traverseContinuation(cont);
+    } else {
+      _trampoline(traverseContinuation(cont));
+    }
+  }
+
+  visitLetPrim(LetPrim node) => _trampoline(node);
+  visitLetCont(LetCont node) => _trampoline(node);
+  visitLetHandler(LetHandler node) => _trampoline(node);
+  visitLetMutable(LetMutable node) => _trampoline(node);
+
+  Expression traverseContinuation(Continuation cont) {
+    processContinuation(cont);
+    cont.parameters.forEach(visitParameter);
+    return cont.body;
+  }
+
+  Expression traverseLetCont(LetCont node) {
+    processLetCont(node);
+    node.continuations.forEach(push);
+    return node.body;
+  }
+
+  Expression traverseLetHandler(LetHandler node) {
+    processLetHandler(node);
+    push(node.handler);
+    return node.body;
+  }
+
+  Expression traverseLetPrim(LetPrim node) {
+    processLetPrim(node);
+    visit(node.primitive);
+    return node.body;
+  }
+
+  Expression traverseLetMutable(LetMutable node) {
+    processLetMutable(node);
+    visit(node.variable);
+    processReference(node.value);
+    return node.body;
+  }
+
+  void _trampoline(Expression node) {
+    int initialHeight = _stack.length;
+    _processBlock(node);
+    while (_stack.length > initialHeight) {
+      StackAction callback = _stack.removeLast();
+      callback();
+    }
+  }
+
+  _processBlock(Expression node) {
+    while (node is InteriorExpression) {
+      if (node is LetCont) {
+        node = traverseLetCont(node);
+      } else if (node is LetHandler) {
+        node = traverseLetHandler(node);
+      } else if (node is LetPrim) {
+        node = traverseLetPrim(node);
+      } else {
+        node = traverseLetMutable(node);
+      }
+    }
+    visit(node);
+  }
+}
+
 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
 class RemovalVisitor extends RecursiveVisitor {
-  const RemovalVisitor();
-
   processReference(Reference reference) {
     reference.unlink();
   }
 
   static void remove(Node node) {
-    (const RemovalVisitor()).visit(node);
+    (new RemovalVisitor()).visit(node);
   }
 }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index c6cdfc5..1a317c4 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -314,11 +314,6 @@
     return '(TypeExpression ${node.dartType} ($args))';
   }
 
-  String visitNonTailThrow(NonTailThrow node) {
-    String value = access(node.value);
-    return '(NonTailThrow $value)';
-  }
-
   String visitCreateInvocationMirror(CreateInvocationMirror node) {
     String selector = node.selector.name;
     String args = node.arguments.map(access).join(' ');
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index a299237..ba67e95 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -339,11 +339,6 @@
         "${node.arguments.map(formatReference).join(', ')}";
   }
 
-  visitNonTailThrow(cps_ir.NonTailThrow node) {
-    String value = formatReference(node.value);
-    return "NonTailThrow($value)";
-  }
-
   visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
     String args = node.arguments.map(formatReference).join(', ');
     return "CreateInvocationMirror(${node.selector.name}, $args)";
@@ -365,8 +360,7 @@
   visitForeignCode(cps_ir.ForeignCode node) {
     String id = names.name(node);
     String arguments = node.arguments.map(formatReference).join(', ');
-    String continuation = node.continuation == null ? ''
-        : ' ${formatReference(node.continuation)}';
+    String continuation = formatReference(node.continuation);
     printStmt(id, "ForeignCode ${node.type} ${node.codeTemplate.source} "
         "$arguments $continuation");
   }
@@ -619,10 +613,6 @@
     unexpectedNode(node);
   }
 
-  visitNonTailThrow(cps_ir.NonTailThrow node) {
-    unexpectedNode(node);
-  }
-
   visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
     unexpectedNode(node);
   }
@@ -661,8 +651,6 @@
 
   @override
   visitForeignCode(cps_ir.ForeignCode node) {
-    if (node.continuation != null) {
-      addEdgeToContinuation(node.continuation);
-    }
+    addEdgeToContinuation(node.continuation);
   }
 }
diff --git a/pkg/compiler/lib/src/cps_ir/let_sinking.dart b/pkg/compiler/lib/src/cps_ir/let_sinking.dart
index c7f2c21..4c4736a 100644
--- a/pkg/compiler/lib/src/cps_ir/let_sinking.dart
+++ b/pkg/compiler/lib/src/cps_ir/let_sinking.dart
@@ -8,29 +8,34 @@
 import 'optimizers.dart';
 
 /// Sinks single-use primitives to the use when this is safe and profitable.
-/// 
+///
 /// To avoid sinking non-constant primitives into loops, this pass performs a
 /// control-flow analysis to determine the effective nesting of loops.
-/// 
-/// In the example below, the value 'p' can be sunk to its use site in the 
+///
+/// In the example below, the value 'p' can be sunk to its use site in the
 /// 'else' branch because that branch is not effectively part of a loop,
 /// despite being lexically nested in a recursive continuation.
-/// 
+///
 ///   let prim p = getInterceptor(<something>)
-///   let rec kont x = 
-///     if (<loop condition>) 
+///   let rec kont x =
+///     if (<loop condition>)
 ///       <loop body>
 ///       InvokeContinuation kont x'
-///     else 
+///     else
 ///       <after loop>
 ///       return p.foo()
-/// 
+///
 class LetSinker extends RecursiveVisitor implements Pass {
   String get passName => 'Let sinking';
 
   LoopHierarchy loopHierarchy;
   List<Continuation> stack = <Continuation>[];
-  Set<LetPrim> sunkNodes = new Set<LetPrim>();
+
+  /// Maps a sinkable primitive to its loop header.
+  Map<Primitive, Continuation> loopHeaderForPrimitive =
+      <Primitive, Continuation>{};
+
+  Continuation currentLoopHeader;
 
   void rewrite(FunctionDefinition node) {
     new ParentVisitor().visit(node);
@@ -38,19 +43,40 @@
     visit(node.body);
   }
 
-  void visitLetPrim(LetPrim node) {
-    // Visit the body, wherein this primitive may be sunk to its use site.
-    visit(node.body);
-
-    if (node.primitive != null) {
-      // The primitive could not be sunk. Sink dependencies to this location.
-      visit(node.primitive);
+  @override
+  Expression traverseLetPrim(LetPrim node) {
+    Primitive prim = node.primitive;
+    if (prim.hasExactlyOneUse && prim.isSafeForReordering) {
+      // This can potentially be sunk. Register the loop header, so when we
+      // find the use site, we can check if they are in the same loop.
+      loopHeaderForPrimitive[prim] = currentLoopHeader;
+      pushAction(() {
+        if (node.primitive != null) {
+          // The primitive could not be sunk. Try to sink dependencies here.
+          visit(node.primitive);
+        } else {
+          // The primitive was sunk. Destroy the old LetPrim.
+          InteriorNode parent = node.parent;
+          parent.body = node.body;
+          node.body.parent = parent;
+        }
+      });
     } else {
-      // The primitive was sunk. Destroy the old LetPrim.
-      InteriorNode parent = node.parent;
-      parent.body = node.body;
-      node.body.parent = parent;
+      visit(node.primitive);
     }
+
+    // Visit the body, wherein this primitive may be sunk to its use site.
+    return node.body;
+  }
+
+  @override
+  Expression traverseContinuation(Continuation cont) {
+    Continuation oldLoopHeader = currentLoopHeader;
+    pushAction(() {
+      currentLoopHeader = oldLoopHeader;
+    });
+    currentLoopHeader = loopHierarchy.getLoopHeader(cont);
+    return cont.body;
   }
 
   void processReference(Reference ref) {
@@ -60,13 +86,12 @@
         definition.hasExactlyOneUse &&
         definition.isSafeForReordering) {
       // Check if use is in the same loop.
-      LetPrim binding = definition.parent;
-      Continuation bindingLoop = loopHierarchy.getLoopHeader(binding);
-      Expression use = getEnclosingExpression(ref.parent);
-      Continuation useLoop = loopHierarchy.getLoopHeader(use);
-      if (bindingLoop == useLoop || definition is Constant) {
+      Continuation bindingLoop = loopHeaderForPrimitive.remove(definition);
+      if (bindingLoop == currentLoopHeader || definition is Constant) {
         // Sink the definition.
 
+        Expression use = getEnclosingExpression(ref.parent);
+        LetPrim binding = definition.parent;
         binding.primitive = null;  // Mark old binding for deletion.
         LetPrim newBinding = new LetPrim(definition);
         definition.parent = newBinding;
@@ -127,20 +152,9 @@
     _processBlock(node.body, null);
   }
 
-  /// Returns the innermost loop which [node] is effectively part of.
-  Continuation getLoopHeader(Expression exp) {
-    Node node = exp.parent;
-    while (node != null && node is! Continuation) {
-      node = node.parent;
-    }
-    if (node is Continuation) {
-      if (node.isRecursive) { 
-        return node;
-      } else {
-        return loopTarget[node];
-      }
-    }
-    return null;
+  /// Returns the innermost loop which [cont] is effectively part of.
+  Continuation getLoopHeader(Continuation cont) {
+    return cont.isRecursive ? cont : loopTarget[cont];
   }
 
   /// Marks the innermost loop as a subloop of the other loop.
diff --git a/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart b/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart
index c561e81..d01c3f5 100644
--- a/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart
+++ b/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart
@@ -26,11 +26,12 @@
   /// its declaration.
   Set<MutableVariable> hasAssignmentInTry = new Set<MutableVariable>();
 
-  void visitLetHandler(LetHandler node) {
+  @override
+  Expression traverseLetHandler(LetHandler node) {
+    push(node.handler);
     ++currentDepth;
-    visit(node.body);
-    --currentDepth;
-    visit(node.handler);
+    pushAction(() => --currentDepth);
+    return node.body;
   }
 
   void processLetMutable(LetMutable node) {
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_join.dart b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
index 92bd51b..2a1a584 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_join.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
@@ -234,7 +234,7 @@
 class AlphaRenamer extends RecursiveVisitor {
   Map<Parameter, Parameter> renaming = <Parameter, Parameter>{};
 
-  visitContinuation(Continuation cont) {
+  processContinuation(Continuation cont) {
     if (cont.isReturnContinuation) return;
 
     List<Parameter> shadowedKeys = <Parameter>[];
@@ -255,16 +255,15 @@
       }
     }
 
-    // Visit the body with the updated environment.
-    visit(cont.body);
-
-    // Restore the original environment.
-    for (int i = 0; i < cont.parameters.length; ++i) {
-      renaming.remove(cont.parameters[i]);
-      if (shadowedValues[i] != null) {
-        renaming[shadowedKeys[i]] = shadowedValues[i];
+    pushAction(() {
+      // Restore the original environment.
+      for (int i = 0; i < cont.parameters.length; ++i) {
+        renaming.remove(cont.parameters[i]);
+        if (shadowedValues[i] != null) {
+          renaming[shadowedKeys[i]] = shadowedValues[i];
+        }
       }
-    }
+    });
   }
 
   processReference(Reference ref) {
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index 0173804..ac1d143 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -14,14 +14,14 @@
 class ShrinkingReducer extends Pass {
   String get passName => 'Shrinking reductions';
 
-  Set<_ReductionTask> _worklist;
+  List<_ReductionTask> _worklist;
 
   static final _DeletedNode _DELETED = new _DeletedNode();
 
   /// Applies shrinking reductions to root, mutating root in the process.
   @override
   void rewrite(FunctionDefinition root) {
-    _worklist = new Set<_ReductionTask>();
+    _worklist = new List<_ReductionTask>();
     _RedexVisitor redexVisitor = new _RedexVisitor(_worklist);
 
     // Set all parent pointers.
@@ -32,8 +32,7 @@
 
     // Process the worklist.
     while (_worklist.isNotEmpty) {
-      _ReductionTask task = _worklist.first;
-      _worklist.remove(task);
+      _ReductionTask task = _worklist.removeLast();
       _processTask(task);
     }
   }
@@ -400,7 +399,7 @@
 
 /// Traverses a term and adds any found redexes to the worklist.
 class _RedexVisitor extends RecursiveVisitor {
-  final Set<_ReductionTask> worklist;
+  final List<_ReductionTask> worklist;
 
   _RedexVisitor(this.worklist);
 
@@ -446,7 +445,7 @@
 /// any corresponding tasks can be skipped.  Nodes are marked so by setting
 /// their parent to the deleted sentinel.
 class _RemovalVisitor extends RecursiveVisitor {
-  final Set<_ReductionTask> worklist;
+  final List<_ReductionTask> worklist;
 
   _RemovalVisitor(this.worklist);
 
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 60e9c4c..5784bba 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -546,7 +546,7 @@
  * Uses the information from a preceding analysis pass in order to perform the
  * actual transformations on the CPS graph.
  */
-class TransformingVisitor extends RecursiveVisitor {
+class TransformingVisitor extends LeafVisitor {
   final TypePropagationVisitor analyzer;
   final Map<Expression, ConstantValue> replacements;
   final ConstantPropagationLattice lattice;
@@ -555,11 +555,12 @@
   JavaScriptBackend get backend => compiler.backend;
   TypeMaskSystem get typeSystem => lattice.typeSystem;
   types.DartTypes get dartTypes => lattice.dartTypes;
-  Set<Node> get reachable => analyzer.reachableNodes;
   Map<Node, AbstractValue> get values => analyzer.values;
 
   final dart2js.InternalErrorFunction internalError;
 
+  final List<Node> stack = <Node>[];
+
   TransformingVisitor(this.compiler,
                       this.lattice,
                       this.analyzer,
@@ -567,9 +568,81 @@
                       this.internalError);
 
   void transform(FunctionDefinition root) {
-    visit(root);
+    push(root.body);
+    while (stack.isNotEmpty) {
+      visit(stack.removeLast());
+    }
   }
 
+  void push(Node node) {
+    assert(node != null);
+    stack.add(node);
+  }
+
+  void pushAll(Iterable<Node> nodes) {
+    nodes.forEach(push);
+  }
+
+  /************************* INTERIOR EXPRESSIONS *************************/
+  //
+  // These return nothing, and must push recursive children on the stack.
+
+  void visitLetCont(LetCont node) {
+    pushAll(node.continuations);
+    push(node.body);
+  }
+
+  void visitLetHandler(LetHandler node) {
+    push(node.handler);
+    push(node.body);
+  }
+
+  void visitLetMutable(LetMutable node) {
+    visit(node.variable);
+    push(node.body);
+  }
+
+  void visitLetPrim(LetPrim node) {
+    AbstractValue value = getValue(node.primitive);
+    if (node.primitive is! Constant && value.isConstant) {
+      // If the value is a known constant, compile it as a constant.
+      Constant newPrim = makeConstantPrimitive(value.constant);
+      newPrim.substituteFor(node.primitive);
+      RemovalVisitor.remove(node.primitive);
+      node.primitive = newPrim;
+      newPrim.parent = node;
+    } else {
+      Primitive newPrim = visit(node.primitive);
+      if (newPrim != null) {
+        newPrim.substituteFor(node.primitive);
+        RemovalVisitor.remove(node.primitive);
+        node.primitive = newPrim;
+        newPrim.parent = node;
+        reanalyze(newPrim);
+      }
+      if (node.primitive.hasNoUses && node.primitive.isSafeForElimination) {
+        // Remove unused primitives before entering the body.
+        // This would also be done by shrinking reductions, but usage analyses
+        // such as isAlwaysBoolified are more precise without the dead uses, so
+        // we prefer to remove them early.
+        RemovalVisitor.remove(node.primitive);
+        node.parent.body = node.body;
+        node.body.parent = node.parent;
+      }
+    }
+    push(node.body);
+  }
+
+  void visitContinuation(Continuation node) {
+    if (node.isReturnContinuation) return;
+    // Process the continuation body.
+    // Note that the continuation body may have changed since the continuation
+    // was put on the stack (e.g. [visitInvokeContinuation] may do this).
+    push(node.body);
+  }
+
+  /************************* TRANSFORMATION HELPERS *************************/
+
   /// Sets parent pointers and computes types for the given subtree.
   void reanalyze(Node node) {
     new ParentVisitor().visit(node);
@@ -623,6 +696,16 @@
     context.body = node;
     node.parent = context;
   }
+  
+  /// Binds [prim] before [node].
+  void insertLetPrim(Expression node, Primitive prim) {
+    InteriorNode parent = node.parent;
+    LetPrim let = new LetPrim(prim);
+    parent.body = let;
+    let.body = node;
+    node.parent = let;
+    let.parent = parent;
+  }
 
   /// Make a constant primitive for [constant] and set its entry in [values].
   Constant makeConstantPrimitive(ConstantValue constant) {
@@ -648,23 +731,7 @@
     return letPrim;
   }
 
-  /// Side-effect free expressions with constant results are be replaced by:
-  ///
-  ///    (LetPrim p = constant (InvokeContinuation k p)).
-  ///
-  /// The new expression will be visited.
-  ///
-  /// Returns true if the node was replaced.
-  bool constifyExpression(CallExpression node) {
-    Continuation continuation = node.continuation.definition;
-    ConstantValue constant = replacements[node];
-    if (constant == null) return false;
-    Constant primitive = makeConstantPrimitive(constant);
-    LetPrim letPrim = makeLetPrimInvoke(primitive, continuation);
-    replaceSubtree(node, letPrim);
-    visitLetPrim(letPrim);
-    return true;
-  }
+  /************************* TAIL EXPRESSIONS *************************/
 
   // A branch can be eliminated and replaced by an invocation if only one of
   // the possible continuations is reachable. Removal often leads to both dead
@@ -684,13 +751,13 @@
     if (boolifiedValue == AbstractBool.True) {
       InvokeContinuation invoke = new InvokeContinuation(trueCont, []);
       replaceSubtree(node, invoke);
-      visitInvokeContinuation(invoke);
+      push(invoke);
       return;
     }
     if (boolifiedValue == AbstractBool.False) {
       InvokeContinuation invoke = new InvokeContinuation(falseCont, []);
       replaceSubtree(node, invoke);
-      visitInvokeContinuation(invoke);
+      push(invoke);
       return;
     }
 
@@ -718,6 +785,36 @@
     }
   }
 
+  void visitInvokeContinuation(InvokeContinuation node) {
+    // Inline the single-use continuations. These are often introduced when
+    // specializing an invocation node. These would also be inlined by a later
+    // pass, but doing it here helps simplify pattern matching code, since the
+    // effective definition of a primitive can then be found without going
+    // through redundant InvokeContinuations.
+    Continuation cont = node.continuation.definition;
+    if (cont.hasExactlyOneUse &&
+        !cont.isReturnContinuation &&
+        !cont.isRecursive &&
+        !node.isEscapingTry) {
+      for (int i = 0; i < node.arguments.length; ++i) {
+        node.arguments[i].definition.useElementAsHint(cont.parameters[i].hint);
+        node.arguments[i].definition.substituteFor(cont.parameters[i]);
+        node.arguments[i].unlink();
+      }
+      node.continuation.unlink();
+      InteriorNode parent = node.parent;
+      Expression body = cont.body;
+      parent.body = body;
+      body.parent = parent;
+      cont.body = new Unreachable();
+      cont.body.parent = cont;
+      push(body);
+    }
+  }
+
+
+  /************************* CALL EXPRESSIONS *************************/
+
   /// Replaces [node] with a more specialized instruction, if possible.
   ///
   /// Returns `true` if the node was replaced.
@@ -727,10 +824,11 @@
                            Primitive left,
                            Primitive right) {
       Primitive prim =
-          new ApplyBuiltinOperator(operator, <Primitive>[left, right]);
+          new ApplyBuiltinOperator(operator, <Primitive>[left, right],
+                                   node.sourceInformation);
       LetPrim let = makeLetPrimInvoke(prim, cont);
       replaceSubtree(node, let);
-      visitLetPrim(let);
+      push(let);
       return true; // So returning early is more convenient.
     }
 
@@ -828,7 +926,7 @@
       GetField get = new GetField(getDartReceiver(node), target);
       LetPrim let = makeLetPrimInvoke(get, cont);
       replaceSubtree(node, let);
-      visitLetPrim(let);
+      push(let);
       return true;
     } else {
       if (target.isFinal) return false;
@@ -840,7 +938,7 @@
                                getDartArgument(node, 0)));
       cps.invokeContinuation(cont);
       replaceSubtree(node, cps.result);
-      visit(cps.result);
+      push(cps.result);
       return true;
     }
   }
@@ -933,7 +1031,7 @@
         CpsFragment cps = new CpsFragment(sourceInfo);
         cps.invokeContinuation(cont, [cps.letPrim(new GetLength(list))]);
         replaceSubtree(node, cps.result);
-        visit(cps.result);
+        push(cps.result);
         return true;
 
       case '[]':
@@ -945,7 +1043,7 @@
         GetIndex get = cps.letPrim(new GetIndex(list, index));
         cps.invokeContinuation(cont, [get]);
         replaceSubtree(node, cps.result);
-        visit(cps.result);
+        push(cps.result);
         return true;
 
       case '[]=':
@@ -961,7 +1059,7 @@
         cont.parameters.clear();
         cps.invokeContinuation(cont, []);
         replaceSubtree(node, cps.result);
-        visit(cps.result);
+        push(cps.result);
         return true;
 
       case 'forEach':
@@ -1014,7 +1112,7 @@
         cps.continueLoop(loop, [addOne]);
 
         replaceSubtree(node, cps.result);
-        visit(cps.result);
+        push(cps.result);
         return true;
 
       case 'iterator':
@@ -1165,9 +1263,7 @@
         insertBefore(iteratorCont.body, cps);
         InvokeContinuation invoke = new InvokeContinuation(iteratorCont, []);
         replaceSubtree(node, invoke);
-        visit(invoke);
-        // TODO(asgerf): A procedure for rewriting mutables into parameters
-        //               might enable further optimizations after this.
+        push(invoke);
         return true;
 
       // TODO(asgerf): Rewrite 'add', 'removeLast', ...
@@ -1242,7 +1338,7 @@
           node.sourceInformation);
       node.receiver.unlink();
       replaceSubtree(node, invoke, unlink: false);
-      visitInvokeStatic(invoke);
+      push(invoke);
       return true;
     }
     CallExpression tearOffInvoke = getCallWithResult(tearOff);
@@ -1300,12 +1396,30 @@
         assert(isPure);
       }
 
-      visitInvokeMethod(invoke);
+      push(invoke);
       return true;
     }
     return false;
   }
 
+  /// Side-effect free expressions with constant results are be replaced by:
+  ///
+  ///    (LetPrim p = constant (InvokeContinuation k p)).
+  ///
+  /// The new expression will be visited.
+  ///
+  /// Returns true if the node was replaced.
+  bool constifyExpression(CallExpression node) {
+    Continuation continuation = node.continuation.definition;
+    ConstantValue constant = replacements[node];
+    if (constant == null) return false;
+    Constant primitive = makeConstantPrimitive(constant);
+    LetPrim letPrim = makeLetPrimInvoke(primitive, continuation);
+    replaceSubtree(node, letPrim);
+    push(letPrim);
+    return true;
+  }
+
   void visitInvokeMethod(InvokeMethod node) {
     if (constifyExpression(node)) return;
     if (specializeOperatorCall(node)) return;
@@ -1315,7 +1429,6 @@
 
     AbstractValue receiver = getValue(node.receiver.definition);
     node.receiverIsNotNull = receiver.isDefinitelyNotNull;
-    super.visitInvokeMethod(node);
   }
 
   void visitTypeCast(TypeCast node) {
@@ -1332,17 +1445,14 @@
         InvokeContinuation invoke =
             new InvokeContinuation(cont, <Primitive>[node.value.definition]);
         replaceSubtree(node, invoke);
-        visitInvokeContinuation(invoke);
+        push(invoke);
         return;
 
       case AbstractBool.False:
         // Cast always fails, remove unreachable continuation body.
-        assert(!reachable.contains(cont));
         replaceSubtree(cont.body, new Unreachable());
         break;
     }
-
-    super.visitTypeCast(node);
   }
 
   /// Specialize calls to internal static methods.
@@ -1361,7 +1471,7 @@
             InvokeContinuation invoke =
                 new InvokeContinuation(cont, <Primitive>[arg(0)]);
             replaceSubtree(node, invoke);
-            visitInvokeContinuation(invoke);
+            push(invoke);
             return true;
           }
           break;
@@ -1380,14 +1490,13 @@
     return value == null ? new AbstractValue.nothing() : value;
   }
 
-  void insertLetPrim(Expression node, Primitive prim) {
-    InteriorNode parent = node.parent;
-    LetPrim let = new LetPrim(prim);
-    parent.body = let;
-    let.body = node;
-    node.parent = let;
-    let.parent = parent;
-  }
+
+  /*************************** PRIMITIVES **************************/
+  //
+  // The visit method for a primitive may optionally return a new
+  // primitive. If non-null, the surrounding LetPrim will substitute it
+  // and bind the new primitive instead.
+  //
 
   void visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
     DartString getString(AbstractValue value) {
@@ -1461,18 +1570,21 @@
         // If value is null or a number, we can skip the typeof test.
         return new ApplyBuiltinOperator(
             BuiltinOperator.IsFloor,
-            <Primitive>[prim, prim]);
+            <Primitive>[prim, prim],
+            node.sourceInformation);
       }
       if (lattice.isDefinitelyNotNonIntegerDouble(value)) {
         // If the value cannot be a non-integer double, but might not be a
         // number at all, we can skip the Math.floor test.
         return new ApplyBuiltinOperator(
             BuiltinOperator.IsNumber,
-            <Primitive>[prim]);
+            <Primitive>[prim],
+            node.sourceInformation);
       }
       return new ApplyBuiltinOperator(
           BuiltinOperator.IsNumberAndFloor,
-          <Primitive>[prim, prim, prim]);
+          <Primitive>[prim, prim, prim],
+          node.sourceInformation);
     }
     return null;
   }
@@ -1485,73 +1597,6 @@
     node.objectIsNotNull = getValue(node.object.definition).isDefinitelyNotNull;
   }
 
-  void visitLetPrim(LetPrim node) {
-    AbstractValue value = getValue(node.primitive);
-    if (node.primitive is! Constant && value.isConstant) {
-      // If the value is a known constant, compile it as a constant.
-      Constant newPrim = makeConstantPrimitive(value.constant);
-      newPrim.substituteFor(node.primitive);
-      RemovalVisitor.remove(node.primitive);
-      node.primitive = newPrim;
-      newPrim.parent = node;
-    } else {
-      Primitive newPrim = visit(node.primitive);
-      if (newPrim != null) {
-        newPrim.substituteFor(node.primitive);
-        RemovalVisitor.remove(node.primitive);
-        node.primitive = newPrim;
-        newPrim.parent = node;
-        reanalyze(newPrim);
-      }
-      if (node.primitive.hasNoUses && node.primitive.isSafeForElimination) {
-        // Remove unused primitives before entering the body.
-        // This would also be done by shrinking reductions, but usage analyses
-        // such as isAlwaysBoolified are more precise without the dead uses, so
-        // we prefer to remove them early.
-        RemovalVisitor.remove(node.primitive);
-        node.parent.body = node.body;
-        node.body.parent = node.parent;
-      }
-    }
-    visit(node.body);
-  }
-
-  void visitLetCont(LetCont node) {
-    // Visit body before continuations to ensure more information is available
-    // about the parameters. In particular, if this is a call continuation, its
-    // invocation should be specialized before the body is processed, because
-    // we specialize definitions before their uses.
-    visit(node.body);
-    node.continuations.forEach(visit);
-  }
-
-  void visitInvokeContinuation(InvokeContinuation node) {
-    // Inline the single-use continuations. These are often introduced when
-    // specializing an invocation node. These would also be inlined by a later
-    // pass, but doing it here helps simplify pattern matching code, since the
-    // effective definition of a primitive can then be found without going
-    // through redundant InvokeContinuations.
-    Continuation cont = node.continuation.definition;
-    if (cont.hasExactlyOneUse &&
-        !cont.isReturnContinuation &&
-        !cont.isRecursive &&
-        !node.isEscapingTry) {
-      for (int i = 0; i < node.arguments.length; ++i) {
-        node.arguments[i].definition.useElementAsHint(cont.parameters[i].hint);
-        node.arguments[i].definition.substituteFor(cont.parameters[i]);
-        node.arguments[i].unlink();
-      }
-      node.continuation.unlink();
-      InteriorNode parent = node.parent;
-      Expression body = cont.body;
-      parent.body = body;
-      body.parent = parent;
-      cont.body = new Unreachable();
-      cont.body.parent = cont;
-      visit(body);
-    }
-  }
-
   void visitInterceptor(Interceptor node) {
     // Filter out intercepted classes that do not match the input type.
     AbstractValue value = getValue(node.input.definition);
@@ -1586,11 +1631,11 @@
   // TODO(jgruber): Storing reachability per-edge instead of per-node would
   // allow for further optimizations.
   final List<Node> nodeWorklist = <Node>[];
-  final Set<Node> reachableNodes = new Set<Node>();
+  final Set<Continuation> reachableContinuations = new Set<Continuation>();
 
   // The definition workset stores all definitions which need to be reprocessed
   // since their lattice value has changed.
-  final Set<Definition> defWorkset = new Set<Definition>();
+  final List<Definition> defWorklist = <Definition>[];
 
   final ConstantPropagationLattice lattice;
   final dart2js.InternalErrorFunction internalError;
@@ -1619,17 +1664,17 @@
                          this.internalError);
 
   void analyze(FunctionDefinition root) {
-    reachableNodes.clear();
+    reachableContinuations.clear();
 
     // Initially, only the root node is reachable.
-    setReachable(root);
+    push(root);
 
     iterateWorklist();
   }
 
   void reanalyzeSubtree(Node node) {
-    new ResetAnalysisInfo(reachableNodes, values).visit(node);
-    setReachable(node);
+    new ResetAnalysisInfo(reachableContinuations, values).visit(node);
+    push(node);
     iterateWorklist();
   }
 
@@ -1639,10 +1684,9 @@
         // Process a new reachable expression.
         Node node = nodeWorklist.removeLast();
         visit(node);
-      } else if (defWorkset.isNotEmpty) {
+      } else if (defWorklist.isNotEmpty) {
         // Process all usages of a changed definition.
-        Definition def = defWorkset.first;
-        defWorkset.remove(def);
+        Definition def = defWorklist.removeLast();
 
         // Visit all uses of this definition. This might add new entries to
         // [nodeWorklist], for example by visiting a newly-constant usage within
@@ -1656,19 +1700,23 @@
     }
   }
 
+  /// Adds [node] to the worklist.
+  void push(Node node) {
+    nodeWorklist.add(node);
+  }
+
   /// If the passed node is not yet reachable, mark it reachable and add it
   /// to the work list.
-  void setReachable(Node node) {
-    if (!reachableNodes.contains(node)) {
-      reachableNodes.add(node);
-      nodeWorklist.add(node);
+  void setReachable(Continuation cont) {
+    if (reachableContinuations.add(cont)) {
+      push(cont);
     }
   }
 
   /// Returns the lattice value corresponding to [node], defaulting to nothing.
   ///
   /// Never returns null.
-  AbstractValue getValue(Node node) {
+  AbstractValue getValue(Definition node) {
     AbstractValue value = values[node];
     return (value == null) ? nothing : value;
   }
@@ -1676,7 +1724,7 @@
   /// Joins the passed lattice [updateValue] to the current value of [node],
   /// and adds it to the definition work set if it has changed and [node] is
   /// a definition.
-  void setValue(Node node, AbstractValue updateValue) {
+  void setValue(Definition node, AbstractValue updateValue) {
     AbstractValue oldValue = getValue(node);
     AbstractValue newValue = lattice.join(oldValue, updateValue);
     if (oldValue == newValue) {
@@ -1687,9 +1735,7 @@
     assert(newValue.kind >= oldValue.kind);
 
     values[node] = newValue;
-    if (node is Definition) {
-      defWorkset.add(node);
-    }
+    defWorklist.add(node);
   }
 
   // -------------------------- Visitor overrides ------------------------------
@@ -1701,21 +1747,21 @@
                nonConstant(typeSystem.getReceiverType(node.element)));
     }
     node.parameters.forEach(visit);
-    setReachable(node.body);
+    push(node.body);
   }
 
   void visitLetPrim(LetPrim node) {
     visit(node.primitive); // No reason to delay visits to primitives.
-    setReachable(node.body);
+    push(node.body);
   }
 
   void visitLetCont(LetCont node) {
     // The continuation is only marked as reachable on use.
-    setReachable(node.body);
+    push(node.body);
   }
 
   void visitLetHandler(LetHandler node) {
-    setReachable(node.body);
+    push(node.body);
     // The handler is assumed to be reachable (we could instead treat it as
     // unreachable unless we find something reachable that might throw in the
     // body --- it's not clear if we want to do that here or in some other
@@ -1732,7 +1778,7 @@
 
   void visitLetMutable(LetMutable node) {
     setValue(node.variable, getValue(node.value.definition));
-    setReachable(node.body);
+    push(node.body);
   }
 
   void visitInvokeStatic(InvokeStatic node) {
@@ -1954,10 +2000,6 @@
   void visitUnreachable(Unreachable node) {
   }
 
-  void visitNonTailThrow(NonTailThrow node) {
-    internalError(null, 'found non-tail throw after they were eliminated');
-  }
-
   void visitBranch(Branch node) {
     IsTrue isTrue = node.condition;
     AbstractValue conditionCell = getValue(isTrue.value.definition);
@@ -2052,10 +2094,7 @@
   }
 
   void visitCreateFunction(CreateFunction node) {
-    setReachable(node.definition);
-    ConstantValue constant =
-        new FunctionConstantValue(node.definition.element);
-    setValue(node, constantValue(constant, typeSystem.functionType));
+    throw 'CreateFunction is not used';
   }
 
   void visitGetMutable(GetMutable node) {
@@ -2102,7 +2141,7 @@
     node.parameters.forEach(visit);
 
     if (node.body != null) {
-      setReachable(node.body);
+      push(node.body);
     }
   }
 
@@ -2131,7 +2170,7 @@
   }
 
   void visitInterceptor(Interceptor node) {
-    setReachable(node.input.definition);
+    push(node.input.definition);
     AbstractValue value = getValue(node.input.definition);
     if (!value.isNothing) {
       setValue(node, nonConstant(typeSystem.nonNullType));
@@ -2294,14 +2333,21 @@
 }
 
 class ResetAnalysisInfo extends RecursiveVisitor {
-  Set<Node> reachableNodes;
+  Set<Continuation> reachableContinuations;
   Map<Definition, AbstractValue> values;
 
-  ResetAnalysisInfo(this.reachableNodes, this.values);
+  ResetAnalysisInfo(this.reachableContinuations, this.values);
 
-  visit(Node node) {
-    reachableNodes.remove(node);
-    if (node is Definition) values.remove(node);
-    node.accept(this);
+  processContinuation(Continuation cont) {
+    reachableContinuations.remove(cont);
+    cont.parameters.forEach(values.remove);
+  }
+
+  processLetPrim(LetPrim node) {
+    values.remove(node.primitive);
+  }
+
+  processLetMutable(LetMutable node) {
+    values.remove(node.variable);
   }
 }
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 5e36769..24a058f 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -503,7 +503,7 @@
 void fail(String message) {
   if (diagnosticHandler != null) {
     diagnosticHandler.report(
-        null, -1, -1, message, api.Diagnostic.ERROR);
+        null, null, -1, -1, message, api.Diagnostic.ERROR);
   } else {
     print('Error: $message');
   }
diff --git a/pkg/compiler/lib/src/dart2jslib.dart b/pkg/compiler/lib/src/dart2jslib.dart
index 14dad6a..e5c924d 100644
--- a/pkg/compiler/lib/src/dart2jslib.dart
+++ b/pkg/compiler/lib/src/dart2jslib.dart
@@ -60,9 +60,11 @@
 import 'tree/tree.dart';
 import 'types/types.dart' as ti;
 import 'universe/universe.dart';
+import 'universe/class_set.dart';
 import 'util/characters.dart' show $_;
 import 'util/uri_extras.dart' as uri_extras show relativize;
 import 'util/util.dart';
+import 'warnings.dart';
 
 export 'helpers/helpers.dart';
 export 'resolution/resolution.dart' show TreeElements, TreeElementMapping;
@@ -76,6 +78,7 @@
     show Spannable,
          CURRENT_ELEMENT_SPANNABLE,
          NO_LOCATION_SPANNABLE;
+export 'warnings.dart';
 
 part 'compiler.dart';
 part 'diagnostic_listener.dart';
@@ -83,5 +86,4 @@
 part 'resolved_visitor.dart';
 part 'script.dart';
 part 'typechecker.dart';
-part 'warnings.dart';
 part 'world.dart';
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index e261ff6..3ae1bae 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -252,6 +252,30 @@
       Set<ConstantValue> constants,
       isMirrorUsage) {
 
+    /// Recursively collects all the dependencies of [type].
+    void collectTypeDependencies(DartType type) {
+      if (type is GenericType) {
+        type.typeArguments.forEach(collectTypeDependencies);
+      }
+      if (type is FunctionType) {
+        for (DartType argumentType in type.parameterTypes) {
+          collectTypeDependencies(argumentType);
+        }
+        for (DartType argumentType in type.optionalParameterTypes) {
+          collectTypeDependencies(argumentType);
+        }
+        for (DartType argumentType in type.namedParameterTypes) {
+          collectTypeDependencies(argumentType);
+        }
+        collectTypeDependencies(type.returnType);
+      } else if (type is TypedefType) {
+        elements.add(type.element);
+        collectTypeDependencies(type.unalias(compiler));
+      } else if (type is InterfaceType) {
+        elements.add(type.element);
+      }
+    }
+
     /// Collects all direct dependencies of [element].
     ///
     /// The collected dependent elements and constants are are added to
@@ -281,22 +305,10 @@
         elements.add(dependency);
       }
 
-      void registerTypeArgumentsAsDependencies(DartType type) {
-        Element dependency = type.element;
-        if (dependency == null || dependency.isErroneous ||
-            dependency.isTypeVariable) {
-          return;
-        }
-        elements.add(dependency);
-        if (type is GenericType) {
-          type.typeArguments.forEach(registerTypeArgumentsAsDependencies);
-        }
+      for (DartType type in treeElements.requiredTypes) {
+        collectTypeDependencies(type);
       }
 
-      treeElements.forEachType((Node node, DartType type) {
-        if (node is NewExpression) registerTypeArgumentsAsDependencies(type);
-      });
-
       treeElements.forEachConstantNode((Node node, _) {
         // Explicitly depend on the backend constants.
         ConstantValue value =
@@ -319,34 +331,11 @@
       }
     }
 
-    collectTypeDependencies(DartType type) {
-      if (type is FunctionType) {
-        for (DartType argumentType in type.parameterTypes) {
-          collectTypeDependencies(argumentType);
-        }
-        for (DartType argumentType in type.optionalParameterTypes) {
-          collectTypeDependencies(argumentType);
-        }
-        for (DartType argumentType in type.namedParameterTypes) {
-          collectTypeDependencies(argumentType);
-        }
-        collectTypeDependencies(type.returnType);
-      } else if (type is TypedefType) {
-        elements.add(type.element);
-        collectTypeDependencies(type.unalias(compiler));
-      } else if (type is InterfaceType) {
-        elements.add(type.element);
-      }
-    }
-
     if (element is FunctionElement &&
         compiler.resolverWorld.closurizedMembers.contains(element)) {
       collectTypeDependencies(element.type);
     }
 
-    // TODO(sigurdm): Also collect types that are used in is checks and for
-    // checked mode.
-
     if (element.isClass) {
       // If we see a class, add everything its live instance members refer
       // to.  Static members are not relevant, unless we are processing
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 2524fb1..3b8f8bc 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -639,9 +639,10 @@
       encoder.startChunkedConversion(
           new StringConversionSink.fromStringSink(buffer));
     sink.add(outJson);
-    compiler.reportInfo(NO_LOCATION_SPANNABLE,
-        const MessageKind(
-            "View the dumped .info.json file at "
-            "https://dart-lang.github.io/dump-info-visualizer"));
+    compiler.reportInfo(
+        NO_LOCATION_SPANNABLE,
+        MessageKind.GENERIC,
+        {'text': "View the dumped .info.json file at "
+                 "https://dart-lang.github.io/dump-info-visualizer"});
   }
 }
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 85d7579..0f96bdb 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -24,6 +24,7 @@
     FunctionType,
     InterfaceType,
     MessageKind,
+    MessageTemplate,
     Script,
     Selector,
     SourceSpan,
@@ -308,7 +309,10 @@
 
   FunctionElement asFunctionElement() => this;
 
-  String get message => '${messageKind.message(messageArguments)}';
+  String get message {
+    return MessageTemplate.TEMPLATES[messageKind]
+        .message(messageArguments).toString();
+  }
 
   String toString() => '<$name: $message>';
 
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 416d7ea..56b88d1 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -172,7 +172,24 @@
   SourceInformation buildLoop(Node node) => buildBegin(node);
 
   @override
-  SourceInformation buildGet(Node node) => buildBegin(node);
+  SourceInformation buildGet(Node node) {
+    Node left = node;
+    Node right = node;
+    Send send = node.asSend();
+    if (send != null) {
+      right = send.selector;
+    }
+    // For a read access like `a.b` the first source locations points to the
+    // left-most part of the access, `a` in the example, and the second source
+    // location points to the 'name' of accessed property, `b` in the
+    // example. The latter is needed when both `a` and `b` are compiled into
+    // JavaScript invocations.
+    return new PositionSourceInformation(
+        new OffsetSourceLocation(
+            sourceFile, left.getBeginToken().charOffset, name),
+        new OffsetSourceLocation(
+            sourceFile, right.getBeginToken().charOffset, name));
+  }
 
   @override
   SourceInformation buildCall(Node receiver, Node call) {
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 09d1ca9..7acf719 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -74,13 +74,13 @@
   /// Generate [SourceInformation] for the loop [node].
   SourceInformation buildLoop(Node node) => null;
 
-  /// Generate [SourceInformation] for the read access in [node].
+  /// Generate [SourceInformation] for a read access like `a.b` where in
+  /// [receiver] points to the left-most part of the access, `a` in the example,
+  /// and [property] points to the 'name' of accessed property, `b` in the
+  /// example.
   SourceInformation buildGet(Node node) => null;
 
-  /// Generate [SourceInformation] for an invocation like `a.b()` where
-  /// [receiver] points to the left-most part of the invocation, `a` in the
-  /// example, and [call] points the 'name' of the call, `b` or `()` depending
-  /// on whether `b` is a method or a field/getter.
+  /// Generate [SourceInformation] for the read access in [node].
   SourceInformation buildCall(Node receiver, Node call) => null;
 
   /// Generate [SourceInformation] for the if statement in [node].
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index 4547fca..68469eb 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -9,6 +9,7 @@
 
 import '../dart2jslib.dart' show
     MessageKind,
+    MessageTemplate,
     SourceSpan;
 import '../elements/elements.dart' show
     AstElement,
@@ -182,10 +183,11 @@
   void checkValidSourceFileLocation(
       SourceLocation location, SourceFile sourceFile, int offset) {
     if (!location.isValid) {
-      throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message(
-          {'offset': offset,
-           'fileName': sourceFile.filename,
-           'length': sourceFile.length});
+      throw MessageTemplate.TEMPLATES[MessageKind.INVALID_SOURCE_FILE_LOCATION]
+          .message(
+              {'offset': offset,
+               'fileName': sourceFile.filename,
+               'length': sourceFile.length});
     }
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index ba39217..91c4765 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -242,10 +242,10 @@
   static const String START_ROOT_ISOLATE = 'startRootIsolate';
 
 
+  String get patchVersion => emitter.patchVersion;
+  
   bool get supportsReflection => emitter.emitter.supportsReflection;
 
-  String get patchVersion => USE_LAZY_EMITTER ? 'lazy' : 'full';
-
   final Annotations annotations;
 
   /// Reference to the internal library to lookup functions to always inline.
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index e0388d2..f305c76 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -645,7 +645,8 @@
     js.Name helperName = glue.getInterceptorName(node.interceptedClasses);
     js.Expression globalHolder = glue.getInterceptorLibrary();
     return js.js('#.#(#)',
-        [globalHolder, helperName, visitExpression(node.input)]);
+        [globalHolder, helperName, visitExpression(node.input)])
+            .withSourceInformation(node.sourceInformation);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index de97137..14cc633 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -62,17 +62,10 @@
     JavaScriptBackend backend = compiler.backend;
     return compiler.withCurrentElement(element, () {
       try {
-        ClassElement cls = element.enclosingClass;
-        String name = element.name;
-        String className = cls == null ? null : cls.name;
-        LibraryElement library = element.library;
-        String libraryName = library == null ? null : library.toString();
         // TODO(karlklose): remove this fallback.
         // Fallback for a few functions that we know require try-finally and
         // switch.
-        if (element.isNative ||
-            element.isPatched ||
-            libraryName == 'origin library(dart:typed_data)') {
+        if (element.isNative) {
           compiler.log('Using SSA compiler for platform element $element');
           return fallbackCompiler.compile(work);
         }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 110d156..01ebde7 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -3,9 +3,9 @@
 import '../../cps_ir/cps_ir_nodes.dart';
 
 import '../../cps_ir/optimizers.dart' show ParentVisitor;
-import '../../constants/expressions.dart';
 import '../../constants/values.dart';
 import '../../elements/elements.dart';
+import '../../io/source_information.dart';
 import '../../js_backend/codegen/glue.dart';
 import '../../dart2jslib.dart' show Selector, World;
 import '../../cps_ir/cps_ir_builder.dart' show ThisParameterLocal;
@@ -82,12 +82,6 @@
     visit(function);
   }
 
-  @override
-  visit(Node node) {
-    Node result = node.accept(this);
-    return result != null ? result : node;
-  }
-
   Constant get trueConstant {
     return new Constant(new TrueConstantValue());
   }
@@ -134,7 +128,8 @@
     Primitive nullPrimitive = nullConstant;
     Primitive test = new ApplyBuiltinOperator(
         BuiltinOperator.Identical,
-          <Primitive>[function.parameters.single, nullPrimitive]);
+          <Primitive>[function.parameters.single, nullPrimitive],
+          function.parameters.single.sourceInformation);
 
     Expression newBody =
         new LetCont.many(<Continuation>[returnFalse, originalBody],
@@ -165,8 +160,8 @@
     Selector selector = new Selector.fromElement(function);
     // TODO(johnniwinther): Come up with an implementation of SourceInformation
     // for calls such as this one that don't appear in the original source.
-    InvokeStatic invoke =
-        new InvokeStatic(function, selector, arguments, continuation, null);
+    InvokeStatic invoke = new InvokeStatic(
+        function, selector, arguments, continuation, null);
     _parentVisitor.processInvokeStatic(invoke);
 
     LetCont letCont = new LetCont(continuation, invoke);
@@ -176,7 +171,11 @@
     letCont.parent = parent;
   }
 
-  processLetHandler(LetHandler node) {
+  @override
+  Expression traverseLetHandler(LetHandler node) {
+    assert(node.handler.parameters.length == 2);
+    Parameter previousExceptionParameter = _exceptionParameter;
+
     // BEFORE: Handlers have two parameters, exception and stack trace.
     // AFTER: Handlers have a single parameter, which is unwrapped to get
     // the exception and stack trace.
@@ -200,18 +199,11 @@
 
     assert(stackTraceParameter.hasNoUses);
     node.handler.parameters.removeLast();
-  }
 
-  @override
-  visitLetHandler(LetHandler node) {
-    assert(node.handler.parameters.length == 2);
-    Parameter previousExceptionParameter = _exceptionParameter;
-    _exceptionParameter = node.handler.parameters.first;
-    processLetHandler(node);
     visit(node.handler);
     _exceptionParameter = previousExceptionParameter;
 
-    visit(node.body);
+    return node.body;
   }
 
   processThrow(Throw node) {
@@ -236,17 +228,19 @@
 
   /// Returns an interceptor for the given value, capable of responding to
   /// [selector].
-  /// 
+  ///
   /// A single getInterceptor call will be created per primitive, bound
   /// immediately after the primitive is bound.
-  /// 
+  ///
   /// The type propagation pass will later narrow the set of interceptors
   /// based on the input type, and the let sinking pass will propagate the
   /// getInterceptor call closer to its use when this is profitable.
-  Interceptor getInterceptorFor(Primitive prim, Selector selector) {
+  Interceptor getInterceptorFor(Primitive prim, Selector selector,
+                                SourceInformation sourceInformation) {
+    assert(prim is! Interceptor);
     Interceptor interceptor = interceptors[prim];
     if (interceptor == null) {
-      interceptor = new Interceptor(prim);
+      interceptor = new Interceptor(prim, sourceInformation);
       interceptors[prim] = interceptor;
       InteriorNode parent = prim.parent;
       insertLetPrim(interceptor, parent.body);
@@ -273,7 +267,8 @@
       //  Change 'receiver.foo()'  to  'this.foo(receiver)'.
       newReceiver = thisParameter;
     } else {
-      newReceiver = getInterceptorFor(receiver, node.selector);
+      newReceiver = getInterceptorFor(
+          receiver, node.selector, node.sourceInformation);
     }
 
     node.arguments.insert(0, node.receiver);
@@ -301,7 +296,8 @@
     Primitive t = trueConstant;
     Primitive i = new ApplyBuiltinOperator(
         BuiltinOperator.Identical,
-        <Primitive>[condition.value.definition, t]);
+        <Primitive>[condition.value.definition, t],
+        condition.value.definition.sourceInformation);
     LetPrim newNode = new LetPrim(t,
         new LetPrim(i,
             new Branch(new IsTrue(i),
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index cdcc609..b069aaf 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -43,7 +43,8 @@
     if (USE_LAZY_EMITTER) {
       emitter = new lazy_js_emitter.Emitter(compiler, namer, nativeEmitter);
     } else if (USE_STARTUP_EMITTER) {
-      emitter = new startup_js_emitter.Emitter(compiler, namer, nativeEmitter);
+      emitter = new startup_js_emitter.Emitter(
+          compiler, namer, nativeEmitter, generateSourceMap);
     } else {
       emitter =
           new full_js_emitter.Emitter(compiler, namer, generateSourceMap, this);
@@ -53,6 +54,10 @@
 
   String get name => 'Code emitter';
 
+  /// Returns the string that is used to find library patches that are
+  /// specialized for the emitter.
+  String get patchVersion => emitter.patchVersion;
+
   /// Returns the closure expression of a static function.
   jsAst.Expression isolateStaticClosureAccess(FunctionElement element) {
     return emitter.isolateStaticClosureAccess(element);
@@ -148,6 +153,10 @@
 }
 
 abstract class Emitter {
+  /// Returns the string that is used to find library patches that are
+  /// specialized for this emitter.
+  String get patchVersion;
+
   /// Uses the [programBuilder] to generate a model of the program, emits
   /// the program, and returns the size of the generated output.
   int emitProgram(ProgramBuilder programBuilder);
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 c12637c..10e27921 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
@@ -193,14 +193,15 @@
   void emitCheckedClassSetters(Class cls, ClassBuilder builder) {
     if (cls.onlyForRti) return;
 
-    for (Field field in cls.fields) {
-      if (field.needsCheckedSetter) {
-        assert(!field.needsUncheckedSetter);
-        compiler.withCurrentElement(field.element, () {
-          generateCheckedSetter(
-              field.element, field.name, field.accessorName, builder);
-        });
-      }
+    for (StubMethod method in cls.checkedSetters) {
+      Element member = method.element;
+      assert(member != null);
+      jsAst.Expression code = method.code;
+      jsAst.Name setterName = method.name;
+      compiler.dumpInfoTask.registerElementAst(member,
+          builder.addProperty(setterName, code));
+      generateReflectionDataForFieldGetterOrSetter(
+          member, setterName, builder, isGetter: false);
     }
   }
 
@@ -376,19 +377,6 @@
                      message: '$previousName != ${memberName}'));
   }
 
-  void generateCheckedSetter(Element member,
-                             jsAst.Name fieldName,
-                             jsAst.Name accessorName,
-                             ClassBuilder builder) {
-    jsAst.Expression code = backend.generatedCode[member];
-    assert(code != null);
-    jsAst.Name setterName = namer.deriveSetterName(accessorName);
-    compiler.dumpInfoTask.registerElementAst(member,
-        builder.addProperty(setterName, code));
-    generateReflectionDataForFieldGetterOrSetter(
-        member, setterName, builder, isGetter: false);
-  }
-
   void emitGetterForCSP(Element member, jsAst.Name fieldName,
                         jsAst.Name accessorName,
                         ClassBuilder builder) {
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
index b0a94ce..ebd7d1a 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
@@ -20,7 +20,7 @@
     bool canBeReflected = method.canBeReflected;
     bool canTearOff = method.needsTearOff;
     jsAst.Name tearOffName = method.tearOffName;
-    bool isClosure = method is InstanceMethod && method.isClosure;
+    bool isClosure = method is InstanceMethod && method.isClosureCallMethod;
     jsAst.Name superAlias = method is InstanceMethod ? method.aliasName : null;
     bool hasSuperAlias = superAlias != null;
     jsAst.Expression memberTypeExpression = method.functionType;
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 02a0ac2..60382c1 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -206,6 +206,9 @@
   }
 
   @override
+  String get patchVersion => "full";
+
+  @override
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
     if (constant.isFunction) return true;    // Already emitted.
     if (constant.isPrimitive) return true;   // Inlined.
@@ -397,6 +400,13 @@
             generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
         return jsAst.js.expressionTemplateFor("$typesAccess[#]");
 
+      case JsBuiltin.createDartClosureFromNameOfStaticFunction:
+        // The global-functions map contains a map from name to tear-off
+        // getters.
+        String functionGettersMap =
+            generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS);
+        return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()");
+
       default:
         compiler.internalError(NO_LOCATION_SPANNABLE,
             "Unhandled Builtin: $builtin");
@@ -838,7 +848,14 @@
           NativeGenerator.generateIsolateAffinityTagInitialization(
               backend,
               generateEmbeddedGlobalAccess,
-              js("convertToFastObject", [])));
+              js("""
+        // On V8, the 'intern' function converts a string to a symbol, which
+        // makes property access much faster.
+        function (s) {
+          var o = {};
+          o[s] = 1;
+          return Object.keys(convertToFastObject(o))[0];
+        }""", [])));
     }
 
     parts..add(js.comment('BEGIN invoke [main].'))
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
index 70431c1..810b678 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
@@ -42,6 +42,9 @@
         _emitter = new ModelEmitter(compiler, namer, nativeEmitter);
 
   @override
+  String get patchVersion => "lazy";
+
+  @override
   int emitProgram(ProgramBuilder programBuilder) {
     Program program = programBuilder.buildProgram();
     return _emitter.emitProgram(program);
@@ -174,6 +177,9 @@
       case JsBuiltin.getType:
         return _emitter.templateForReadType;
 
+      case JsBuiltin.createDartClosureFromNameOfStaticFunction:
+        throw new UnsupportedError('createDartClosureFromNameOfStaticFunction');
+
       default:
         _compiler.internalError(NO_LOCATION_SPANNABLE,
                                 "Unhandled Builtin: $builtin");
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 ee7030e..b97a47e 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
@@ -235,7 +235,7 @@
           NativeGenerator.generateIsolateAffinityTagInitialization(
               backend,
               generateEmbeddedGlobalAccess,
-              // TODO(floitsch): convertToFastObject.
+              // TODO(floitsch): internStringFunction.
               js.js("(function(x) { return x; })", []));
     } else {
       nativeIsolateAffinityTagInitialization = js.js.statement(";");
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index a76c63a..fe83370 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -22,6 +22,10 @@
   final bool hasIsolateSupport;
   /// A map from load id to the list of fragments that need to be loaded.
   final Map<String, List<Fragment>> loadMap;
+  /// A map from names to strings.
+  ///
+  /// This map is needed to support `const Symbol` expressions;
+  final Map<js.Name, String> symbolsMap;
 
   // If this field is not `null` then its value must be emitted in the embedded
   // global `TYPE_TO_INTERCEPTOR_MAP`. The map references constants and classes.
@@ -35,6 +39,7 @@
   Program(this.fragments,
           this.holders,
           this.loadMap,
+          this.symbolsMap,
           this.typeToInterceptorMap,
           this._metadataCollector,
           this.finalizers,
@@ -226,6 +231,7 @@
   final List<Method> methods;
   final List<Field> fields;
   final List<StubMethod> isChecks;
+  final List<StubMethod> checkedSetters;
 
   /// Stub methods for this class that are call stubs for getters.
   final List<StubMethod> callStubs;
@@ -263,6 +269,7 @@
         this.callStubs,
         this.typeVariableReaderStubs,
         this.noSuchMethodStubs,
+        this.checkedSetters,
         this.isChecks,
         this.functionTypeIndex,
         {this.onlyForRti,
@@ -295,6 +302,7 @@
                    List<Field> staticFieldsForReflection,
                    List<StubMethod> callStubs,
                    List<StubMethod> typeVariableReaderStubs,
+                   List<StubMethod> checkedSetters,
                    List<StubMethod> isChecks,
                    js.Expression functionTypeIndex,
                    {bool onlyForRti,
@@ -307,7 +315,9 @@
               callStubs,
               typeVariableReaderStubs,
               const <StubMethod>[],
-              isChecks, functionTypeIndex,
+              checkedSetters,
+              isChecks,
+              functionTypeIndex,
               onlyForRti: onlyForRti,
               isDirectlyInstantiated: isDirectlyInstantiated,
               isNative: false);
@@ -356,6 +366,12 @@
 
   bool get needsInterceptedGetter => getterFlags > 1;
   bool get needsInterceptedSetter => setterFlags > 1;
+
+  bool get needsInterceptedGetterOnReceiver => getterFlags == 2;
+  bool get needsInterceptedSetterOnReceiver => setterFlags == 2;
+
+  bool get needsInterceptedGetterOnThis => getterFlags == 3;
+  bool get needsInterceptedSetterOnThis => setterFlags == 3;
 }
 
 abstract class Method {
@@ -369,7 +385,7 @@
 }
 
 /// A method that corresponds to a method in the original Dart program.
-class DartMethod extends Method {
+abstract class DartMethod extends Method {
   final bool needsTearOff;
   final js.Name tearOffName;
   final List<ParameterStubMethod> parameterStubs;
@@ -407,6 +423,8 @@
            (requiredParameterCount != null &&
             optionalParameterDefaultValues != null));
   }
+
+  bool get isStatic;
 }
 
 class InstanceMethod extends DartMethod {
@@ -415,7 +433,11 @@
   /// ensure that this method is registered on the prototype under both [name]
   /// and [aliasName].
   final js.Name aliasName;
-  final bool isClosure;
+
+  /// True if this is the implicit `call` instance method of an anonymous
+  /// closure. This predicate is false for explicit `call` methods and for
+  /// functions that can be torn off.
+  final bool isClosureCallMethod;
 
 
   InstanceMethod(Element element, js.Name name, js.Expression code,
@@ -428,7 +450,7 @@
                   bool canBeReflected,
                   int requiredParameterCount,
                   /* List | Map */ optionalParameterDefaultValues,
-                  this.isClosure,
+                  this.isClosureCallMethod,
                   js.Expression functionType})
       : super(element, name, code, parameterStubs, callName,
               needsTearOff: needsTearOff,
@@ -438,8 +460,10 @@
               requiredParameterCount: requiredParameterCount,
               optionalParameterDefaultValues: optionalParameterDefaultValues,
               functionType: functionType) {
-    assert(isClosure != null);
+    assert(isClosureCallMethod != null);
   }
+
+  bool get isStatic => false;
 }
 
 /// A method that is generated by the backend and has not direct correspondence
@@ -495,6 +519,8 @@
               requiredParameterCount: requiredParameterCount,
               optionalParameterDefaultValues: optionalParameterDefaultValues,
               functionType: functionType);
+
+  bool get isStatic => true;
 }
 
 class StaticStubMethod extends StubMethod implements StaticMethod {
diff --git a/pkg/compiler/lib/src/js_emitter/native_generator.dart b/pkg/compiler/lib/src/js_emitter/native_generator.dart
index 9a4145c..fd15d8a 100644
--- a/pkg/compiler/lib/src/js_emitter/native_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_generator.dart
@@ -17,7 +17,7 @@
   static jsAst.Statement generateIsolateAffinityTagInitialization(
       JavaScriptBackend backend,
       jsAst.Expression generateEmbeddedGlobalAccess(String global),
-      jsAst.Expression convertToFastObject) {
+      jsAst.Expression internStringFunction) {
     assert(backend.needToInitializeIsolateAffinityTag);
 
     jsAst.Expression getIsolateTagAccess =
@@ -29,13 +29,7 @@
 
     return js.statement('''
       !function() {
-        // On V8, the 'intern' function converts a string to a symbol, which
-        // makes property access much faster.
-        function intern(s) {
-          var o = {};
-          o[s] = 1;
-          return Object.keys(#convertToFastObject(o))[0];
-        }
+        var intern = #internStringFunction;
 
         #getIsolateTag = function(name) {
           return intern("___dart_" + name + #isolateTag);
@@ -63,7 +57,7 @@
       }();
     ''',
     {'initializeDispatchProperty': backend.needToInitializeDispatchProperty,
-     'convertToFastObject': convertToFastObject,
+     'internStringFunction': internStringFunction,
      'getIsolateTag': getIsolateTagAccess,
      'isolateTag': isolateTagAccess,
      'dispatchPropertyName': dispatchPropertyNameAccess});
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 a526b48..1b9b6ef 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
@@ -82,6 +82,13 @@
   /// update field-initializers to point to the ConstantModel.
   final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{};
 
+  /// Mapping from names to strings.
+  ///
+  /// This mapping is used to support `const Symbol` expressions.
+  ///
+  /// This map is filled when building classes.
+  final Map<js.Name, String> _symbolsMap = <js.Name, String>{};
+
   Set<Class> _unneededNativeClasses;
 
   Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
@@ -162,6 +169,7 @@
         fragments,
         holders,
         _buildLoadMap(),
+        _symbolsMap,
         _buildTypeToInterceptorMap(),
         _task.metadataCollector,
         finalizers,
@@ -350,7 +358,7 @@
     js.Name name = namer.className(element);
 
     return new Class(
-        element, name, null, [], instanceFields, [], [], [], [], [], null,
+        element, name, null, [], instanceFields, [], [], [], [], [], [], null,
         isDirectlyInstantiated: true,
         onlyForRti: false,
         isNative: element.isNative);
@@ -394,10 +402,17 @@
         runtimeTypeGenerator.generateTypeVariableReaderStubs(element);
 
     List<StubMethod> noSuchMethodStubs = <StubMethod>[];
+
     if (backend.enabledNoSuchMethod && element == _compiler.objectClass) {
       Map<js.Name, Selector> selectors =
           classStubGenerator.computeSelectorsForNsmHandlers();
       selectors.forEach((js.Name name, Selector selector) {
+        // If the program contains `const Symbol` names we have to retain them.
+        String selectorName = selector.name;
+        if (selector.isSetter) selectorName = "$selectorName=";
+        if (backend.symbolsUsed.contains(selectorName)) {
+          _symbolsMap[name] = selectorName;
+        }
         noSuchMethodStubs
             .add(classStubGenerator.generateStubForNoSuchMethod(name,
                                                                 selector));
@@ -430,6 +445,18 @@
             element,
             storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata);
 
+    List<StubMethod> checkedSetters = <StubMethod>[];
+    for (Field field in instanceFields) {
+      if (field.needsCheckedSetter) {
+        assert(!field.needsUncheckedSetter);
+        Element element = field.element;
+        js.Expression code = backend.generatedCode[element];
+        assert(code != null);
+        js.Name name = namer.deriveSetterName(field.accessorName);
+        checkedSetters.add(_buildStubMethod(name, code, element: element));
+      }
+    }
+
     List<StubMethod> isChecks = <StubMethod>[];
     typeTests.properties.forEach((js.Name name, js.Node code) {
       isChecks.add(_buildStubMethod(name, code));
@@ -454,6 +481,7 @@
                                     staticFieldsForReflection,
                                     callStubs,
                                     typeVariableReaderStubs,
+                                    checkedSetters,
                                     isChecks,
                                     typeTests.functionTypeIndex,
                                     isDirectlyInstantiated: isInstantiated,
@@ -465,6 +493,7 @@
                          callStubs,
                          typeVariableReaderStubs,
                          noSuchMethodStubs,
+                         checkedSetters,
                          isChecks,
                          typeTests.functionTypeIndex,
                          isDirectlyInstantiated: isInstantiated,
@@ -530,7 +559,7 @@
 
     bool canTearOff = false;
     js.Name tearOffName;
-    bool isClosure = false;
+    bool isClosureCallMethod = false;
     bool isNotApplyTarget = !element.isFunction || element.isAccessor;
 
     bool canBeReflected = _methodCanBeReflected(element);
@@ -545,7 +574,7 @@
     } else {
       if (element.enclosingClass.isClosure) {
         canTearOff = false;
-        isClosure = true;
+        isClosureCallMethod = true;
       } else {
         // Careful with operators.
         canTearOff = universe.hasInvokedGetter(element, _compiler.world) ||
@@ -599,7 +628,7 @@
     return new InstanceMethod(element, name, code,
         _generateParameterStubs(element, canTearOff), callName,
         needsTearOff: canTearOff, tearOffName: tearOffName,
-        isClosure: isClosure, aliasName: aliasName,
+        isClosureCallMethod: isClosureCallMethod, aliasName: aliasName,
         canBeApplied: canBeApplied, canBeReflected: canBeReflected,
         requiredParameterCount: requiredParameterCount,
         optionalParameterDefaultValues: optionalParameterDefaultValues,
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/deferred_fragment_hash.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/deferred_fragment_hash.dart
new file mode 100644
index 0000000..4c09dcf
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/deferred_fragment_hash.dart
@@ -0,0 +1,26 @@
+// 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.
+
+part of dart2js.js_emitter.startup_emitter.model_emitter;
+
+class _DeferredFragmentHash extends js.DeferredString {
+  String _hash;
+  final DeferredFragment _fragment;
+
+  _DeferredFragmentHash(this._fragment);
+
+  void setHash(String hash) {
+    assert(_hash == null);
+    _hash = hash;
+  }
+
+  @override
+  String get value {
+    assert(_hash != null);
+    // Note the additional quotes in the returned value.
+    return '"$_hash"';
+  }
+
+  String toString() => "HashCode for ${_fragment} [$_hash]";
+}
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index fb5b823..a3f2a13 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -7,6 +7,7 @@
 import 'package:js_runtime/shared/embedded_names.dart' show
     JsBuiltin,
     METADATA,
+    STATIC_FUNCTION_NAME_TO_CLOSURE,
     TYPES;
 
 import '../program_builder/program_builder.dart' show ProgramBuilder;
@@ -36,10 +37,15 @@
 
   JavaScriptBackend get _backend => _compiler.backend;
 
-  Emitter(Compiler compiler, Namer namer, NativeEmitter nativeEmitter)
+  Emitter(Compiler compiler, Namer namer, NativeEmitter nativeEmitter,
+      bool shouldGenerateSourceMap)
       : this._compiler = compiler,
         this.namer = namer,
-        _emitter = new ModelEmitter(compiler, namer, nativeEmitter);
+        _emitter = new ModelEmitter(
+            compiler, namer, nativeEmitter, shouldGenerateSourceMap);
+
+  @override
+  String get patchVersion => "startup";
 
   @override
   int emitProgram(ProgramBuilder programBuilder) {
@@ -172,6 +178,11 @@
             _emitter.generateEmbeddedGlobalAccessString(TYPES);
         return js.js.expressionTemplateFor("$typesAccess[#]");
 
+      case JsBuiltin.createDartClosureFromNameOfStaticFunction:
+        String functionAccess = _emitter.generateEmbeddedGlobalAccessString(
+            STATIC_FUNCTION_NAME_TO_CLOSURE);
+        return js.js.expressionTemplateFor("$functionAccess(#)");
+
       default:
         _compiler.internalError(NO_LOCATION_SPANNABLE,
             "Unhandled Builtin: $builtin");
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 390ecd6..f0b5a78 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -4,6 +4,27 @@
 
 part of dart2js.js_emitter.startup_emitter.model_emitter;
 
+/// The name of the property that stores the tear-off getter on a static
+/// function.
+///
+/// This property is only used when isolates are used.
+///
+/// When serializing static functions we transmit the
+/// name of the static function, but not the name of the function's getter. We
+/// store the getter-function on the static function itself, which allows us to
+/// find it easily.
+const String tearOffPropertyName = r'$tearOff';
+
+/// The name of the property that stores the list of fields on a constructor.
+///
+/// This property is only used when isolates are used.
+///
+/// When serializing objects we extract all fields from any given object.
+/// We extract the names of all fields from a fresh empty object. This list
+/// is cached on the constructor in this property to to avoid too many
+/// allocations.
+const String cachedClassFieldNames = r'$cachedFieldNames';
+
 /// The fast startup emitter's goal is to minimize the amount of work that the
 /// JavaScript engine has to do before it can start running user code.
 ///
@@ -47,17 +68,59 @@
   }
 }
 
+var supportsDirectProtoAccess = (function () {
+  var cls = function () {};
+  cls.prototype = {'p': {}};
+  var object = new cls();
+  return object.__proto__ &&
+         object.__proto__.p === cls.prototype.p;
+})();
+
+var functionsHaveName = (function() {
+  function t() {};
+  return (typeof t.name == 'string')
+})();
+
+var isChrome = (typeof window != 'undefined') &&
+    (typeof window.chrome != 'undefined');
+
+// Sets the name property of functions, if the JS engine doesn't set the name
+// itself.
+// As of 2015 only IE doesn't set the name.
+function setFunctionNamesIfNecessary(holders) {
+  if (functionsHaveName) return;
+  for (var i = 0; i < holders.length; i++) {
+    var holder = holders[i];
+    var keys = Object.keys(holder);
+    for (var j = 0; j < keys.length; j++) {
+      var key = keys[j];
+      var f = holder[key];
+      if (typeof f == 'function') f.name = key;
+    }
+  }
+}
+
 // Makes [cls] inherit from [sup].
 // On Chrome, Firefox and recent IEs this happens by updating the internal
 // proto-property of the classes 'prototype' field.
 // Older IEs use `Object.create` and copy over the properties.
 function inherit(cls, sup) {
-  // TODO(floitsch): IE doesn't support changing the __proto__ property. There,
-  // we need to copy the properties instead.
   cls.#typeNameProperty = cls.name;  // Needed for RTI.
   cls.prototype.constructor = cls;
   cls.prototype[#operatorIsPrefix + cls.name] = cls;
-  cls.prototype.__proto__ = sup.prototype;
+
+  // The superclass is only null for the Dart Object.
+  if (sup != null) {
+    if (supportsDirectProtoAccess) {
+      // Firefox doesn't like to update the prototypes, but when setting up
+      // the hierarchy chain it's ok.
+      cls.prototype.__proto__ = sup.prototype;
+      return;
+    }
+    var clsPrototype = Object.create(sup.prototype);
+    copyProperties(cls.prototype, clsPrototype);
+    cls.prototype = clsPrototype;
+  }
 }
 
 // Mixes in the properties of [mixin] into [cls].
@@ -71,14 +134,19 @@
 // getter ([getterName]) to access the field. If the field wasn't set before
 // the first access, it is initialized with the [initializer].
 function lazy(holder, name, getterName, initializer) {
-  holder[name] = null;
+  var uninitializedSentinel = holder;
+  holder[name] = uninitializedSentinel;
   holder[getterName] = function() {
     holder[getterName] = function() { #cyclicThrow(name) };
     var result;
     var sentinelInProgress = initializer;
     try {
-      result = holder[name] = sentinelInProgress;
-      result = holder[name] = initializer();
+      if (holder[name] === uninitializedSentinel) {
+        result = holder[name] = sentinelInProgress;
+        result = holder[name] = initializer();
+      } else {
+        result = holder[name];
+      }
     } finally {
       // Use try-finally, not try-catch/throw as it destroys the stack
       // trace.
@@ -108,7 +176,74 @@
   return list;
 }
 
-// TODO(floitsch): provide code for tear-offs.
+function convertToFastObject(properties) {
+  // Create an instance that uses 'properties' as prototype. This should
+  // make 'properties' a fast object.
+  function t() {};
+  t.prototype = properties;
+  new t();
+  return properties;
+}
+
+// This variable is used by the tearOffCode to guarantee unique functions per
+// tear-offs.
+var functionCounter = 0;
+#tearOffCode;
+
+// Each deferred hunk comes with its own types which are added to the end
+// of the types-array.
+// The `funTypes` passed to the `installTearOff` function below is relative to
+// the hunk the function comes from. The `typesOffset` variable encodes the
+// offset at which the new types will be added.
+var typesOffset = 0;
+
+// Adapts the stored data, so it's suitable for a tearOff call.
+//
+// Stores the tear-off getter-function in the [container]'s [getterName]
+// property.
+//
+// The [container] is either a class (that is, its prototype), or the holder for
+// static functions.
+//
+// The argument [funsOrNames] is an array of strings or functions. If it is a
+// name, then the function should be fetched from the container. The first
+// entry in that array *must* be a string.
+//
+// TODO(floitsch): Change tearOffCode to accept the data directly, or create a
+// different tearOffCode?
+function installTearOff(
+    container, getterName, isStatic, isIntercepted, requiredParameterCount,
+    optionalParameterDefaultValues, callNames, funsOrNames, funType) {
+  // A function can have several stubs (for example to fill in optional
+  // arguments). We collect these functions in the `funs` array.
+  var funs = [];
+  for (var i = 0; i < funsOrNames.length; i++) {
+    var fun = funsOrNames[i];
+    if ((typeof fun) == 'string') fun = container[fun];
+    fun.#callName = callNames[i];
+    funs.push(fun);
+  }
+
+  // The main function to which all stubs redirect.
+  var fun = funs[0];
+
+  fun[#argumentCount] = requiredParameterCount;
+  fun[#defaultArgumentValues] = optionalParameterDefaultValues;
+  var reflectionInfo = funType;
+  if (typeof reflectionInfo == "number") {
+    // The reflectionInfo can either be a function, or a pointer into the types
+    // table. If it points into the types-table we need to update the index,
+    // in case the tear-off is part of a deferred hunk.
+    reflectionInfo = reflectionInfo + typesOffset;
+  }
+  var name = funsOrNames[0];
+  var getterFunction =
+      tearOff(funs, reflectionInfo, isStatic, name, isIntercepted);
+  container[getterName] = getterFunction;
+  if (isStatic) {
+    fun.$tearOffPropertyName = getterFunction;
+  }
+}
 
 // Instead of setting the interceptor tags directly we use this update
 // function. This makes it easier for deferred fragments to contribute to the
@@ -137,32 +272,63 @@
 // Updates the types embedded global.
 function updateTypes(newTypes) {
   var types = #embeddedTypes;
+  // This relies on the fact that types are added *after* the tear-offs have
+  // been installed. The tear-off function uses the types-length to figure
+  // out at which offset its types are located. If the types were added earlier
+  // the offset would be wrong.
   types.push.apply(types, newTypes);
 }
 
 // Updates the given holder with the properties of the [newHolder].
 // This function is used when a deferred fragment is initialized.
 function updateHolder(holder, newHolder) {
-  // TODO(floitsch): updating the prototype (instead of copying) is
-  // *horribly* inefficient in Firefox. There we should just copy the
-  // properties.
-  var oldPrototype = holder.__proto__;
-  newHolder.__proto__ = oldPrototype;
-  holder.__proto__ = newHolder;
+  // Firefox doesn't like when important objects have their prototype chain
+  // updated. We therefore do this only on V8.
+  if (isChrome) {
+    var oldPrototype = holder.__proto__;
+    newHolder.__proto__ = oldPrototype;
+    holder.__proto__ = newHolder;
+  } else {
+    copyProperties(newHolder, holder);
+  }
   return holder;
 }
 
 // Every deferred hunk (i.e. fragment) is a function that we can invoke to
 // initialize it. At this moment it contributes its data to the main hunk.
 function initializeDeferredHunk(hunk) {
+  // Update the typesOffset for the next deferred library.
+  typesOffset = #embeddedTypes.length;
+
   // TODO(floitsch): extend natives.
-  hunk(derive, mixin, lazy, makeConstList, installTearOff,
-       updateHolder, updateTypes, updateInterceptorsByTag, updateLeafTags,
-       #embeddedGlobalsObject, #holdersList, #currentIsolate);
+  hunk(inherit, mixin, lazy, makeConstList, convertToFastObject, installTearOff,
+       setFunctionNamesIfNecessary, updateHolder, updateTypes,
+       setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
+       #embeddedGlobalsObject, #holdersList, #staticState);
+}
+
+// Returns the global with the given [name].
+function getGlobalFromName(name) {
+  // TODO(floitsch): we are running through all holders. Since negative
+  // lookups are expensive we might need to improve this.
+  // Relies on the fact that all names are unique across all holders.
+  for (var i = 0; i < holders.length; i++) {
+    // The constant holder reuses the same names. Therefore we must skip it.
+    if (holders[i] == #constantHolderReference) continue;
+    // Relies on the fact that all variables are unique.
+    if (holders[i][name]) return holders[i][name];
+  }
 }
 
 // Creates the holders.
 #holders;
+
+// If the name is not set on the functions, do it now.
+setFunctionNamesIfNecessary(#holdersList);
+
+// TODO(floitsch): we should build this object as a literal.
+var #staticStateDeclaration = {};
+
 // Sets the prototypes of classes.
 #prototypes;
 // Sets aliases of methods (on the prototypes of classes).
@@ -172,13 +338,6 @@
 // Builds the inheritance structure.
 #inheritance;
 
-// Emits the embedded globals.
-#embeddedGlobals;
-
-// Sets up the native support.
-// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
-#nativeSupport;
-
 // Instantiates all constants.
 #constants;
 // Initializes the static non-final fields (with their constant values).
@@ -186,6 +345,13 @@
 // Creates lazy getters for statics that must run initializers on first access.
 #lazyStatics;
 
+// Emits the embedded globals.
+#embeddedGlobals;
+
+// Sets up the native support.
+// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
+#nativeSupport;
+
 // Invokes main (making sure that it records the 'current-script' value).
 #invokeMain;
 })();
@@ -197,15 +363,17 @@
 /// For example, once the holders have been created, they are included into
 /// the main holders.
 const String deferredBoilerplate = '''
-{
-#deferredInitializers.current =
-function(derive, mixin, lazy, makeConstList, installTearOff,
-          updateHolder, updateTypes,
-          setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
-          #embeddedGlobalsObject, holdersList, #currentIsolate) {
+function(inherit, mixin, lazy, makeConstList, convertToFastObject,
+         installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes,
+         setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
+         #embeddedGlobalsObject, holdersList, #staticState) {
 
 // Builds the holders. They only contain the data for new holders.
 #holders;
+
+// If the name is not set on the functions, do it now.
+setFunctionNamesIfNecessary(#deferredHoldersList);
+
 // Updates the holders of the main-fragment. Uses the provided holdersList to
 // access the main holders.
 // The local holders are replaced by the combined holders. This is necessary
@@ -220,11 +388,6 @@
 // Builds the inheritance structure.
 #inheritance;
 
-updateTypes(#types);
-
-// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
-#nativeSupport;
-
 // Instantiates all constants of this deferred fragment.
 // Note that the constant-holder has been updated earlier and storing the
 // constant values in the constant-holder makes them available globally.
@@ -233,10 +396,11 @@
 #staticNonFinalFields;
 // Creates lazy getters for statics that must run initializers on first access.
 #lazyStatics;
-};
-// TODO(floitsch): this last line should be outside the AST, since it
-// requires to know the hash of the part of the code above this comment.
-#deferredInitializers[#hash] = #deferredInitializers.current;
+
+updateTypes(#types);
+
+// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
+#nativeSupport;
 }''';
 
 /**
@@ -263,14 +427,880 @@
   js.Expression generateConstantReference(ConstantValue value) =>
       modelEmitter.generateConstantReference(value);
 
-  js.Statement emitMainFragment(Program program) {
-    MainFragment fragment = program.fragments.first;
-    throw new UnimplementedError('emitMain');
+  js.Expression classReference(Class cls) {
+    return js.js('#.#', [cls.holder.name, cls.name]);
   }
 
-  js.Statement emitDeferredFragment(DeferredFragment fragment,
-                                    js.Expression deferredTypes,
-                                    List<Holder> holders) {
-    throw new UnimplementedError('emitDeferred');
+  js.Statement emitMainFragment(
+      Program program,
+      Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
+    MainFragment fragment = program.fragments.first;
+
+    Iterable<Holder> nonStaticStateHolders = program.holders
+        .where((Holder holder) => !holder.isStaticStateHolder);
+
+    return js.js.statement(mainBoilerplate,
+        {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
+         'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
+         'cyclicThrow': backend.emitter.staticFunctionAccess(
+                 backend.getCyclicThrowHelper()),
+         'operatorIsPrefix': js.string(namer.operatorIsPrefix),
+         'tearOffCode': new js.Block(buildTearOffCode(backend)),
+         'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
+         'embeddedInterceptorTags':
+             generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
+         'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
+         'embeddedGlobalsObject': js.js("init"),
+         'holdersList': new js.ArrayInitializer(nonStaticStateHolders
+             .map((holder) => js.js("#", holder.name))
+             .toList(growable: false)),
+         'staticStateDeclaration': new js.VariableDeclaration(
+             namer.staticStateHolder, allowRename: false),
+         'staticState': js.js('#', namer.staticStateHolder),
+         'constantHolderReference': buildConstantHolderReference(program),
+         'holders': emitHolders(program.holders, fragment),
+         'callName': js.string(namer.callNameField),
+         'argumentCount': js.string(namer.requiredParameterField),
+         'defaultArgumentValues': js.string(namer.defaultValuesField),
+         'prototypes': emitPrototypes(fragment),
+         'inheritance': emitInheritance(fragment),
+         'aliases': emitInstanceMethodAliases(fragment),
+         'tearOffs': emitInstallTearOffs(fragment),
+         'constants': emitConstants(fragment),
+         'staticNonFinalFields': emitStaticNonFinalFields(fragment),
+         'lazyStatics': emitLazilyInitializedStatics(fragment),
+         'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes),
+         'nativeSupport': program.needsNativeSupport
+              ? emitNativeSupport(fragment)
+              : new js.EmptyStatement(),
+         'invokeMain': fragment.invokeMain,
+         });
   }
-}
\ No newline at end of file
+
+  js.Expression emitDeferredFragment(DeferredFragment fragment,
+                                     js.Expression deferredTypes,
+                                     List<Holder> holders) {
+    List<Holder> nonStaticStateHolders = holders
+        .where((Holder holder) => !holder.isStaticStateHolder)
+        .toList(growable: false);
+
+    List<js.Statement> updateHolderAssignments = <js.Statement>[];
+    for (int i = 0; i < nonStaticStateHolders.length; i++) {
+      Holder holder = nonStaticStateHolders[i];
+      updateHolderAssignments.add(js.js.statement(
+          '#holder = updateHolder(holdersList[#index], #holder)',
+          {'index': js.number(i),
+           'holder': new js.VariableUse(holder.name)}));
+    }
+
+    // TODO(floitsch): don't just reference 'init'.
+    return js.js(deferredBoilerplate,
+    {'embeddedGlobalsObject': new js.Parameter('init'),
+     'staticState': new js.Parameter(namer.staticStateHolder),
+     'holders': emitHolders(holders, fragment),
+     'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders
+         .map((holder) => js.js("#", holder.name))
+         .toList(growable: false)),
+     'updateHolders': new js.Block(updateHolderAssignments),
+     'prototypes': emitPrototypes(fragment),
+     'inheritance': emitInheritance(fragment),
+     'aliases': emitInstanceMethodAliases(fragment),
+     'tearOffs': emitInstallTearOffs(fragment),
+     'constants': emitConstants(fragment),
+     'staticNonFinalFields': emitStaticNonFinalFields(fragment),
+     'lazyStatics': emitLazilyInitializedStatics(fragment),
+     'types': deferredTypes,
+     // TODO(floitsch): only call emitNativeSupport if we need native.
+     'nativeSupport': emitNativeSupport(fragment),
+    });
+  }
+
+  js.Statement emitDeferredInitializerGlobal(Map loadMap) {
+    if (loadMap.isEmpty) return new js.Block.empty();
+
+    return js.js.statement("""
+    if (typeof(${ModelEmitter.deferredInitializersGlobal}) === 'undefined')
+      var ${ModelEmitter.deferredInitializersGlobal} = Object.create(null);""");
+  }
+
+  /// Emits all holders, except for the static-state holder.
+  ///
+  /// The emitted holders contain classes (only the constructors) and all
+  /// static functions.
+  js.Statement emitHolders(List<Holder> holders, Fragment fragment) {
+    // Skip the static-state holder in this function.
+    holders = holders
+        .where((Holder holder) => !holder.isStaticStateHolder)
+        .toList(growable: false);
+
+    Map<Holder, Map<js.Name, js.Expression>> holderCode =
+        <Holder, Map<js.Name, js.Expression>>{};
+
+    for (Holder holder in holders) {
+      holderCode[holder] = <js.Name, js.Expression>{};
+    }
+
+    for (Library library in fragment.libraries) {
+      for (StaticMethod method in library.statics) {
+        assert(!method.holder.isStaticStateHolder);
+        holderCode[method.holder].addAll(emitStaticMethod(method));
+      }
+      for (Class cls in library.classes) {
+        assert(!cls.holder.isStaticStateHolder);
+        holderCode[cls.holder][cls.name] = emitConstructor(cls);
+      }
+    }
+
+    js.VariableInitialization emitHolderInitialization(Holder holder) {
+      List<js.Property> properties = <js.Property>[];
+      holderCode[holder].forEach((js.Name key, js.Expression value) {
+        properties.add(new js.Property(js.quoteName(key), value));
+      });
+
+      return new js.VariableInitialization(
+          new js.VariableDeclaration(holder.name, allowRename: false),
+          new js.ObjectInitializer(properties));
+    }
+
+    // The generated code looks like this:
+    //
+    //    {
+    //      var H = {...}, ..., G = {...};
+    //      var holders = [ H, ..., G ];
+    //    }
+
+    List<js.Statement> statements = [
+      new js.ExpressionStatement(
+          new js.VariableDeclarationList(holders
+              .map(emitHolderInitialization)
+              .toList())),
+      js.js.statement('var holders = #', new js.ArrayInitializer(
+          holders
+              .map((holder) => new js.VariableUse(holder.name))
+              .toList(growable: false)))];
+    return new js.Block(statements);
+  }
+
+  /// Returns a reference to the constant holder, or the JS-literal `null`.
+  js.Expression buildConstantHolderReference(Program program) {
+    Holder constantHolder = program.holders
+        .firstWhere((Holder holder) => holder.isConstantsHolder,
+                    orElse: () => null);
+    if (constantHolder == null) return new js.LiteralNull();
+    return new js.VariableUse(constantHolder.name);
+  }
+
+  /// Emits the given [method].
+  ///
+  /// A Dart method might result in several JavaScript functions, if it
+  /// requires stubs. The returned map contains the original method and all
+  /// the stubs it needs.
+  Map<js.Name, js.Expression> emitStaticMethod(StaticMethod method) {
+    Map<js.Name, js.Expression> jsMethods = <js.Name, js.Expression>{};
+
+    // We don't need to install stub-methods. They can only be used when there
+    // are tear-offs, in which case they are emitted there.
+    assert(() {
+      if (method is StaticDartMethod) {
+        return method.needsTearOff || method.parameterStubs.isEmpty;
+      }
+      return true;
+    });
+    jsMethods[method.name] = method.code;
+
+    return jsMethods;
+  }
+
+  /// Emits a constructor for the given class [cls].
+  ///
+  /// The constructor is statically built.
+  js.Expression emitConstructor(Class cls) {
+    List<js.Name> fieldNames = const <js.Name>[];
+
+    // If the class is not directly instantiated we only need it for inheritance
+    // or RTI. In either case we don't need its fields.
+    if (cls.isDirectlyInstantiated && !cls.isNative) {
+      fieldNames = cls.fields.map((Field field) => field.name).toList();
+    }
+    js.Name name = cls.name;
+
+    Iterable<js.Name> assignments = fieldNames.map((js.Name field) {
+      return js.js("this.#field = #field", {"field": field});
+    });
+
+    return js.js('function #(#) { # }', [name, fieldNames, assignments]);
+  }
+
+  /// Emits the prototype-section of the fragment.
+  ///
+  /// This section updates the prototype-property of all constructors in the
+  /// global holders.
+  js.Statement emitPrototypes(Fragment fragment) {
+    List<js.Statement> assignments = fragment.libraries
+        .expand((Library library) => library.classes)
+        .map((Class cls) => js.js.statement(
+            '#.prototype = #;',
+            [classReference(cls), emitPrototype(cls)]))
+        .toList(growable: false);
+
+    return new js.Block(assignments);
+  }
+
+  /// Emits the prototype of the given class [cls].
+  ///
+  /// The prototype is generated as object literal. Inheritance is ignored.
+  ///
+  /// The prototype also includes the `is-property` that every class must have.
+  // TODO(floitsch): we could avoid that property if we knew that it wasn't
+  //    needed.
+  js.Expression emitPrototype(Class cls) {
+    Iterable<Method> methods = cls.methods;
+    Iterable<Method> checkedSetters = cls.checkedSetters;
+    Iterable<Method> isChecks = cls.isChecks;
+    Iterable<Method> callStubs = cls.callStubs;
+    Iterable<Method> typeVariableReaderStubs = cls.typeVariableReaderStubs;
+    Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
+    Iterable<Method> gettersSetters = generateGettersSetters(cls);
+    Iterable<Method> allMethods =
+        [methods, checkedSetters, isChecks, callStubs, typeVariableReaderStubs,
+         noSuchMethodStubs, gettersSetters].expand((x) => x);
+
+    List<js.Property> properties = <js.Property>[];
+
+    if (cls.superclass == null) {
+      properties.add(new js.Property(js.string("constructor"),
+      classReference(cls)));
+      properties.add(new js.Property(namer.operatorIs(cls.element),
+      js.number(1)));
+    }
+
+    allMethods.forEach((Method method) {
+      emitInstanceMethod(method)
+          .forEach((js.Expression name, js.Expression code) {
+        properties.add(new js.Property(name, code));
+      });
+    });
+
+    return new js.ObjectInitializer(properties);
+  }
+
+  /// Generates a getter for the given [field].
+  Method generateGetter(Field field) {
+    assert(field.needsGetter);
+
+    String template;
+    if (field.needsInterceptedGetterOnReceiver) {
+      template = "function(receiver) { return receiver[#]; }";
+    } else if (field.needsInterceptedGetterOnThis) {
+      template = "function(receiver) { return this[#]; }";
+    } else {
+      assert(!field.needsInterceptedGetter);
+      template = "function() { return this[#]; }";
+    }
+    js.Expression fieldName = js.quoteName(field.name);
+    js.Expression code = js.js(template, fieldName);
+    js.Name getterName = namer.deriveGetterName(field.accessorName);
+    return new StubMethod(getterName, code);
+  }
+
+  /// Generates a setter for the given [field].
+  Method generateSetter(Field field) {
+    assert(field.needsUncheckedSetter);
+
+    String template;
+    if (field.needsInterceptedSetterOnReceiver) {
+      template = "function(receiver, val) { return receiver[#] = val; }";
+    } else if (field.needsInterceptedSetterOnThis) {
+      template = "function(receiver, val) { return this[#] = val; }";
+    } else {
+      assert(!field.needsInterceptedSetter);
+      template = "function(val) { return this[#] = val; }";
+    }
+
+    js.Expression fieldName = js.quoteName(field.name);
+    js.Expression code = js.js(template, fieldName);
+    js.Name setterName = namer.deriveSetterName(field.accessorName);
+    return new StubMethod(setterName, code);
+  }
+
+  /// Generates all getters and setters the given class [cls] needs.
+  Iterable<Method> generateGettersSetters(Class cls) {
+    Iterable<Method> getters = cls.fields
+        .where((Field field) => field.needsGetter)
+        .map(generateGetter);
+
+    Iterable<Method> setters = cls.fields
+        .where((Field field) => field.needsUncheckedSetter)
+        .map(generateSetter);
+
+    return [getters, setters].expand((x) => x);
+  }
+
+  /// Emits the given instance [method].
+  ///
+  /// The given method may be a stub-method (for example for is-checks).
+  ///
+  /// If it is a Dart-method, all necessary stub-methods are emitted, too. In
+  /// that case the returned map contains more than just one entry.
+  ///
+  /// If the method is a closure call-method, also returns the necessary
+  /// properties in case the closure can be applied.
+  Map<js.Expression, js.Expression> emitInstanceMethod(Method method) {
+    var properties = <js.Expression, js.Expression>{};
+
+    properties[method.name] = method.code;
+    if (method is InstanceMethod) {
+      for (ParameterStubMethod stubMethod in method.parameterStubs) {
+        properties[stubMethod.name] = stubMethod.code;
+      }
+
+      if (method.isClosureCallMethod && method.canBeApplied) {
+        properties[js.string(namer.callCatchAllName)] =
+            js.quoteName(method.name);
+        properties[js.string(namer.requiredParameterField)] =
+            js.number(method.requiredParameterCount);
+        properties[js.string(namer.defaultValuesField)] =
+             _encodeOptionalParameterDefaultValues(method);
+      }
+    }
+
+    return properties;
+  }
+
+  /// Emits the inheritance block of the fragment.
+  ///
+  /// In this section prototype chains are updated and mixin functions are
+  /// copied.
+  js.Statement emitInheritance(Fragment fragment) {
+    List<js.Expression> inheritCalls = <js.Expression>[];
+    List<js.Expression> mixinCalls = <js.Expression>[];
+
+    for (Library library in fragment.libraries) {
+      for (Class cls in library.classes) {
+        js.Expression superclassReference = (cls.superclass == null)
+            ? new js.LiteralNull()
+            : classReference(cls.superclass);
+
+        inheritCalls.add(js.js('inherit(#, #)',
+            [classReference(cls), superclassReference]));
+
+        if (cls.isMixinApplication) {
+          MixinApplication mixin = cls;
+          mixinCalls.add(js.js('mixin(#, #)',
+              [classReference(cls), classReference(mixin.mixinClass)]));
+        }
+      }
+    }
+
+    return new js.Block([inheritCalls, mixinCalls]
+        .expand((e) => e)
+        .map((e) => new js.ExpressionStatement(e))
+        .toList(growable: false));
+  }
+
+  /// Emits the setup of method aliases.
+  ///
+  /// This step consists of simply copying JavaScript functions to their
+  /// aliased names so they point to the same function.
+  js.Statement emitInstanceMethodAliases(Fragment fragment) {
+    List<js.Statement> assignments = <js.Statement>[];
+
+    for (Library library in fragment.libraries) {
+      for (Class cls in library.classes) {
+        for (InstanceMethod method in cls.methods) {
+          if (method.aliasName != null) {
+            assignments.add(js.js.statement(
+                '#.prototype.# = #.prototype.#',
+                [classReference(cls), js.quoteName(method.aliasName),
+                 classReference(cls), js.quoteName(method.name)]));
+
+          }
+        }
+      }
+    }
+    return new js.Block(assignments);
+  }
+
+  /// Encodes the optional default values so that the runtime Function.apply
+  /// can use them.
+  js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
+    // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
+    if (method.optionalParameterDefaultValues is List) {
+      List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
+      Iterable<js.Expression> elements =
+          defaultValues.map(generateConstantReference);
+      return js.js('function() { return #; }',
+          new js.ArrayInitializer(elements.toList()));
+    } else {
+      Map<String, ConstantValue> defaultValues =
+          method.optionalParameterDefaultValues;
+      List<js.Property> properties = <js.Property>[];
+      List<String> names = defaultValues.keys.toList(growable: false);
+      // Sort the names the same way we sort them for the named-argument calling
+      // convention.
+      names.sort();
+
+      for (String name in names) {
+        ConstantValue value = defaultValues[name];
+        properties.add(new js.Property(js.string(name),
+        generateConstantReference(value)));
+      }
+      return js.js('function() { return #; }',
+          new js.ObjectInitializer(properties));
+    }
+  }
+
+  /// Emits the statement that installs a tear off for a method.
+  ///
+  /// Tear-offs might be passed to `Function.apply` which means that all
+  /// calling-conventions (with or without optional positional/named arguments)
+  /// are possible. As such, the tear-off needs enough information to fill in
+  /// missing parameters.
+  js.Statement emitInstallTearOff(js.Expression container, DartMethod method) {
+    List<js.Name> callNames = <js.Name>[];
+    List<js.Expression> funsOrNames = <js.Expression>[];
+
+    /// Adds the stub-method's code or name to the [funsOrNames] array.
+    ///
+    /// Static methods don't need stub-methods except for tear-offs. As such,
+    /// they are not emitted in the prototype, but directly passed here.
+    ///
+    /// Instance-methods install the stub-methods in their prototype, and we
+    /// use string-based redirections to find them there.
+    void addFunOrName(StubMethod stubMethod) {
+      if (method.isStatic) {
+        funsOrNames.add(stubMethod.code);
+      } else {
+        funsOrNames.add(js.quoteName(stubMethod.name));
+      }
+    }
+
+    callNames.add(method.callName);
+    // The first entry in the funsOrNames-array must be a string.
+    funsOrNames.add(js.quoteName(method.name));
+    for (ParameterStubMethod stubMethod in method.parameterStubs) {
+      callNames.add(stubMethod.callName);
+      addFunOrName(stubMethod);
+    }
+
+    js.ArrayInitializer callNameArray =
+        new js.ArrayInitializer(callNames.map(js.quoteName).toList());
+    js.ArrayInitializer funsOrNamesArray = new js.ArrayInitializer(funsOrNames);
+
+    bool isIntercepted = false;
+    if (method is InstanceMethod) {
+      isIntercepted = backend.isInterceptedMethod(method.element);
+    }
+    int requiredParameterCount = 0;
+    js.Expression optionalParameterDefaultValues = new js.LiteralNull();
+    if (method.canBeApplied) {
+      requiredParameterCount = method.requiredParameterCount;
+      optionalParameterDefaultValues =
+          _encodeOptionalParameterDefaultValues(method);
+    }
+
+    return js.js.statement('''
+        installTearOff(#container, #getterName, #isStatic, #isIntercepted,
+                       #requiredParameterCount, #optionalParameterDefaultValues,
+                       #callNames, #funsOrNames, #funType)''',
+        {
+          "container": container,
+          "getterName": js.quoteName(method.tearOffName),
+          "isStatic": new js.LiteralBool(method.isStatic),
+          "isIntercepted": new js.LiteralBool(isIntercepted),
+          "requiredParameterCount": js.number(requiredParameterCount),
+          "optionalParameterDefaultValues": optionalParameterDefaultValues,
+          "callNames": callNameArray,
+          "funsOrNames": funsOrNamesArray,
+          "funType": method.functionType,
+        });
+  }
+
+  /// Emits the section that installs tear-off getters.
+  js.Statement emitInstallTearOffs(Fragment fragment) {
+    List<js.Statement> inits = <js.Statement>[];
+
+    for (Library library in fragment.libraries) {
+      for (StaticMethod method in library.statics) {
+        // TODO(floitsch): can there be anything else than a StaticDartMethod?
+        if (method is StaticDartMethod) {
+          if (method.needsTearOff) {
+            Holder holder = method.holder;
+            inits.add(
+                emitInstallTearOff(new js.VariableUse(holder.name), method));
+          }
+        }
+      }
+      for (Class cls in library.classes) {
+        for (InstanceMethod method in cls.methods) {
+          if (method.needsTearOff) {
+            js.Expression container = js.js("#.prototype", classReference(cls));
+            inits.add(emitInstallTearOff(container, method));
+          }
+        }
+      }
+    }
+    return new js.Block(inits);
+  }
+
+  /// Emits the constants section.
+  js.Statement emitConstants(Fragment fragment) {
+    List<js.Statement> assignments = <js.Statement>[];
+    for (Constant constant in fragment.constants) {
+      // TODO(floitsch): instead of just updating the constant holder, we should
+      // find the constants that don't have any dependency on other constants
+      // and create an object-literal with them (and assign it to the
+      // constant-holder variable).
+      assignments.add(js.js.statement('#.# = #',
+          [constant.holder.name,
+           constant.name,
+           constantEmitter.generate(constant.value)]));
+    }
+    return new js.Block(assignments);
+  }
+
+
+  /// Emits the static non-final fields section.
+  ///
+  /// This section initializes all static non-final fields that don't require
+  /// an initializer.
+  js.Block emitStaticNonFinalFields(Fragment fragment) {
+    List<StaticField> fields = fragment.staticNonFinalFields;
+    // TODO(floitsch): instead of assigning the fields one-by-one we should
+    // create a literal and assign it to the static-state holder.
+    // TODO(floitsch): if we don't make a literal we should at least initialize
+    // statics that have the same initial value in the same expression:
+    //    `$.x = $.y = $.z = null;`.
+    Iterable<js.Statement> statements = fields.map((StaticField field) {
+      assert(field.holder.isStaticStateHolder);
+      return js.js.statement("#.# = #;",
+          [field.holder.name, field.name, field.code]);
+    });
+    return new js.Block(statements.toList());
+  }
+
+  /// Emits lazy fields.
+  ///
+  /// This section initializes all static (final and non-final) fields that
+  /// require an initializer.
+  js.Block emitLazilyInitializedStatics(Fragment fragment) {
+    List<StaticField> fields = fragment.staticLazilyInitializedFields;
+    Iterable<js.Statement> statements = fields.map((StaticField field) {
+      assert(field.holder.isStaticStateHolder);
+      return js.js.statement("lazy(#, #, #, #);",
+          [field.holder.name,
+           js.quoteName(field.name),
+           js.quoteName(namer.deriveLazyInitializerName(field.name)),
+           field.code]);
+    });
+
+    return new js.Block(statements.toList());
+  }
+
+  /// Emits the embedded globals that are needed for deferred loading.
+  ///
+  /// This function is only invoked for the main fragment.
+  ///
+  /// The [loadMap] contains a map from load-ids (for each deferred library)
+  /// to the list of generated fragments that must be installed when the
+  /// deferred library is loaded.
+  Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
+      Map<String, List<Fragment>> loadMap,
+      Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
+    if (loadMap.isEmpty) return [];
+
+    List<js.Property> globals = <js.Property>[];
+
+    js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
+      return js.stringArray(fragments.map((DeferredFragment fragment) =>
+          "${fragment.outputFileName}.${ModelEmitter.deferredExtension}"));
+    }
+    js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
+      return new js.ArrayInitializer(
+          fragments
+              .map((fragment) => deferredLoadHashes[fragment])
+              .toList(growable: false));
+    }
+
+    List<js.Property> uris = new List<js.Property>(loadMap.length);
+    List<js.Property> hashes = new List<js.Property>(loadMap.length);
+    int count = 0;
+    loadMap.forEach((String loadId, List<Fragment> fragmentList) {
+      uris[count] =
+          new js.Property(js.string(loadId), fragmentUris(fragmentList));
+      hashes[count] =
+          new js.Property(js.string(loadId), fragmentHashes(fragmentList));
+      count++;
+    });
+
+    globals.add(new js.Property(js.string(DEFERRED_LIBRARY_URIS),
+        new js.ObjectInitializer(uris)));
+    globals.add(new js.Property(js.string(DEFERRED_LIBRARY_HASHES),
+        new js.ObjectInitializer(hashes)));
+    globals.add(new js.Property(js.string(DEFERRED_INITIALIZED),
+        js.js("Object.create(null)")));
+
+    String deferredGlobal = ModelEmitter.deferredInitializersGlobal;
+    js.Expression isHunkLoadedFunction =
+        js.js("function(hash) { return !!$deferredGlobal[hash]; }");
+    globals.add(new js.Property(js.string(IS_HUNK_LOADED),
+        isHunkLoadedFunction));
+
+    js.Expression isHunkInitializedFunction =
+        js.js("function(hash) { return !!#deferredInitialized[hash]; }",
+            {'deferredInitialized':
+                generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)});
+    globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED),
+        isHunkInitializedFunction));
+
+    /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the
+    /// deferred hunk.
+    js.Expression initializeLoadedHunkFunction =
+    js.js("""
+            function(hash) {
+              initializeDeferredHunk($deferredGlobal[hash]);
+              #deferredInitialized[hash] = true;
+            }""", {'deferredInitialized':
+                    generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)});
+
+    globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK),
+                                initializeLoadedHunkFunction));
+
+    return globals;
+  }
+
+  /// Emits the [MANGLED_GLOBAL_NAMES] embedded global.
+  ///
+  /// This global maps minified names for selected classes (some important
+  /// core classes, and some native classes) to their unminified names.
+  js.Property emitMangledGlobalNames() {
+    List<js.Property> names = <js.Property>[];
+
+    // We want to keep the original names for the most common core classes when
+    // calling toString on them.
+    List<ClassElement> nativeClassesNeedingUnmangledName =
+        [compiler.intClass, compiler.doubleClass, compiler.numClass,
+         compiler.stringClass, compiler.boolClass, compiler.nullClass,
+         compiler.listClass];
+    // TODO(floitsch): this should probably be on a per-fragment basis.
+    nativeClassesNeedingUnmangledName.forEach((element) {
+      names.add(new js.Property(js.quoteName(namer.className(element)),
+                                js.string(element.name)));
+    });
+
+    return new js.Property(js.string(MANGLED_GLOBAL_NAMES),
+                           new js.ObjectInitializer(names));
+  }
+
+  /// Emits the [GET_TYPE_FROM_NAME] embedded global.
+  ///
+  /// This embedded global provides a way to go from a class name (which is
+  /// also the constructor's name) to the constructor itself.
+  js.Property emitGetTypeFromName() {
+    js.Expression function = js.js("getGlobalFromName");
+    return new js.Property(js.string(GET_TYPE_FROM_NAME), function);
+  }
+
+  /// Emits the [METADATA] embedded global.
+  ///
+  /// The metadata itself has already been computed earlier and is stored in
+  /// the [program].
+  List<js.Property> emitMetadata(Program program) {
+    List<js.Property> metadataGlobals = <js.Property>[];
+
+    js.Property createGlobal(js.Expression metadata, String global) {
+      return new js.Property(js.string(global), metadata);
+    }
+
+    metadataGlobals.add(createGlobal(program.metadata, METADATA));
+    js.Expression types =
+        program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
+    metadataGlobals.add(createGlobal(types, TYPES));
+
+    return metadataGlobals;
+  }
+
+  /// Emits all embedded globals.
+  js.Statement emitEmbeddedGlobals(
+      Program program,
+      Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
+    List<js.Property> globals = <js.Property>[];
+
+    if (program.loadMap.isNotEmpty) {
+      globals.addAll(emitEmbeddedGlobalsForDeferredLoading(
+          program.loadMap, deferredLoadHashes));
+    }
+
+    if (program.typeToInterceptorMap != null) {
+      globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
+      program.typeToInterceptorMap));
+    }
+
+    if (program.hasIsolateSupport) {
+      String staticStateName = namer.staticStateHolder;
+      // TODO(floitsch): this doesn't create a new isolate, but just reuses
+      // the current static state. Since we don't run multiple isolates in the
+      // same JavaScript context (except for testing) this shouldn't have any
+      // impact on real-world programs, though.
+      globals.add(
+          new js.Property(js.string(CREATE_NEW_ISOLATE),
+                          js.js('function () { return $staticStateName; }')));
+
+      js.Expression nameToClosureFunction = js.js('''
+        // First fetch the static function. From there we can execute its
+        // getter function which builds a Dart closure.
+        function(name) {
+           var staticFunction = getGlobalFromName(name);
+           var getterFunction = staticFunction.$tearOffPropertyName;
+           return getterFunction();
+         }''');
+      globals.add(new js.Property(js.string(STATIC_FUNCTION_NAME_TO_CLOSURE),
+                                  nameToClosureFunction));
+
+      globals.add(
+          new js.Property(js.string(CLASS_ID_EXTRACTOR),
+                          js.js('function(o) { return o.constructor.name; }')));
+
+      js.Expression extractFieldsFunction = js.js('''
+      function(o) {
+        var constructor = o.constructor;
+        var fieldNames = constructor.$cachedClassFieldNames;
+        if (!fieldNames) {
+          // Extract the fields from an empty unmodified object.
+          var empty = new constructor();
+          // This gives us the keys that the constructor sets.
+          fieldNames = constructor.$cachedClassFieldNames = Object.keys(empty);
+        }
+        var result = new Array(fieldNames.length);
+        for (var i = 0; i < fieldNames.length; i++) {
+          result[i] = o[fieldNames[i]];
+        }
+        return result;
+      }''');
+      globals.add(new js.Property(js.string(CLASS_FIELDS_EXTRACTOR),
+                                  extractFieldsFunction));
+
+      js.Expression createInstanceFromClassIdFunction = js.js('''
+        function(name) {
+          var constructor = getGlobalFromName(name);
+          return new constructor();
+        }
+      ''');
+      globals.add(new js.Property(js.string(INSTANCE_FROM_CLASS_ID),
+                                  createInstanceFromClassIdFunction));
+
+      js.Expression initializeEmptyInstanceFunction = js.js('''
+      function(name, o, fields) {
+        var constructor = o.constructor;
+        // By construction the object `o` is an empty object with the same
+        // keys as the one we used in the extract-fields function.
+        var fieldNames = Object.keys(o);
+        if (fieldNames.length != fields.length) {
+          throw new Error("Mismatch during deserialization.");
+        }
+        for (var i = 0; i < fields.length; i++) {
+          o[fieldNames[i]] = fields[i];
+        }
+        return o;
+      }''');
+      globals.add(new js.Property(js.string(INITIALIZE_EMPTY_INSTANCE),
+                                  initializeEmptyInstanceFunction));
+    }
+
+    globals.add(emitMangledGlobalNames());
+
+    // The [MANGLED_NAMES] table must contain the mapping for const symbols.
+    // Without const symbols, the table is only relevant for reflection and
+    // therefore unused in this emitter.
+    List<js.Property> mangledNamesProperties = <js.Property>[];
+    program.symbolsMap.forEach((js.Name mangledName, String unmangledName) {
+      mangledNamesProperties.add(
+          new js.Property(mangledName, js.string(unmangledName)));
+    });
+    globals.add(new js.Property(
+        js.string(MANGLED_NAMES),
+        new js.ObjectInitializer(mangledNamesProperties)));
+
+    globals.add(emitGetTypeFromName());
+
+    globals.addAll(emitMetadata(program));
+
+    if (program.needsNativeSupport) {
+      globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG),
+          new js.LiteralNull()));
+      globals.add(new js.Property(js.string(LEAF_TAGS),
+          new js.LiteralNull()));
+    }
+
+    js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
+
+    return js.js.statement('var init = #;', globalsObject);
+  }
+
+  /// Emits data needed for native classes.
+  ///
+  /// We don't try to reduce the size of the native data, but rather build
+  /// JavaScript object literals that contain all the information directly.
+  /// This means that the output size is bigger, but that the startup is faster.
+  ///
+  /// This function is the static equivalent of
+  /// [NativeGenerator.buildNativeInfoHandler].
+  js.Statement emitNativeSupport(Fragment fragment) {
+    List<js.Statement> statements = <js.Statement>[];
+
+    // The isolate-affinity tag must only be initialized once per program.
+    if (fragment.isMainFragment &&
+        NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
+      statements.add(NativeGenerator.generateIsolateAffinityTagInitialization(
+              backend,
+              generateEmbeddedGlobalAccess,
+              js.js("""
+        // On V8, the 'intern' function converts a string to a symbol, which
+        // makes property access much faster.
+        function (s) {
+          var o = {};
+          o[s] = 1;
+          return Object.keys(convertToFastObject(o))[0];
+        }""", [])));
+    }
+
+    Map<String, js.Expression> interceptorsByTag = <String, js.Expression>{};
+    Map<String, js.Expression> leafTags = <String, js.Expression>{};
+    js.Statement subclassAssignment = new js.EmptyStatement();
+
+    for (Library library in fragment.libraries) {
+      for (Class cls in library.classes) {
+        if (cls.nativeLeafTags != null) {
+          for (String tag in cls.nativeLeafTags) {
+            interceptorsByTag[tag] = classReference(cls);
+            leafTags[tag] = new js.LiteralBool(true);
+          }
+        }
+        if (cls.nativeNonLeafTags != null) {
+          for (String tag in cls.nativeNonLeafTags) {
+            interceptorsByTag[tag] = classReference(cls);
+            leafTags[tag] = new js.LiteralBool(false);
+          }
+          if (cls.nativeExtensions != null) {
+            List<Class> subclasses = cls.nativeExtensions;
+            js.Expression value = js.string(cls.nativeNonLeafTags[0]);
+            for (Class subclass in subclasses) {
+              value = js.js('#.# = #',
+                  [classReference(subclass),
+                   NATIVE_SUPERCLASS_TAG_NAME,
+                   js.string(cls.nativeNonLeafTags[0])]);
+            }
+            subclassAssignment = new js.ExpressionStatement(value);
+          }
+        }
+      }
+    }
+    statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);",
+        js.objectLiteral(interceptorsByTag)));
+    statements.add(js.js.statement("setOrUpdateLeafTags(#);",
+        js.objectLiteral(leafTags)));
+    statements.add(subclassAssignment);
+
+    return new js.Block(statements);
+  }
+}
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 9797dbb..e30c58b 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
@@ -4,37 +4,65 @@
 
 library dart2js.js_emitter.startup_emitter.model_emitter;
 
+import 'dart:convert' show JsonEncoder;
+
+import '../../common.dart';
+
 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
 import '../../dart2jslib.dart' show Compiler;
 import '../../elements/elements.dart' show ClassElement, FunctionElement;
+import '../../hash/sha1.dart' show Hasher;
+
+import '../../io/code_output.dart';
+
+import '../../io/line_column_provider.dart' show
+    LineColumnCollector,
+    LineColumnProvider;
+
+import '../../io/source_map_builder.dart' show
+    SourceMapBuilder;
+
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show
     JavaScriptBackend,
     Namer,
     ConstantEmitter;
 
+import '../../util/util.dart' show
+    NO_LOCATION_SPANNABLE;
+
+import '../../util/uri_extras.dart' show
+    relativize;
+
 import '../js_emitter.dart' show AstContainer, NativeEmitter;
 
 import 'package:js_runtime/shared/embedded_names.dart' show
+    CLASS_FIELDS_EXTRACTOR,
+    CLASS_ID_EXTRACTOR,
     CREATE_NEW_ISOLATE,
     DEFERRED_INITIALIZED,
     DEFERRED_LIBRARY_URIS,
     DEFERRED_LIBRARY_HASHES,
     GET_TYPE_FROM_NAME,
+    INITIALIZE_EMPTY_INSTANCE,
     INITIALIZE_LOADED_HUNK,
+    INSTANCE_FROM_CLASS_ID,
     INTERCEPTORS_BY_TAG,
     IS_HUNK_INITIALIZED,
     IS_HUNK_LOADED,
     LEAF_TAGS,
     MANGLED_GLOBAL_NAMES,
+    MANGLED_NAMES,
     METADATA,
     NATIVE_SUPERCLASS_TAG_NAME,
+    STATIC_FUNCTION_NAME_TO_CLOSURE,
     TYPE_TO_INTERCEPTOR_MAP,
     TYPES;
 
 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
 import '../model.dart';
 
+part 'deferred_fragment_hash.dart';
 part 'fragment_emitter.dart';
 
 class ModelEmitter {
@@ -42,6 +70,11 @@
   final Namer namer;
   ConstantEmitter constantEmitter;
   final NativeEmitter nativeEmitter;
+  final bool shouldGenerateSourceMap;
+
+  // The full code that is written to each hunk part-file.
+  final Map<Fragment, CodeOutput> outputBuffers = <Fragment, CodeOutput>{};
+
 
   JavaScriptBackend get backend => compiler.backend;
 
@@ -53,7 +86,8 @@
 
   static const String typeNameProperty = r"builtin$cls";
 
-  ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter)
+  ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter,
+               this.shouldGenerateSourceMap)
       : this.compiler = compiler,
         this.namer = namer {
     this.constantEmitter = new ConstantEmitter(
@@ -126,55 +160,239 @@
   }
 
   int emitProgram(Program program) {
-    List<Fragment> fragments = program.fragments;
-    MainFragment mainFragment = fragments.first;
-
-    int totalSize = 0;
+    MainFragment mainFragment = program.fragments.first;
+    List<DeferredFragment> deferredFragments =
+        new List<DeferredFragment>.from(program.fragments.skip(1));
 
     FragmentEmitter fragmentEmitter =
         new FragmentEmitter(compiler, namer, backend, constantEmitter, this);
 
-    // We have to emit the deferred fragments first, since we need their
-    // deferred hash (which depends on the output) when emitting the main
-    // fragment.
-    List<js.Expression> fragmentsCode = fragments.skip(1).map(
-            (DeferredFragment deferredFragment) {
-          js.Expression types =
-          program.metadataTypesForOutputUnit(deferredFragment.outputUnit);
-          return fragmentEmitter.emitDeferredFragment(
-              deferredFragment, types, program.holders);
-        }).toList();
+    Map<DeferredFragment, _DeferredFragmentHash> deferredHashTokens =
+      new Map<DeferredFragment, _DeferredFragmentHash>();
+    for (DeferredFragment fragment in deferredFragments) {
+      deferredHashTokens[fragment] = new _DeferredFragmentHash(fragment);
+    }
 
-    js.Statement mainAst = fragmentEmitter.emitMainFragment(program);
+    js.Statement mainCode =
+        fragmentEmitter.emitMainFragment(program, deferredHashTokens);
+
+    Map<DeferredFragment, js.Expression> deferredFragmentsCode =
+        <DeferredFragment, js.Expression>{};
+
+    for (DeferredFragment fragment in deferredFragments) {
+      js.Expression types =
+          program.metadataTypesForOutputUnit(fragment.outputUnit);
+      deferredFragmentsCode[fragment] = fragmentEmitter.emitDeferredFragment(
+                fragment, types, program.holders);
+    }
 
     js.TokenCounter counter = new js.TokenCounter();
-    fragmentsCode.forEach(counter.countTokens);
-    counter.countTokens(mainAst);
+    deferredFragmentsCode.values.forEach(counter.countTokens);
+    counter.countTokens(mainCode);
 
     program.finalizers.forEach((js.TokenFinalizer f) => f.finalizeTokens());
 
-    for (int i = 0; i < fragmentsCode.length; ++i) {
-      String code = js.prettyPrint(fragmentsCode[i], compiler).getText();
-      totalSize += code.length;
-      compiler.outputProvider(fragments[i+1].outputFileName, deferredExtension)
-        ..add(code)
-        ..close();
+    Map<DeferredFragment, String> hunkHashes =
+        writeDeferredFragments(deferredFragmentsCode);
+
+    // Now that we have written the deferred hunks, we can update the hash
+    // tokens in the main-fragment.
+    deferredHashTokens.forEach((DeferredFragment key,
+                                _DeferredFragmentHash token) {
+      token.setHash(hunkHashes[key]);
+    });
+
+    writeMainFragment(mainFragment, mainCode);
+
+    if (backend.requiresPreamble &&
+        !backend.htmlLibraryIsLoaded) {
+      compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
     }
 
-    String mainCode = js.prettyPrint(mainAst, compiler).getText();
-    compiler.outputProvider(mainFragment.outputFileName, 'js')
-      ..add(buildGeneratedBy(compiler))
-      ..add(mainCode)
-      ..close();
-    totalSize += mainCode.length;
-
-    return totalSize;
+    if (compiler.deferredMapUri != null) {
+      writeDeferredMap();
+    }
+    
+    // Return the total program size.
+    return outputBuffers.values.fold(0, (a, b) => a + b.length);
   }
 
+  /// Generates a simple header that provides the compiler's build id.
   String buildGeneratedBy(compiler) {
     var suffix = '';
     if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
     return '// Generated by dart2js (fast startup), '
         'the Dart to JavaScript compiler$suffix.\n';
   }
+
+  /// Writes all deferred fragment's code into files.
+  ///
+  /// Returns a map from fragment to its hashcode (as used for the deferred
+  /// library code).
+  ///
+  /// Updates the shared [outputBuffers] field with the output.
+  Map<DeferredFragment, String> writeDeferredFragments(
+      Map<DeferredFragment, js.Expression> fragmentsCode) {
+    Map<DeferredFragment, String> hunkHashes = <DeferredFragment, String>{};
+
+    fragmentsCode.forEach((DeferredFragment fragment, js.Expression code) {
+      hunkHashes[fragment] = writeDeferredFragment(fragment, code);
+    });
+
+    return hunkHashes;
+  }
+
+  // Writes the given [fragment]'s [code] into a file.
+  //
+  // Updates the shared [outputBuffers] field with the output.
+  void writeMainFragment(MainFragment fragment, js.Statement code) {
+    LineColumnCollector lineColumnCollector;
+    List<CodeOutputListener> codeOutputListeners;
+    if (shouldGenerateSourceMap) {
+      lineColumnCollector = new LineColumnCollector();
+      codeOutputListeners = <CodeOutputListener>[lineColumnCollector];
+    }
+
+    CodeOutput mainOutput = new StreamCodeOutput(
+            compiler.outputProvider('', 'js'),
+            codeOutputListeners);
+    outputBuffers[fragment] = mainOutput;
+
+    mainOutput.addBuffer(js.prettyPrint(code, compiler,
+        monitor: compiler.dumpInfoTask));
+
+    if (shouldGenerateSourceMap) {
+      mainOutput.add(
+          generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
+    }
+
+    mainOutput.close();
+
+    if (shouldGenerateSourceMap) {
+      outputSourceMap(mainOutput, lineColumnCollector, '',
+      compiler.sourceMapUri, compiler.outputUri);
+    }
+  }
+
+  // Writes the given [fragment]'s [code] into a file.
+  //
+  // Returns the deferred fragment's hash.
+  //
+  // Updates the shared [outputBuffers] field with the output.
+  String writeDeferredFragment(DeferredFragment fragment, js.Expression code) {
+    List<CodeOutputListener> outputListeners = <CodeOutputListener>[];
+    Hasher hasher = new Hasher();
+    outputListeners.add(hasher);
+
+    LineColumnCollector lineColumnCollector;
+    if (shouldGenerateSourceMap) {
+      lineColumnCollector = new LineColumnCollector();
+      outputListeners.add(lineColumnCollector);
+    }
+
+    String hunkPrefix = fragment.outputFileName;
+
+    CodeOutput output = new StreamCodeOutput(
+        compiler.outputProvider(hunkPrefix, deferredExtension),
+        outputListeners);
+
+    outputBuffers[fragment] = output;
+
+    // The [code] contains the function that must be invoked when the deferred
+    // hunk is loaded.
+    // That function must be in a map from its hashcode to the function. Since
+    // we don't know the hash before we actually emit the code we store the
+    // function in a temporary field first:
+    //
+    //   deferredInitializer.current = <pretty-printed code>;
+    //   deferredInitializer[<hash>] = deferredInitializer.current;
+
+    output.add('\n${deferredInitializersGlobal}.current = ');
+
+    output.addBuffer(js.prettyPrint(code, compiler,
+        monitor: compiler.dumpInfoTask));
+
+    // Make a unique hash of the code (before the sourcemaps are added)
+    // This will be used to retrieve the initializing function from the global
+    // variable.
+    String hash = hasher.getHash();
+
+    // Now we copy the deferredInitializer.current into its correct hash.
+    output.add('\n${deferredInitializersGlobal}["$hash"] = '
+        '${deferredInitializersGlobal}.current');
+
+    if (shouldGenerateSourceMap) {
+      Uri mapUri, partUri;
+      Uri sourceMapUri = compiler.sourceMapUri;
+      Uri outputUri = compiler.outputUri;
+
+      if (sourceMapUri != null) {
+        String mapFileName =
+            hunkPrefix + deferredExtension + ".map";
+        List<String> mapSegments = sourceMapUri.pathSegments.toList();
+        mapSegments[mapSegments.length - 1] = mapFileName;
+        mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments);
+      }
+
+      if (outputUri != null) {
+        String hunkFileName = hunkPrefix + deferredExtension;
+        List<String> partSegments = outputUri.pathSegments.toList();
+        partSegments[partSegments.length - 1] = hunkFileName;
+        partUri = compiler.outputUri.replace(pathSegments: partSegments);
+      }
+
+      output.add(generateSourceMapTag(mapUri, partUri));
+      output.close();
+      outputSourceMap(output, lineColumnCollector, hunkPrefix, mapUri, partUri);
+    } else {
+      output.close();
+    }
+
+    return hash;
+  }
+
+  String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) {
+    if (sourceMapUri != null && fileUri != null) {
+      String sourceMapFileName = relativize(fileUri, sourceMapUri, false);
+      return '''
+
+//# sourceMappingURL=$sourceMapFileName
+''';
+    }
+    return '';
+  }
+
+
+  void outputSourceMap(CodeOutput output,
+                       LineColumnProvider lineColumnProvider,
+                       String name,
+                       [Uri sourceMapUri,
+                       Uri fileUri]) {
+    if (!shouldGenerateSourceMap) return;
+    // Create a source file for the compilation output. This allows using
+    // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder].
+    SourceMapBuilder sourceMapBuilder =
+    new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider);
+    output.forEachSourceLocation(sourceMapBuilder.addMapping);
+    String sourceMap = sourceMapBuilder.build();
+    compiler.outputProvider(name, 'js.map')
+      ..add(sourceMap)
+      ..close();
+  }
+
+  /// Writes a mapping from library-name to hunk files.
+  ///
+  /// The output is written into a separate file that can be used by outside
+  /// tools.
+  void writeDeferredMap() {
+    Map<String, dynamic> mapping = new Map<String, dynamic>();
+    // Json does not support comments, so we embed the explanation in the
+    // data.
+    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')
+      ..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 3e6acb5..9919cee 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -530,15 +530,15 @@
   /// loaded as well.
   Future<LibraryElement> loadDeserializedLibrary(
       LibraryDependencyHandler handler,
-      LibraryElement library) async {
+      LibraryElement library) {
     compiler.onLibraryCreated(library);
     libraryCanonicalUriMap[library.canonicalUri] = library;
-    await compiler.onLibraryScanned(library, handler);
-    for (LibraryTag tag in library.tags) {
-      LibraryElement dependency = library.getLibraryFromTag(tag);
-      await createLibrary(handler, library, dependency.canonicalUri);
-    }
-    return library;
+    return compiler.onLibraryScanned(library, handler).then((_) {
+      return Future.forEach(library.tags, (LibraryTag tag) {
+        LibraryElement dependency = library.getLibraryFromTag(tag);
+        return createLibrary(handler, library, dependency.canonicalUri);
+      }).then((_) => library);
+    });
   }
 
   /**
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 34d6e79..59bbc19 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -31,8 +31,8 @@
   LegacyCompilerDiagnostics(this._handler);
 
   @override
-  void report(Uri uri, int begin, int end,
-                        String message, Diagnostic kind) {
+  void report(var code, Uri uri, int begin, int end,
+              String message, Diagnostic kind) {
     _handler(uri, begin, end, message, kind);
   }
 }
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 297897b..a639a58 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -440,6 +440,8 @@
         return const PatchVersion('full');
       } else if (annotation.beginToken.next.value == 'patch_lazy') {
         return const PatchVersion('lazy');
+      } else if (annotation.beginToken.next.value == 'patch_startup') {
+        return const PatchVersion('startup');
       }
     }
     return null;
diff --git a/pkg/compiler/lib/src/resolution/access_semantics.dart b/pkg/compiler/lib/src/resolution/access_semantics.dart
index 2c741b3..834a043 100644
--- a/pkg/compiler/lib/src/resolution/access_semantics.dart
+++ b/pkg/compiler/lib/src/resolution/access_semantics.dart
@@ -143,6 +143,10 @@
 
   /// The destination of the access is unresolved super access.
   UNRESOLVED_SUPER,
+
+  /// The destination is invalid as an access. For instance a prefix used
+  /// as an expression.
+  INVALID,
 }
 
 enum CompoundAccessKind {
@@ -178,7 +182,7 @@
   /// Read from a superclass getter and write to a superclass field.
   SUPER_GETTER_FIELD,
 
-  /// Read from a superclass where the getter (and maybe setter) is unresolved.
+  /// Read from a superclass where the getter is unresolved.
   UNRESOLVED_SUPER_GETTER,
   /// Read from a superclass getter and write to an unresolved setter.
   UNRESOLVED_SUPER_SETTER,
@@ -227,6 +231,14 @@
 
   ConstantExpression get constant => null;
 
+  /// The element for the getter in case of a compound access,
+  /// [element] otherwise.
+  Element get getter => element;
+
+  /// The element for the setter in case of a compound access,
+  /// [element] otherwise.
+  Element get setter => element;
+
   AccessSemantics.expression()
       : kind = AccessKind.EXPRESSION;
 
@@ -357,6 +369,9 @@
 
   StaticAccess.unresolvedSuper(this.element)
       : super._(AccessKind.UNRESOLVED_SUPER);
+
+  StaticAccess.invalid(this.element)
+      : super._(AccessKind.INVALID);
 }
 
 class CompoundAccessSemantics extends AccessSemantics {
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index ea44ed2..a67de98 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -874,26 +874,36 @@
     }
   }
 
-  /// Check that access to `super` is currently allowed.
-  bool checkSuperAccess(Send node) {
+  /// Check that access to `super` is currently allowed. Returns an
+  /// [AccessSemantics] in case of an error, `null` otherwise.
+  AccessSemantics checkSuperAccess(Send node) {
     if (!inInstanceContext) {
-      compiler.reportError(node, MessageKind.NO_SUPER_IN_STATIC);
-      return false;
+      return new StaticAccess.invalid(
+          reportAndCreateErroneousElement(
+              node, 'super',
+              MessageKind.NO_SUPER_IN_STATIC, {},
+              isError: true));
     }
     if (node.isConditional) {
       // `super?.foo` is not allowed.
-      compiler.reportError(node, MessageKind.INVALID_USE_OF_SUPER);
-      return false;
+      return new StaticAccess.invalid(
+          reportAndCreateErroneousElement(
+              node, 'super',
+              MessageKind.INVALID_USE_OF_SUPER, {},
+              isError: true));
     }
     if (currentClass.supertype == null) {
       // This is just to guard against internal errors, so no need
       // for a real error message.
-      compiler.reportError(node, MessageKind.GENERIC,
-            {'text': "Object has no superclass"});
-      return false;
+      return new StaticAccess.invalid(
+          reportAndCreateErroneousElement(
+              node, 'super',
+              MessageKind.GENERIC,
+              {'text': "Object has no superclass"},
+              isError: true));
     }
     registry.registerSuperUse(node);
-    return true;
+    return null;
   }
 
   /// Check that access to `this` is currently allowed.
@@ -926,6 +936,78 @@
     }
   }
 
+  /// Compute the [AccessSemantics] corresponding to a compound super access
+  /// reading from [getter] and writing to [setter].
+  AccessSemantics computeCompoundSuperAccessSemantics(
+      Spannable node,
+      Element getter,
+      Element setter) {
+    if (getter.isErroneous) {
+      if (setter.isErroneous) {
+        return new StaticAccess.unresolvedSuper(getter);
+      } else if (setter.isFunction) {
+        assert(invariant(node, setter.name == '[]=',
+            message: "Unexpected super setter '$setter'."));
+        return new CompoundAccessSemantics(
+                    CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, setter);
+      } else {
+        assert(invariant(node, setter.isSetter,
+            message: "Unexpected super setter '$setter'."));
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, setter);
+      }
+    } else if (getter.isField) {
+      if (setter.isField) {
+        if (getter == setter) {
+          return new StaticAccess.superField(getter);
+        } else {
+          return new CompoundAccessSemantics(
+              CompoundAccessKind.SUPER_FIELD_FIELD, getter, setter);
+        }
+      } else {
+        // Either the field is accessible directly, or a setter shadows the
+        // setter access. If there was another instance member it would shadow
+        // the field.
+        assert(invariant(node, setter.isSetter,
+            message: "Unexpected super setter '$setter'."));
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.SUPER_FIELD_SETTER, getter, setter);
+      }
+    } else if (getter.isGetter) {
+      if (setter.isErroneous) {
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, setter);
+      } else if (setter.isField) {
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.SUPER_GETTER_FIELD, getter, setter);
+      } else {
+        assert(invariant(node, setter.isSetter,
+            message: "Unexpected super setter '$setter'."));
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.SUPER_GETTER_SETTER, getter, setter);
+      }
+    } else {
+      assert(invariant(node, getter.isFunction,
+          message: "Unexpected super getter '$getter'."));
+      if (setter.isErroneous) {
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, setter);
+      } else if (setter.isFunction) {
+        assert(invariant(node, getter.name == '[]',
+            message: "Unexpected super getter '$getter'."));
+        assert(invariant(node, setter.name == '[]=',
+            message: "Unexpected super setter '$setter'."));
+        return new CompoundAccessSemantics(
+                    CompoundAccessKind.SUPER_GETTER_SETTER, getter, setter);
+      } else {
+        assert(invariant(node, setter.isSetter,
+            message: "Unexpected super setter '$setter'."));
+        return new CompoundAccessSemantics(
+            CompoundAccessKind.SUPER_METHOD_SETTER, getter, setter);
+      }
+    }
+  }
+
   /// Compute the [AccessSemantics] corresponding to a local access of [target].
   AccessSemantics computeLocalAccessSemantics(Spannable node,
                                               LocalElement target) {
@@ -1043,6 +1125,55 @@
     return computeSuperAccessSemantics(node, target);
   }
 
+  /// Compute the [AccessSemantics] for accessing the name of [selector] on the
+  /// super class.
+  ///
+  /// If no matching super member is found and error is reported and
+  /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName]
+  /// is provided, the [AccessSemantics] corresponding to the alternate name is
+  /// returned. For instance, the access of a super setter for an unresolved
+  /// getter:
+  ///
+  ///     class Super {
+  ///       set name(_) {}
+  ///     }
+  ///     class Sub extends Super {
+  ///       foo => super.name; // Access to the setter.
+  ///     }
+  ///
+  AccessSemantics computeSuperAccessSemanticsForSelectors(
+      Spannable node,
+      Selector getterSelector, Selector setterSelector) {
+
+    // TODO(johnniwinther): Ensure correct behavior if currentClass is a
+    // patch.
+    Element getter = currentClass.lookupSuperByName(getterSelector.memberName);
+    // [target] may be null which means invoking noSuchMethod on super.
+    if (getter == null) {
+      getter = reportAndCreateErroneousElement(
+          node, getterSelector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
+          {'className': currentClass.name, 'memberName': getterSelector.name});
+      // We still need to register the invocation, because we might
+      // call `super.noSuchMethod` which calls [JSInvocationMirror._invokeOn].
+      registry.registerDynamicInvocation(
+          new UniverseSelector(getterSelector, null));
+      registry.registerSuperNoSuchMethod();
+    }
+    Element setter = currentClass.lookupSuperByName(setterSelector.memberName);
+    // [target] may be null which means invoking noSuchMethod on super.
+    if (setter == null) {
+      setter = reportAndCreateErroneousElement(
+          node, setterSelector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
+          {'className': currentClass.name, 'memberName': setterSelector.name});
+      // We still need to register the invocation, because we might
+      // call `super.noSuchMethod` which calls [JSInvocationMirror._invokeOn].
+      registry.registerDynamicInvocation(
+          new UniverseSelector(setterSelector, null));
+      registry.registerSuperNoSuchMethod();
+    }
+    return computeCompoundSuperAccessSemantics(node, getter, setter);
+  }
+
   /// Resolve [node] as a subexpression that is _not_ the prefix of a member
   /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`.
   ResolutionResult visitExpression(Node node) {
@@ -1151,7 +1282,8 @@
 
     AccessSemantics semantics;
     if (node.isSuperCall) {
-      if (checkSuperAccess(node)) {
+      semantics = checkSuperAccess(node);
+      if (semantics == null) {
         semantics = computeSuperAccessSemanticsForSelector(node, selector);
         // TODO(johnniwinther): Add information to [AccessSemantics] about
         // whether it is erroneous.
@@ -1197,8 +1329,6 @@
       }
     }
     if (semantics != null) {
-      // TODO(johnniwinther): Support invalid super access as an
-      // [AccessSemantics].
       registry.registerSendStructure(node,
           new UnaryStructure(semantics, operator));
     }
@@ -1325,7 +1455,8 @@
     registry.setSelector(node, selector);
 
     if (node.isSuperCall) {
-      if (checkSuperAccess(node)) {
+      semantics = checkSuperAccess(node);
+      if (semantics == null) {
         semantics = computeSuperAccessSemanticsForSelector(node, selector);
         // TODO(johnniwinther): Add information to [AccessSemantics] about
         // whether it is erroneous.
@@ -1552,71 +1683,78 @@
     } else {
       selector = new Selector(SelectorKind.GETTER, name, callStructure);
     }
-    if (checkSuperAccess(node)) {
-      AccessSemantics semantics = computeSuperAccessSemanticsForSelector(
+    AccessSemantics semantics = checkSuperAccess(node);
+    if (semantics == null) {
+      semantics = computeSuperAccessSemanticsForSelector(
           node, selector, alternateName: name.setter);
-      if (node.isCall) {
-        bool isIncompatibleInvoke = false;
-        switch (semantics.kind) {
-          case AccessKind.SUPER_METHOD:
-            MethodElementX superMethod = semantics.element;
-            superMethod.computeSignature(compiler);
-            if (!callStructure.signatureApplies(
-                    superMethod.functionSignature)) {
-              registry.registerThrowNoSuchMethod();
-              registry.registerDynamicInvocation(
-                  new UniverseSelector(selector, null));
-              registry.registerSuperNoSuchMethod();
-              isIncompatibleInvoke = true;
-            } else {
-              registry.registerStaticInvocation(semantics.element);
-            }
-            break;
-          case AccessKind.SUPER_FIELD:
-          case AccessKind.SUPER_FINAL_FIELD:
-          case AccessKind.SUPER_GETTER:
-            registry.registerStaticUse(semantics.element);
-            selector = callStructure.callSelector;
+    }
+    if (node.isCall) {
+      bool isIncompatibleInvoke = false;
+      switch (semantics.kind) {
+        case AccessKind.SUPER_METHOD:
+          MethodElementX superMethod = semantics.element;
+          superMethod.computeSignature(compiler);
+          if (!callStructure.signatureApplies(
+                  superMethod.functionSignature)) {
+            registry.registerThrowNoSuchMethod();
             registry.registerDynamicInvocation(
                 new UniverseSelector(selector, null));
-            break;
-          case AccessKind.SUPER_SETTER:
-          case AccessKind.UNRESOLVED_SUPER:
-            // NoSuchMethod registered in [computeSuperSemantics].
-            break;
-          default:
-            internalError(node, "Unexpected super property access $semantics.");
-            break;
-        }
-        registry.registerSendStructure(node,
-            isIncompatibleInvoke
-                ? new IncompatibleInvokeStructure(semantics, selector)
-                : new InvokeStructure(semantics, selector));
-      } else {
-        switch (semantics.kind) {
-          case AccessKind.SUPER_METHOD:
-            // TODO(johnniwinther): Method this should be registered as a
-            // closurization.
-            registry.registerStaticUse(semantics.element);
-            break;
-          case AccessKind.SUPER_FIELD:
-          case AccessKind.SUPER_FINAL_FIELD:
-          case AccessKind.SUPER_GETTER:
-            registry.registerStaticUse(semantics.element);
-            break;
-          case AccessKind.SUPER_SETTER:
-          case AccessKind.UNRESOLVED_SUPER:
-            // NoSuchMethod registered in [computeSuperSemantics].
-            break;
-          default:
-            internalError(node, "Unexpected super property access $semantics.");
-            break;
-        }
-        registry.registerSendStructure(node,
-            new GetStructure(semantics, selector));
+            registry.registerSuperNoSuchMethod();
+            isIncompatibleInvoke = true;
+          } else {
+            registry.registerStaticInvocation(semantics.element);
+          }
+          break;
+        case AccessKind.SUPER_FIELD:
+        case AccessKind.SUPER_FINAL_FIELD:
+        case AccessKind.SUPER_GETTER:
+          registry.registerStaticUse(semantics.element);
+          selector = callStructure.callSelector;
+          registry.registerDynamicInvocation(
+              new UniverseSelector(selector, null));
+          break;
+        case AccessKind.SUPER_SETTER:
+        case AccessKind.UNRESOLVED_SUPER:
+          // NoSuchMethod registered in [computeSuperSemantics].
+          break;
+        case AccessKind.INVALID:
+          // 'super' is not allowed.
+          break;
+        default:
+          internalError(node, "Unexpected super property access $semantics.");
+          break;
       }
-      target = semantics.element;
+      registry.registerSendStructure(node,
+          isIncompatibleInvoke
+              ? new IncompatibleInvokeStructure(semantics, selector)
+              : new InvokeStructure(semantics, selector));
+    } else {
+      switch (semantics.kind) {
+        case AccessKind.SUPER_METHOD:
+          // TODO(johnniwinther): Method this should be registered as a
+          // closurization.
+          registry.registerStaticUse(semantics.element);
+          break;
+        case AccessKind.SUPER_FIELD:
+        case AccessKind.SUPER_FINAL_FIELD:
+        case AccessKind.SUPER_GETTER:
+          registry.registerStaticUse(semantics.element);
+          break;
+        case AccessKind.SUPER_SETTER:
+        case AccessKind.UNRESOLVED_SUPER:
+          // NoSuchMethod registered in [computeSuperSemantics].
+          break;
+        case AccessKind.INVALID:
+          // 'super' is not allowed.
+          break;
+        default:
+          internalError(node, "Unexpected super property access $semantics.");
+          break;
+      }
+      registry.registerSendStructure(node,
+          new GetStructure(semantics, selector));
     }
+    target = semantics.element;
 
     // TODO(johnniwinther): Remove these when all information goes through
     // the [SendStructure].
@@ -1979,11 +2117,14 @@
       Name name,
       PrefixElement prefix) {
     if ((ElementCategory.PREFIX & allowedCategory) == 0) {
-      compiler.reportError(
+      ErroneousElement error = reportAndCreateErroneousElement(
           node,
+          name.text,
           MessageKind.PREFIX_AS_EXPRESSION,
-          {'prefix': name});
-      return const NoneResult();
+          {'prefix': name},
+          isError: true);
+      return handleErroneousAccess(
+          node, name, error, new StaticAccess.invalid(error));
     }
     if (prefix.isDeferred) {
       // TODO(johnniwinther): Remove this when deferred access is detected
@@ -2062,8 +2203,7 @@
         name.text,
         MessageKind.THIS_PROPERTY, {},
         isError: true);
-    // TODO(johnniwinther): Support `this` as property as an [AccessSemantics].
-    AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
+    AccessSemantics accessSemantics = new StaticAccess.invalid(error);
     return handleErroneousAccess(node, name, error, accessSemantics);
   }
 
@@ -2534,7 +2674,209 @@
     return cls.computeType(compiler);
   }
 
+  /// Handle index operations like `a[b] = c`, `a[b] += c`, and `a[b]++`.
+  ResolutionResult handleIndexSendSet(SendSet node) {
+    String operatorText = node.assignmentOperator.source;
+    Node receiver = node.receiver;
+    Node index = node.arguments.head;
+    visitExpression(receiver);
+    visitExpression(index);
+    if (node.isPrefix || node.isPostfix) {
+      // `a[b]++` or `++a[b]`.
+      IncDecOperator operator = IncDecOperator.parse(operatorText);
+      AccessSemantics semantics = new DynamicAccess.dynamicProperty(receiver);
+      Selector getterSelector = new Selector.index();
+      Selector setterSelector = new Selector.indexSet();
+      Selector operatorSelector =
+          new Selector.binaryOperator(operator.selectorName);
+
+      // TODO(johnniwinther): Remove these when selectors are only accessed
+      // through the send structure.
+      registry.setGetterSelectorInComplexSendSet(node, getterSelector);
+      registry.setSelector(node, setterSelector);
+      registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);
+
+      registry.registerDynamicInvocation(
+          new UniverseSelector(getterSelector, null));
+      registry.registerDynamicInvocation(
+          new UniverseSelector(setterSelector, null));
+      registry.registerDynamicInvocation(
+          new UniverseSelector(operatorSelector, null));
+
+      SendStructure sendStructure = node.isPrefix
+          ? new IndexPrefixStructure(
+              semantics, operator, getterSelector, setterSelector)
+          : new IndexPostfixStructure(
+              semantics, operator, getterSelector, setterSelector);
+      registry.registerSendStructure(node, sendStructure);
+      return const NoneResult();
+    } else {
+      Node rhs = node.arguments.tail.head;
+      visitExpression(rhs);
+
+      AssignmentOperator operator = AssignmentOperator.parse(operatorText);
+      if (operator.kind == AssignmentOperatorKind.ASSIGN) {
+        // `a[b] = c`.
+        AccessSemantics semantics = new DynamicAccess.dynamicProperty(receiver);
+        Selector setterSelector = new Selector.indexSet();
+
+        // TODO(johnniwinther): Remove this when selectors are only accessed
+        // through the send structure.
+        registry.setSelector(node, setterSelector);
+        registry.registerDynamicInvocation(
+            new UniverseSelector(setterSelector, null));
+
+        SendStructure sendStructure =
+            new IndexSetStructure(semantics, setterSelector);
+        registry.registerSendStructure(node, sendStructure);
+        return const NoneResult();
+      } else {
+        // `a[b] += c`.
+        AccessSemantics semantics = new DynamicAccess.dynamicProperty(receiver);
+        Selector getterSelector = new Selector.index();
+        Selector setterSelector = new Selector.indexSet();
+        Selector operatorSelector =
+            new Selector.binaryOperator(operator.selectorName);
+
+        // TODO(johnniwinther): Remove these when selectors are only accessed
+        // through the send structure.
+        registry.setGetterSelectorInComplexSendSet(node, getterSelector);
+        registry.setSelector(node, setterSelector);
+        registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);
+
+        registry.registerDynamicInvocation(
+            new UniverseSelector(getterSelector, null));
+        registry.registerDynamicInvocation(
+            new UniverseSelector(setterSelector, null));
+        registry.registerDynamicInvocation(
+            new UniverseSelector(operatorSelector, null));
+
+        SendStructure sendStructure = new CompoundIndexSetStructure(
+                semantics, operator, getterSelector, setterSelector);
+        registry.registerSendStructure(node, sendStructure);
+        return const NoneResult();
+      }
+    }
+  }
+
+  /// Handle super index operations like `super[a] = b`, `super[a] += b`, and
+  /// `super[a]++`.
+  // TODO(johnniwinther): Share code with [handleIndexSendSet].
+  ResolutionResult handleSuperIndexSendSet(SendSet node) {
+    String operatorText = node.assignmentOperator.source;
+    Node index = node.arguments.head;
+    visitExpression(index);
+    AccessSemantics semantics = checkSuperAccess(node);
+    if (node.isPrefix || node.isPostfix) {
+      // `super[a]++` or `++super[a]`.
+      IncDecOperator operator = IncDecOperator.parse(operatorText);
+      Selector getterSelector = new Selector.index();
+      Selector setterSelector = new Selector.indexSet();
+      Selector operatorSelector =
+          new Selector.binaryOperator(operator.selectorName);
+
+      // TODO(johnniwinther): Remove these when selectors are only accessed
+      // through the send structure.
+      registry.setGetterSelectorInComplexSendSet(node, getterSelector);
+      registry.setSelector(node, setterSelector);
+      registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);
+
+      if (semantics == null) {
+        semantics = computeSuperAccessSemanticsForSelectors(
+            node, getterSelector, setterSelector);
+
+        registry.registerStaticInvocation(semantics.getter);
+        registry.registerStaticInvocation(semantics.setter);
+
+        // TODO(johnniwinther): Remove these when elements are only accessed
+        // through the send structure.
+        registry.useElement(node, semantics.setter);
+        registry.useElement(node.selector, semantics.getter);
+      }
+      registry.registerDynamicInvocation(
+          new UniverseSelector(operatorSelector, null));
+
+      SendStructure sendStructure = node.isPrefix
+          ? new IndexPrefixStructure(
+              semantics, operator, getterSelector, setterSelector)
+          : new IndexPostfixStructure(
+              semantics, operator, getterSelector, setterSelector);
+      registry.registerSendStructure(node, sendStructure);
+      return const NoneResult();
+    } else {
+      Node rhs = node.arguments.tail.head;
+      visitExpression(rhs);
+
+      AssignmentOperator operator = AssignmentOperator.parse(operatorText);
+      if (operator.kind == AssignmentOperatorKind.ASSIGN) {
+        // `super[a] = b`.
+        Selector setterSelector = new Selector.indexSet();
+        if (semantics == null) {
+          semantics =
+              computeSuperAccessSemanticsForSelector(node, setterSelector);
+
+          // TODO(johnniwinther): Remove these when elements are only accessed
+          // through the send structure.
+          registry.useElement(node, semantics.setter);
+        }
+
+        // TODO(johnniwinther): Remove this when selectors are only accessed
+        // through the send structure.
+        registry.setSelector(node, setterSelector);
+        registry.registerStaticInvocation(semantics.setter);
+
+        SendStructure sendStructure =
+            new IndexSetStructure(semantics, setterSelector);
+        registry.registerSendStructure(node, sendStructure);
+        return const NoneResult();
+      } else {
+        // `super[a] += b`.
+        Selector getterSelector = new Selector.index();
+        Selector setterSelector = new Selector.indexSet();
+        Selector operatorSelector =
+            new Selector.binaryOperator(operator.selectorName);
+        if (semantics == null) {
+          semantics = computeSuperAccessSemanticsForSelectors(
+              node, getterSelector, setterSelector);
+
+          registry.registerStaticInvocation(semantics.getter);
+          registry.registerStaticInvocation(semantics.setter);
+
+          // TODO(johnniwinther): Remove these when elements are only accessed
+          // through the send structure.
+          registry.useElement(node, semantics.setter);
+          registry.useElement(node.selector, semantics.getter);
+        }
+
+        // TODO(johnniwinther): Remove these when selectors are only accessed
+        // through the send structure.
+        registry.setGetterSelectorInComplexSendSet(node, getterSelector);
+        registry.setSelector(node, setterSelector);
+        registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);
+
+        registry.registerDynamicInvocation(
+            new UniverseSelector(operatorSelector, null));
+
+        SendStructure sendStructure = new CompoundIndexSetStructure(
+                semantics, operator, getterSelector, setterSelector);
+        registry.registerSendStructure(node, sendStructure);
+        return const NoneResult();
+      }
+    }
+  }
+
   ResolutionResult visitSendSet(SendSet node) {
+    if (node.isIndex) {
+      if (node.isSuperCall) {
+        return handleSuperIndexSendSet(node);
+      } else {
+        return handleIndexSendSet(node);
+      }
+    }
+    return oldVisitSendSet(node);
+  }
+
+  ResolutionResult oldVisitSendSet(SendSet node) {
     bool oldSendIsMemberAccess = sendIsMemberAccess;
     sendIsMemberAccess = node.isPropertyAccess || node.isCall;
     ResolutionResult result = resolveSend(node);
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 1f3e943..36c4618 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -398,11 +398,13 @@
   void registerIsCheck(DartType type) {
     worldImpact.registerCheckedType(type);
     backend.resolutionCallbacks.onIsCheck(type, this);
+    mapping.addRequiredType(type);
   }
 
   void registerAsCheck(DartType type) {
     registerIsCheck(type);
     backend.resolutionCallbacks.onAsCheck(type, this);
+    mapping.addRequiredType(type);
   }
 
   void registerClosure(LocalFunctionElement element) {
@@ -480,6 +482,7 @@
 
   void registerInstantiatedType(InterfaceType type) {
     world.registerInstantiatedType(type, this);
+    mapping.addRequiredType(type);
   }
 
   void registerAbstractClassInstantiation() {
@@ -492,6 +495,7 @@
 
   void registerRequiredType(DartType type, Element enclosingElement) {
     backend.registerRequiredType(type, enclosingElement);
+    mapping.addRequiredType(type);
   }
 
   void registerStringInterpolation() {
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 3c265cc..d54b68a 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -141,6 +141,7 @@
   /// Read of the [parameter].
   ///
   /// For instance:
+  ///
   ///     m(parameter) => parameter;
   ///
   R visitParameterGet(
@@ -151,6 +152,7 @@
   /// Assignment of [rhs] to the [parameter].
   ///
   /// For instance:
+  ///
   ///     m(parameter) {
   ///       parameter = rhs;
   ///     }
@@ -164,6 +166,7 @@
   /// Assignment of [rhs] to the final [parameter].
   ///
   /// For instance:
+  ///
   ///     m(final parameter) {
   ///       parameter = rhs;
   ///     }
@@ -177,6 +180,7 @@
   /// Invocation of the [parameter] with [arguments].
   ///
   /// For instance:
+  ///
   ///     m(parameter) {
   ///       parameter(null, 42);
   ///     }
@@ -191,6 +195,7 @@
   /// Read of the local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       var variable;
   ///       return variable;
@@ -204,6 +209,7 @@
   /// Assignment of [rhs] to the local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       var variable;
   ///       variable = rhs;
@@ -218,6 +224,7 @@
   /// Assignment of [rhs] to the final local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       final variable = null;
   ///       variable = rhs;
@@ -232,6 +239,7 @@
   /// Invocation of the local variable [variable] with [arguments].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       var variable;
   ///       variable(null, 42);
@@ -247,6 +255,7 @@
   /// Closurization of the local [function].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       o(a, b) {}
   ///       return o;
@@ -260,6 +269,7 @@
   /// Assignment of [rhs] to the local [function].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       o(a, b) {}
   ///       o = rhs;
@@ -274,6 +284,7 @@
   /// Invocation of the local [function] with [arguments].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       o(a, b) {}
   ///       return o(null, 42);
@@ -289,6 +300,7 @@
   /// Invocation of the local [function] with incompatible [arguments].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       o(a) {}
   ///       return o(null, 42);
@@ -303,7 +315,8 @@
 
   /// Getter call on [receiver] of the property defined by [selector].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(receiver) => receiver.foo;
   ///
   R visitDynamicPropertyGet(
@@ -315,7 +328,8 @@
   /// Conditional (if not null) getter call on [receiver] of the property
   /// defined by [selector].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(receiver) => receiver?.foo;
   ///
   R visitIfNotNullDynamicPropertyGet(
@@ -327,7 +341,8 @@
   /// Setter call on [receiver] with argument [rhs] of the property defined by
   /// [selector].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(receiver) {
   ///       receiver.foo = rhs;
   ///     }
@@ -342,7 +357,8 @@
   /// Conditional (if not null) setter call on [receiver] with argument [rhs] of
   /// the property defined by [selector].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(receiver) {
   ///       receiver?.foo = rhs;
   ///     }
@@ -357,7 +373,8 @@
   /// Invocation of the property defined by [selector] on [receiver] with
   /// [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(receiver) {
   ///       receiver.foo(null, 42);
   ///     }
@@ -372,7 +389,8 @@
   /// Conditinal invocation of the property defined by [selector] on [receiver]
   /// with [arguments], if [receiver] is not null.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(receiver) {
   ///       receiver?.foo(null, 42);
   ///     }
@@ -386,7 +404,8 @@
 
   /// Getter call on `this` of the property defined by [selector].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       m() => this.foo;
   ///     }
@@ -404,6 +423,9 @@
 
   /// Setter call on `this` with argument [rhs] of the property defined by
   /// [selector].
+  ///
+  /// For instance:
+  ///
   ///     class C {
   ///       m() { this.foo = rhs; }
   ///     }
@@ -423,7 +445,8 @@
   /// Invocation of the property defined by [selector] on `this` with
   /// [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       m() { this.foo(null, 42); }
   ///     }
@@ -443,7 +466,8 @@
 
   /// Read of `this`.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       m() => this;
   ///     }
@@ -454,7 +478,8 @@
 
   /// Invocation of `this` with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       m() => this(null, 42);
   ///     }
@@ -468,7 +493,8 @@
 
   /// Read of the super [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       var foo;
   ///     }
@@ -483,7 +509,8 @@
 
   /// Assignment of [rhs] to the super [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       var foo;
   ///     }
@@ -499,7 +526,8 @@
 
   /// Assignment of [rhs] to the final static [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       final foo = null;
   ///     }
@@ -515,7 +543,8 @@
 
   /// Invocation of the super [field] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       var foo;
   ///     }
@@ -532,7 +561,8 @@
 
   /// Closurization of the super [method].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       foo(a, b) {}
   ///     }
@@ -547,7 +577,8 @@
 
   /// Invocation of the super [method] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       foo(a, b) {}
   ///     }
@@ -564,7 +595,8 @@
 
   /// Invocation of the super [method] with incompatible [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       foo(a, b) {}
   ///     }
@@ -581,7 +613,8 @@
 
   /// Assignment of [rhs] to the super [method].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       foo(a, b) {}
   ///     }
@@ -597,7 +630,8 @@
 
   /// Getter call to the super [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       get foo => null;
   ///     }
@@ -612,7 +646,8 @@
 
   /// Getter call the super [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       set foo(_) {}
   ///     }
@@ -627,7 +662,8 @@
 
   /// Setter call to the super [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       set foo(_) {}
   ///     }
@@ -643,7 +679,8 @@
 
   /// Assignment of [rhs] to the super [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       get foo => null;
   ///     }
@@ -659,7 +696,8 @@
 
   /// Invocation of the super [getter] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       get foo => null;
   ///     }
@@ -676,7 +714,8 @@
 
   /// Invocation of the super [setter] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       set foo(_) {}
   ///     }
@@ -693,7 +732,8 @@
 
   /// Invocation of a [expression] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() => (a, b){}(null, 42);
   ///
   R visitExpressionInvoke(
@@ -705,7 +745,8 @@
 
   /// Read of the static [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static var foo;
   ///     }
@@ -718,7 +759,8 @@
 
   /// Assignment of [rhs] to the static [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static var foo;
   ///     }
@@ -732,7 +774,8 @@
 
   /// Assignment of [rhs] to the final static [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static final foo;
   ///     }
@@ -746,7 +789,8 @@
 
   /// Invocation of the static [field] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static var foo;
   ///     }
@@ -761,7 +805,8 @@
 
   /// Closurization of the static [function].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static foo(a, b) {}
   ///     }
@@ -774,7 +819,8 @@
 
   /// Invocation of the static [function] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static foo(a, b) {}
   ///     }
@@ -789,7 +835,8 @@
 
   /// Invocation of the static [function] with incompatible [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static foo(a, b) {}
   ///     }
@@ -804,7 +851,8 @@
 
   /// Assignment of [rhs] to the static [function].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static foo(a, b) {}
   ///     }
@@ -818,7 +866,8 @@
 
   /// Getter call to the static [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static get foo => null;
   ///     }
@@ -831,7 +880,8 @@
 
   /// Getter call the static [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static set foo(_) {}
   ///     }
@@ -844,7 +894,8 @@
 
   /// Setter call to the static [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static set foo(_) {}
   ///     }
@@ -858,7 +909,8 @@
 
   /// Assignment of [rhs] to the static [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static get foo => null;
   ///     }
@@ -872,7 +924,8 @@
 
   /// Invocation of the static [getter] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static get foo => null;
   ///     }
@@ -887,7 +940,8 @@
 
   /// Invocation of the static [setter] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static set foo(_) {}
   ///     }
@@ -902,7 +956,8 @@
 
   /// Read of the top level [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     var foo;
   ///     m() => foo;
   ///
@@ -913,7 +968,8 @@
 
   /// Assignment of [rhs] to the top level [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     var foo;
   ///     m() { foo = rhs; }
   ///
@@ -925,7 +981,8 @@
 
   /// Assignment of [rhs] to the final top level [field].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     final foo = null;
   ///     m() { foo = rhs; }
   ///
@@ -937,7 +994,8 @@
 
   /// Invocation of the top level [field] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     var foo;
   ///     m() { foo(null, 42); }
   ///
@@ -950,7 +1008,8 @@
 
   /// Closurization of the top level [function].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     foo(a, b) {};
   ///     m() => foo;
   ///
@@ -961,7 +1020,8 @@
 
   /// Invocation of the top level [function] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     foo(a, b) {};
   ///     m() { foo(null, 42); }
   ///
@@ -974,7 +1034,8 @@
 
   /// Invocation of the top level [function] with incompatible [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static foo(a, b) {}
   ///     }
@@ -989,7 +1050,8 @@
 
   /// Assignment of [rhs] to the top level [function].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     foo(a, b) {};
   ///     m() { foo = rhs; }
   ///
@@ -1001,7 +1063,8 @@
 
   /// Getter call to the top level [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get foo => null;
   ///     m() => foo;
   ///
@@ -1012,7 +1075,8 @@
 
   /// Getter call the top level [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set foo(_) {}
   ///     m() => foo;
   ///
@@ -1023,7 +1087,8 @@
 
   /// Setter call to the top level [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set foo(_) {}
   ///     m() { foo = rhs; }
   ///
@@ -1035,7 +1100,8 @@
 
   /// Assignment of [rhs] to the top level [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get foo => null;
   ///     m() { foo = rhs; }
   ///
@@ -1047,7 +1113,8 @@
 
   /// Invocation of the top level [getter] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get foo => null;
   ///     m() { foo(null, 42); }
   ///
@@ -1060,7 +1127,8 @@
 
   /// Invocation of the top level [setter] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set foo(_) {};
   ///     m() { foo(null, 42); }
   ///
@@ -1073,7 +1141,8 @@
 
   /// Read of the type literal for class [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m() => C;
   ///
@@ -1084,7 +1153,8 @@
 
   /// Invocation of the type literal for class [element] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m() => C(null, 42);
   ///
@@ -1097,7 +1167,8 @@
 
   /// Assignment of [rhs] to the type literal for class [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m() { C = rhs; }
   ///
@@ -1109,7 +1180,8 @@
 
   /// Read of the type literal for typedef [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     typedef F();
   ///     m() => F;
   ///
@@ -1120,7 +1192,8 @@
 
   /// Invocation of the type literal for typedef [element] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     typedef F();
   ///     m() => F(null, 42);
   ///
@@ -1133,7 +1206,8 @@
 
   /// Assignment of [rhs] to the type literal for typedef [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     typedef F();
   ///     m() { F = rhs; }
   ///
@@ -1145,7 +1219,8 @@
 
   /// Read of the type literal for type variable [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C<T> {
   ///       m() => T;
   ///     }
@@ -1158,7 +1233,8 @@
   /// Invocation of the type literal for type variable [element] with
   /// [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C<T> {
   ///       m() { T(null, 42); }
   ///     }
@@ -1172,7 +1248,8 @@
 
   /// Assignment of [rhs] to the type literal for type variable [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C<T> {
   ///       m() { T = rhs; }
   ///     }
@@ -1185,7 +1262,8 @@
 
   /// Read of the type literal for `dynamic`.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() => dynamic;
   ///
   R visitDynamicTypeLiteralGet(
@@ -1195,7 +1273,8 @@
 
   /// Invocation of the type literal for `dynamic` with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() { dynamic(null, 42); }
   ///
   R visitDynamicTypeLiteralInvoke(
@@ -1207,7 +1286,8 @@
 
   /// Assignment of [rhs] to the type literal for `dynamic`.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() { dynamic = rhs; }
   ///
   R visitDynamicTypeLiteralSet(
@@ -1219,6 +1299,7 @@
   /// Call to `assert` with [expression] as the condition.
   ///
   /// For instance:
+  ///
   ///     m() { assert(expression); }
   ///
   R visitAssert(
@@ -1229,8 +1310,11 @@
   /// Call to `assert` with the wrong number of [arguments].
   ///
   /// For instance:
+  ///
   ///     m() { assert(); }
+  ///
   /// or
+  ///
   ///     m() { assert(expression1, expression2); }
   ///
   R errorInvalidAssert(
@@ -1243,6 +1327,7 @@
   /// by [visitEquals] and index operations `a[b]` are handled by [visitIndex].
   ///
   /// For instance:
+  ///
   ///     add(a, b) => a + b;
   ///     sub(a, b) => a - b;
   ///     mul(a, b) => a * b;
@@ -1259,6 +1344,7 @@
   /// expressions using operator `==` are handled by [visitSuperEquals].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator +(_) => null;
   ///     }
@@ -1275,7 +1361,8 @@
 
   /// Binary operation on the unresolved super [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -1292,6 +1379,7 @@
   /// Index expression `receiver[index]`.
   ///
   /// For instance:
+  ///
   ///     lookup(a, b) => a[b];
   ///
   R visitIndex(
@@ -1304,6 +1392,7 @@
   /// the operation is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     lookup(a, b) => --a[b];
   ///
   R visitIndexPrefix(
@@ -1317,6 +1406,7 @@
   /// the operation is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     lookup(a, b) => a[b]++;
   ///
   R visitIndexPostfix(
@@ -1330,6 +1420,7 @@
   /// superclass by [function].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => null;
   ///     }
@@ -1346,6 +1437,7 @@
   /// Index expression `super[index]` where 'operator []' is unresolved.
   ///
   /// For instance:
+  ///
   ///     class B {}
   ///     class C extends B {
   ///       m(a) => super[a];
@@ -1363,6 +1455,7 @@
   /// is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => null;
   ///       operator []=(a, b) {}
@@ -1385,6 +1478,7 @@
   /// is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => null;
   ///       operator []=(a, b) {}
@@ -1406,6 +1500,7 @@
   /// the operation is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator []=(a, b) {}
   ///     }
@@ -1426,6 +1521,7 @@
   /// the operation is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator []=(a, b) {}
   ///     }
@@ -1446,6 +1542,7 @@
   /// 'operator []=' is unresolved and the operation is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => 42;
   ///     }
@@ -1466,6 +1563,7 @@
   /// 'operator []=' is unresolved and the operation is defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => 42;
   ///     }
@@ -1486,6 +1584,7 @@
   /// defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => 42;
   ///     }
@@ -1505,6 +1604,7 @@
   /// defined by [operator].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](_) => 42;
   ///     }
@@ -1522,6 +1622,7 @@
   /// Binary expression `left == right`.
   ///
   /// For instance:
+  ///
   ///     neq(a, b) => a != b;
   ///
   R visitNotEquals(
@@ -1534,6 +1635,7 @@
   /// superclass by [function].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator +(_) => null;
   ///     }
@@ -1550,6 +1652,7 @@
   /// Binary expression `left == right`.
   ///
   /// For instance:
+  ///
   ///     eq(a, b) => a == b;
   ///
   R visitEquals(
@@ -1562,6 +1665,7 @@
   /// superclass by [function].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator ==(_) => null;
   ///     }
@@ -1579,6 +1683,7 @@
   /// definable operator.
   ///
   /// For instance:
+  ///
   ///     neg(a, b) => -a;
   ///     comp(a, b) => ~a;
   ///
@@ -1592,6 +1697,7 @@
   /// operator implemented on a superclass by [function].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator -() => null;
   ///     }
@@ -1607,7 +1713,8 @@
 
   /// Unary operation on the unresolved super [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -1623,6 +1730,7 @@
   /// Unary expression `!expression`.
   ///
   /// For instance:
+  ///
   ///     not(a) => !a;
   ///
   R visitNot(
@@ -1633,6 +1741,7 @@
   /// Index set expression `receiver[index] = rhs`.
   ///
   /// For instance:
+  ///
   ///     m(receiver, index, rhs) => receiver[index] = rhs;
   ///
   R visitIndexSet(
@@ -1646,6 +1755,7 @@
   /// on a superclass by [function].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator []=(a, b) {}
   ///     }
@@ -1663,7 +1773,8 @@
   /// Index set expression `super[index] = rhs` where `operator []=` is
   /// undefined.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -1679,7 +1790,8 @@
 
   /// If-null, ??, expression with operands [left] and [right].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() => left ?? right;
   ///
   R visitIfNull(
@@ -1690,7 +1802,8 @@
 
   /// Logical and, &&, expression with operands [left] and [right].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() => left && right;
   ///
   R visitLogicalAnd(
@@ -1701,7 +1814,8 @@
 
   /// Logical or, ||, expression with operands [left] and [right].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m() => left || right;
   ///
   R visitLogicalOr(
@@ -1712,7 +1826,8 @@
 
   /// Is test of [expression] against [type].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m() => expression is C;
   ///
@@ -1724,7 +1839,8 @@
 
   /// Is not test of [expression] against [type].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m() => expression is! C;
   ///
@@ -1736,7 +1852,8 @@
 
   /// As cast of [expression] to [type].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m() => expression as C;
   ///
@@ -1751,6 +1868,7 @@
   /// [setterSelector], respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver, rhs) => receiver.foo += rhs;
   ///
   R visitDynamicPropertyCompound(
@@ -1767,6 +1885,7 @@
   /// [getterSelector] and [setterSelector], respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver, rhs) => receiver?.foo += rhs;
   ///
   R visitIfNotNullDynamicPropertyCompound(
@@ -1783,10 +1902,13 @@
   /// [setterSelector], respectively.
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       m(rhs) => this.foo += rhs;
   ///     }
+  ///
   /// or
+  ///
   ///     class C {
   ///       m(rhs) => foo += rhs;
   ///     }
@@ -1802,6 +1924,7 @@
   /// Compound assignment expression of [rhs] with [operator] on a [parameter].
   ///
   /// For instance:
+  ///
   ///     m(parameter, rhs) => parameter += rhs;
   ///
   R visitParameterCompound(
@@ -1815,6 +1938,7 @@
   /// [parameter].
   ///
   /// For instance:
+  ///
   ///     m(final parameter, rhs) => parameter += rhs;
   ///
   R visitFinalParameterCompound(
@@ -1828,6 +1952,7 @@
   /// [variable].
   ///
   /// For instance:
+  ///
   ///     m(rhs) {
   ///       var variable;
   ///       variable += rhs;
@@ -1844,6 +1969,7 @@
   /// [variable].
   ///
   /// For instance:
+  ///
   ///     m(rhs) {
   ///       final variable = 0;
   ///       variable += rhs;
@@ -1860,6 +1986,7 @@
   /// [function].
   ///
   /// For instance:
+  ///
   ///     m(rhs) {
   ///       function() {}
   ///       function += rhs;
@@ -1876,6 +2003,7 @@
   /// [field].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static var field;
   ///       m(rhs) => field += rhs;
@@ -1892,6 +2020,7 @@
   /// [field].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static final field = 0;
   ///       m(rhs) => field += rhs;
@@ -1908,6 +2037,7 @@
   /// static [getter] and writing to a static [setter].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static get o => 0;
   ///       static set o(_) {}
@@ -1927,6 +2057,7 @@
   /// [setter].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static o() {}
   ///       static set o(_) {}
@@ -1945,6 +2076,7 @@
   /// [field].
   ///
   /// For instance:
+  ///
   ///     var field;
   ///     m(rhs) => field += rhs;
   ///
@@ -1959,6 +2091,7 @@
   /// level [field].
   ///
   /// For instance:
+  ///
   ///     final field = 0;
   ///     m(rhs) => field += rhs;
   ///
@@ -1973,6 +2106,7 @@
   /// top level [getter] and writing to a top level [setter].
   ///
   /// For instance:
+  ///
   ///     get o => 0;
   ///     set o(_) {}
   ///     m(rhs) => o += rhs;
@@ -1990,6 +2124,7 @@
   /// level [setter].
   ///
   /// For instance:
+  ///
   ///     o() {}
   ///     set o(_) {}
   ///     m(rhs) => o += rhs;
@@ -2007,6 +2142,7 @@
   /// unresolved setter.
   ///
   /// For instance:
+  ///
   ///     o() {}
   ///     m(rhs) => o += rhs;
   ///
@@ -2021,6 +2157,7 @@
   /// [field].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       var field;
   ///     }
@@ -2039,6 +2176,7 @@
   /// [field].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       final field = 42;
   ///     }
@@ -2056,6 +2194,7 @@
   /// Prefix expression with [operator] on a final super [field].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       final field = 42;
   ///     }
@@ -2072,6 +2211,7 @@
   /// Prefix expression with [operator] on an unresolved super property.
   ///
   /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -2087,6 +2227,7 @@
   /// Postfix expression with [operator] on an unresolved super property.
   ///
   /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -2103,6 +2244,7 @@
   /// super property.
   ///
   /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -2119,6 +2261,7 @@
   /// Postfix expression with [operator] on a final super [field].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       final field = 42;
   ///     }
@@ -2137,6 +2280,7 @@
   /// [writtenField].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -2159,6 +2303,7 @@
   /// super [getter] and writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       get o => 0;
   ///       set o(_) {}
@@ -2180,6 +2325,7 @@
   /// [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       o() {}
   ///       set o(_) {}
@@ -2200,6 +2346,7 @@
   /// closurized super [method] and trying to invoke the non-existing setter.
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       o() {}
   ///     }
@@ -2217,7 +2364,8 @@
   /// Compound assignment expression of [rhs] with [operator] reading from the
   /// non-existing super getter and writing to a super [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       set o(_) {}
   ///     }
@@ -2236,7 +2384,8 @@
   /// Compound assignment expression of [rhs] with [operator] reading from a
   /// super [getter] and writing to the non-existing super setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       get o => 42;
   ///     }
@@ -2256,6 +2405,7 @@
   /// super [field] and writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var o;
   ///     }
@@ -2278,6 +2428,7 @@
   /// super [getter] and writing to a super [field].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var o;
   ///     }
@@ -2300,6 +2451,7 @@
   /// for class [element].
   ///
   /// For instance:
+  ///
   ///     class C {}
   ///     m(rhs) => C += rhs;
   ///
@@ -2314,6 +2466,7 @@
   /// for typedef [element].
   ///
   /// For instance:
+  ///
   ///     typedef F();
   ///     m(rhs) => F += rhs;
   ///
@@ -2328,6 +2481,7 @@
   /// for type variable [element].
   ///
   /// For instance:
+  ///
   ///     class C<T> {
   ///       m(rhs) => T += rhs;
   ///     }
@@ -2343,6 +2497,7 @@
   /// literal for `dynamic`.
   ///
   /// For instance:
+  ///
   ///     m(rhs) => dynamic += rhs;
   ///
   R visitDynamicTypeLiteralCompound(
@@ -2357,6 +2512,7 @@
   /// [getterSelector] and [setterSelector], respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver, index, rhs) => receiver[index] += rhs;
   ///
   R visitCompoundIndexSet(
@@ -2371,6 +2527,7 @@
   /// operators of a super class defined by [getter] and [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       operator [](index) {}
   ///       operator [](index, value) {}
@@ -2392,7 +2549,8 @@
   /// super class where the index getter is undefined and the index setter is
   /// defined by [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -2412,7 +2570,8 @@
   /// super class where the index getter is defined by [getter] but the index
   /// setter is undefined.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       operator [](index) => 42;
   ///     }
@@ -2432,7 +2591,8 @@
   /// Compound index assignment of [rhs] with [operator] to [index] on a super
   /// super class where the index getter and setter are undefined.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///     }
   ///     class C extends B {
@@ -2452,6 +2612,7 @@
   /// respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver) => ++receiver.foo;
   ///
   R visitDynamicPropertyPrefix(
@@ -2467,6 +2628,7 @@
   /// [setterSelector], respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver) => ++receiver?.foo;
   ///
   R visitIfNotNullDynamicPropertyPrefix(
@@ -2480,6 +2642,7 @@
   /// Prefix expression with [operator] on a [parameter].
   ///
   /// For instance:
+  ///
   ///     m(parameter) => ++parameter;
   ///
   R visitParameterPrefix(
@@ -2491,6 +2654,7 @@
   /// Prefix expression with [operator] on a final [parameter].
   ///
   /// For instance:
+  ///
   ///     m(final parameter) => ++parameter;
   ///
   R visitFinalParameterPrefix(
@@ -2502,9 +2666,10 @@
   /// Prefix expression with [operator] on a local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
-  ///     var variable;
-  ///      ++variable;
+  ///       var variable;
+  ///       ++variable;
   ///     }
   ///
   R visitLocalVariablePrefix(
@@ -2516,9 +2681,10 @@
   /// Prefix expression with [operator] on a final local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
-  ///     final variable;
-  ///      ++variable;
+  ///       final variable;
+  ///       ++variable;
   ///     }
   ///
   R visitFinalLocalVariablePrefix(
@@ -2530,9 +2696,10 @@
   /// Prefix expression with [operator] on a local [function].
   ///
   /// For instance:
+  ///
   ///     m() {
-  ///     function() {}
-  ///      ++function;
+  ///       function() {}
+  ///       ++function;
   ///     }
   ///
   R visitLocalFunctionPrefix(
@@ -2547,10 +2714,13 @@
   /// respectively.
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       m() => ++foo;
   ///     }
+  ///
   /// or
+  ///
   ///     class C {
   ///       m() => ++this.foo;
   ///     }
@@ -2565,6 +2735,7 @@
   /// Prefix expression with [operator] on a static [field].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static var field;
   ///       m() => ++field;
@@ -2579,6 +2750,7 @@
   /// Prefix expression with [operator] on a final static [field].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static final field = 42;
   ///       m() => ++field;
@@ -2594,6 +2766,7 @@
   /// writing to a static [setter].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static get o => 0;
   ///       static set o(_) {}
@@ -2612,6 +2785,7 @@
   /// closurizing [method], and writing to a static [setter].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static o() {}
   ///       static set o(_) {}
@@ -2628,6 +2802,7 @@
   /// Prefix expression with [operator] on a top level [field].
   ///
   /// For instance:
+  ///
   ///     var field;
   ///     m() => ++field;
   ///
@@ -2640,6 +2815,7 @@
   /// Prefix expression with [operator] on a final top level [field].
   ///
   /// For instance:
+  ///
   ///     final field;
   ///     m() => ++field;
   ///
@@ -2653,6 +2829,7 @@
   /// writing to a top level [setter].
   ///
   /// For instance:
+  ///
   ///     get o => 0;
   ///     set o(_) {}
   ///     m() => ++o;
@@ -2668,6 +2845,7 @@
   /// is, closurizing [method], and writing to a top level [setter].
   ///
   /// For instance:
+  ///
   ///     o() {}
   ///     set o(_) {}
   ///     m() => ++o;
@@ -2682,6 +2860,7 @@
   /// Prefix expression with [operator] on a super [field].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       var field;
   ///     }
@@ -2699,6 +2878,7 @@
   /// and writing to the different super field [writtenField].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -2720,6 +2900,7 @@
   /// to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -2742,6 +2923,7 @@
   /// writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       get field => 0;
   ///       set field(_) {}
@@ -2761,6 +2943,7 @@
   /// writing to a super [field].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -2782,6 +2965,7 @@
   /// closurizing [method], and writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       o() {}
   ///       set o(_) {}
@@ -2801,6 +2985,7 @@
   /// closurizing [method], and writing to an unresolved super setter.
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       o() {}
   ///       set o(_) {}
@@ -2818,7 +3003,8 @@
   /// Prefix expression with [operator] reading from an unresolved super getter
   /// and writing to a super [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       set o(_) {}
   ///     }
@@ -2837,7 +3023,8 @@
   /// Prefix expression with [operator] reading from a super [getter] and
   /// writing to an unresolved super setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       get o => 42
   ///     }
@@ -2856,6 +3043,7 @@
   /// Prefix expression with [operator] on a type literal for a class [element].
   ///
   /// For instance:
+  ///
   ///     class C {}
   ///     m() => ++C;
   ///
@@ -2869,6 +3057,7 @@
   /// [element].
   ///
   /// For instance:
+  ///
   ///     typedef F();
   ///     m() => ++F;
   ///
@@ -2882,6 +3071,7 @@
   /// [element].
   ///
   /// For instance:
+  ///
   ///     class C<T> {
   ///       m() => ++T;
   ///     }
@@ -2895,6 +3085,7 @@
   /// Prefix expression with [operator] on the type literal for `dynamic`.
   ///
   /// For instance:
+  ///
   ///     m() => ++dynamic;
   ///
   R visitDynamicTypeLiteralPrefix(
@@ -2908,6 +3099,7 @@
   /// respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver) => receiver.foo++;
   ///
   R visitDynamicPropertyPostfix(
@@ -2923,6 +3115,7 @@
   /// [setterSelector], respectively.
   ///
   /// For instance:
+  ///
   ///     m(receiver) => receiver?.foo++;
   ///
   R visitIfNotNullDynamicPropertyPostfix(
@@ -2936,6 +3129,7 @@
   /// Postfix expression with [operator] on a [parameter].
   ///
   /// For instance:
+  ///
   ///     m(parameter) => parameter++;
   ///
   R visitParameterPostfix(
@@ -2947,6 +3141,7 @@
   /// Postfix expression with [operator] on a final [parameter].
   ///
   /// For instance:
+  ///
   ///     m(final parameter) => parameter++;
   ///
   R visitFinalParameterPostfix(
@@ -2958,6 +3153,7 @@
   /// Postfix expression with [operator] on a local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       var variable;
   ///       variable++;
@@ -2972,6 +3168,7 @@
   /// Postfix expression with [operator] on a final local [variable].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///       final variable;
   ///       variable++;
@@ -2986,6 +3183,7 @@
   /// Postfix expression with [operator] on a local [function].
   ///
   /// For instance:
+  ///
   ///     m() {
   ///     function() {}
   ///      function++;
@@ -3003,10 +3201,13 @@
   /// respectively.
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       m() => foo++;
   ///     }
+  ///
   /// or
+  ///
   ///     class C {
   ///       m() => this.foo++;
   ///     }
@@ -3021,6 +3222,7 @@
   /// Postfix expression with [operator] on a static [field].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static var field;
   ///       m() => field++;
@@ -3035,6 +3237,7 @@
   /// Postfix expression with [operator] on a final static [field].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static final field;
   ///       m() => field++;
@@ -3050,6 +3253,7 @@
   /// writing to a static [setter].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static get o => 0;
   ///       static set o(_) {}
@@ -3068,6 +3272,7 @@
   /// is, closurizing [method], and writing to a static [setter].
   ///
   /// For instance:
+  ///
   ///     class C {
   ///       static o() {}
   ///       static set o(_) {}
@@ -3084,6 +3289,7 @@
   /// Postfix expression with [operator] on a top level [field].
   ///
   /// For instance:
+  ///
   ///     var field;
   ///     m() => field++;
   ///
@@ -3096,6 +3302,7 @@
   /// Postfix expression with [operator] on a final top level [field].
   ///
   /// For instance:
+  ///
   ///     final field = 42;
   ///     m() => field++;
   ///
@@ -3109,6 +3316,7 @@
   /// writing to a top level [setter].
   ///
   /// For instance:
+  ///
   ///     get o => 0;
   ///     set o(_) {}
   ///     m() => o++;
@@ -3124,6 +3332,7 @@
   /// is, closurizing [method], and writing to a top level [setter].
   ///
   /// For instance:
+  ///
   ///     o() {}
   ///     set o(_) {}
   ///     m() => o++;
@@ -3138,6 +3347,7 @@
   /// Postfix expression with [operator] on a super [field].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       var field;
   ///     }
@@ -3155,6 +3365,7 @@
   /// [readField] and writing to the different super field [writtenField].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -3176,6 +3387,7 @@
   /// writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -3198,6 +3410,7 @@
   /// writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       get field => 0;
   ///       set field(_) {}
@@ -3217,6 +3430,7 @@
   /// writing to a super [field].
   ///
   /// For instance:
+  ///
   ///     class A {
   ///       var field;
   ///     }
@@ -3238,6 +3452,7 @@
   /// closurizing [method], and writing to a super [setter].
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       o() {}
   ///       set o(_) {}
@@ -3257,6 +3472,7 @@
   /// closurizing [method], and writing to an unresolved super.
   ///
   /// For instance:
+  ///
   ///     class B {
   ///       o() {}
   ///       set o(_) {}
@@ -3274,7 +3490,8 @@
   /// Prefix expression with [operator] reading from an unresolved super getter
   /// and writing to a super [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       set o(_) {}
   ///     }
@@ -3293,7 +3510,8 @@
   /// Prefix expression with [operator] reading from a super [getter] and
   /// writing to an unresolved super setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {
   ///       get o => 42
   ///     }
@@ -3313,6 +3531,7 @@
   /// [element].
   ///
   /// For instance:
+  ///
   ///     class C {}
   ///     m() => C++;
   ///
@@ -3326,6 +3545,7 @@
   /// [element].
   ///
   /// For instance:
+  ///
   ///     typedef F();
   ///     m() => F++;
   ///
@@ -3339,6 +3559,7 @@
   /// [element].
   ///
   /// For instance:
+  ///
   ///     class C<T> {
   ///       m() => T++;
   ///     }
@@ -3352,6 +3573,7 @@
   /// Postfix expression with [operator] on the type literal for `dynamic`.
   ///
   /// For instance:
+  ///
   ///     m() => dynamic++;
   ///
   R visitDynamicTypeLiteralPostfix(
@@ -3362,7 +3584,8 @@
 
   /// Read of the [constant].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     const c = c;
   ///     m() => c;
   ///
@@ -3373,7 +3596,8 @@
 
   /// Invocation of the [constant] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     const c = null;
   ///     m() => c(null, 42);
   ///
@@ -3386,7 +3610,8 @@
 
   /// Read of the unresolved [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m1() => unresolved;
   ///     m2() => prefix.unresolved;
@@ -3408,7 +3633,8 @@
 
   /// Read of the unresolved super [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {}
   ///     class C {
   ///       m() => super.foo;
@@ -3421,7 +3647,8 @@
 
   /// Assignment of [rhs] to the unresolved [element].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m1() => unresolved = 42;
   ///     m2() => prefix.unresolved = 42;
@@ -3444,7 +3671,8 @@
 
   /// Invocation of the unresolved [element] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m1() => unresolved(null, 42);
   ///     m2() => prefix.unresolved(null, 42);
@@ -3468,7 +3696,8 @@
 
   /// Invocation of the unresolved super [element] with [arguments].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class B {}
   ///     class C extends B {
   ///       m() => super.foo();
@@ -3484,7 +3713,8 @@
   /// Compound assignment of [rhs] with [operator] reading from the
   /// non-existing static getter and writing to the static [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       set foo(_) {}
   ///     }
@@ -3501,7 +3731,8 @@
   /// Compound assignment of [rhs] with [operator] reading from the
   /// non-existing top level getter and writing to the top level [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set foo(_) {}
   ///     m1() => foo += 42;
   ///
@@ -3516,7 +3747,8 @@
   /// Compound assignment of [rhs] with [operator] reading from the static
   /// [getter] and writing to the non-existing static setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       get foo => 42;
   ///     }
@@ -3533,7 +3765,8 @@
   /// Compound assignment of [rhs] with [operator] reading from the top level
   /// [getter] and writing to the non-existing top level setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get foo => 42;
   ///     m1() => foo += 42;
   ///
@@ -3548,7 +3781,8 @@
   /// Compound assignment of [rhs] with [operator] reading the closurized static
   /// [method] and trying to invoke the non-existing setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       foo() {}
   ///     }
@@ -3563,7 +3797,8 @@
 
   /// Compound assignment of [rhs] where both getter and setter are unresolved.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m1() => unresolved += 42;
   ///     m2() => prefix.unresolved += 42;
@@ -3588,7 +3823,8 @@
   /// Prefix operation of [operator] reading from the non-existing static getter
   /// and writing to the static [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       set foo(_) {}
   ///     }
@@ -3604,7 +3840,8 @@
   /// Prefix operation of [operator] reading from the non-existing top level
   /// getter and writing to the top level [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set foo(_) {}
   ///     m1() => ++foo;
   ///
@@ -3618,7 +3855,8 @@
   /// Prefix operation of [operator] reading from the static [getter] and
   /// writing to the non-existing static setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       get foo => 42;
   ///     }
@@ -3634,7 +3872,8 @@
   /// Postfix operation of [operator] reading from the top level [getter] and
   /// writing to the non-existing top level setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get foo => 42;
   ///     m1() => ++foo;
   ///
@@ -3648,7 +3887,8 @@
   /// Prefix operation of [operator] reading the closurized static [method] and
   /// trying to invoke the non-existing setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       foo() {}
   ///     }
@@ -3663,7 +3903,8 @@
   /// Prefix operation of [operator] reading the closurized top level [method]
   /// and trying to invoke the non-existing setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       foo() {}
   ///     }
@@ -3677,7 +3918,8 @@
 
   /// Prefix operation where both getter and setter are unresolved.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m1() => ++unresolved;
   ///     m2() => ++prefix.unresolved;
@@ -3701,7 +3943,8 @@
   /// Postfix operation of [operator] reading from the non-existing static
   /// getter and writing to the static [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       set foo(_) {}
   ///     }
@@ -3717,7 +3960,8 @@
   /// Postfix operation of [operator] reading from the non-existing top level
   /// getter and writing to the top level [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set foo(_) {}
   ///     m1() => foo++;
   ///
@@ -3731,7 +3975,8 @@
   /// Postfix operation of [operator] reading from the static [getter] and
   /// writing to the non-existing static setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       get foo => 42;
   ///     }
@@ -3747,7 +3992,8 @@
   /// Postfix operation of [operator] reading from the top level [getter] and
   /// writing to the non-existing top level setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get foo => 42;
   ///     m1() => foo++;
   ///
@@ -3761,7 +4007,8 @@
   /// Postfix operation of [operator] reading the closurized static [method] and
   /// trying to invoke the non-existing setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       foo() {}
   ///     }
@@ -3776,7 +4023,8 @@
   /// Postfix operation of [operator] reading the closurized top level [method]
   /// and trying to invoke the non-existing setter.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       foo() {}
   ///     }
@@ -3790,7 +4038,8 @@
 
   /// Postfix operation where both getter and setter are unresolved.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {}
   ///     m1() => unresolved++;
   ///     m2() => prefix.unresolved++;
@@ -3829,11 +4078,12 @@
 
   /// Const invocation of a [constant] constructor.
   ///
-  /// For instance
-  ///   class C<T> {
-  ///     const C(a, b);
-  ///   }
-  ///   m() => const C<int>(true, 42);
+  /// For instance:
+  ///
+  ///     class C<T> {
+  ///       const C(a, b);
+  ///     }
+  ///     m() => const C<int>(true, 42);
   ///
   R visitConstConstructorInvoke(
       NewExpression node,
@@ -3842,8 +4092,9 @@
 
   /// Const invocation of the `bool.fromEnvironment` constructor.
   ///
-  /// For instance
-  ///   m() => const bool.fromEnvironment('foo', defaultValue: false);
+  /// For instance:
+  ///
+  ///     m() => const bool.fromEnvironment('foo', defaultValue: false);
   ///
   R visitBoolFromEnvironmentConstructorInvoke(
       NewExpression node,
@@ -3852,8 +4103,9 @@
 
   /// Const invocation of the `int.fromEnvironment` constructor.
   ///
-  /// For instance
-  ///   m() => const int.fromEnvironment('foo', defaultValue: 42);
+  /// For instance:
+  ///
+  ///     m() => const int.fromEnvironment('foo', defaultValue: 42);
   ///
   R visitIntFromEnvironmentConstructorInvoke(
       NewExpression node,
@@ -3862,8 +4114,9 @@
 
   /// Const invocation of the `String.fromEnvironment` constructor.
   ///
-  /// For instance
-  ///   m() => const String.fromEnvironment('foo', defaultValue: 'bar');
+  /// For instance:
+  ///
+  ///     m() => const String.fromEnvironment('foo', defaultValue: 'bar');
   ///
   R visitStringFromEnvironmentConstructorInvoke(
       NewExpression node,
@@ -3872,11 +4125,12 @@
 
   /// Invocation of a generative [constructor] on [type] with [arguments].
   ///
-  /// For instance
-  ///   class C<T> {
-  ///     C(a, b);
-  ///   }
-  ///   m() => new C<int>(true, 42);
+  /// For instance:
+  ///
+  ///     class C<T> {
+  ///       C(a, b);
+  ///     }
+  ///     m() => new C<int>(true, 42);
   ///
   /// where [type] is `C<int>`.
   ///
@@ -3891,12 +4145,13 @@
   /// Invocation of a redirecting generative [constructor] on [type] with
   /// [arguments].
   ///
-  /// For instance
-  ///   class C<T> {
-  ///     C(a, b) : this._(b, a);
-  ///     C._(b, a);
-  ///   }
-  ///   m() => new C<int>(true, 42);
+  /// For instance:
+  ///
+  ///     class C<T> {
+  ///       C(a, b) : this._(b, a);
+  ///       C._(b, a);
+  ///     }
+  ///     m() => new C<int>(true, 42);
   ///
   /// where [type] is `C<int>`.
   ///
@@ -3910,12 +4165,13 @@
 
   /// Invocation of a factory [constructor] on [type] with [arguments].
   ///
-  /// For instance
-  ///   class C<T> {
-  ///     factory C(a, b) => new C<T>._(b, a);
-  ///     C._(b, a);
-  ///   }
-  ///   m() => new C<int>(true, 42);
+  /// For instance:
+  ///
+  ///     class C<T> {
+  ///       factory C(a, b) => new C<T>._(b, a);
+  ///       C._(b, a);
+  ///     }
+  ///     m() => new C<int>(true, 42);
   ///
   /// where [type] is `C<int>`.
   ///
@@ -3931,13 +4187,14 @@
   /// [effectiveTarget] and [effectiveTargetType] are the constructor effective
   /// invoked and its type, respectively.
   ///
-  /// For instance
-  ///   class C<T> {
-  ///     factory C(a, b) = C<int>.a;
-  ///     factory C.a(a, b) = C<C<T>>.b;
-  ///     C.b(a, b);
-  ///   }
-  ///   m() => new C<double>(true, 42);
+  /// For instance:
+  ///
+  ///     class C<T> {
+  ///       factory C(a, b) = C<int>.a;
+  ///       factory C.a(a, b) = C<C<T>>.b;
+  ///       C.b(a, b);
+  ///     }
+  ///     m() => new C<double>(true, 42);
   ///
   /// where [type] is `C<double>`, [effectiveTarget] is `C.b` and
   /// [effectiveTargetType] is `C<C<int>>`.
@@ -3954,11 +4211,12 @@
 
   /// Invocation of an unresolved [constructor] on [type] with [arguments].
   ///
-  /// For instance
-  ///   class C<T> {
-  ///     C();
-  ///   }
-  ///   m() => new C<int>.unresolved(true, 42);
+  /// For instance:
+  ///
+  ///     class C<T> {
+  ///       C();
+  ///     }
+  ///     m() => new C<int>.unresolved(true, 42);
   ///
   /// where [type] is `C<int>`.
   ///
@@ -3974,8 +4232,9 @@
 
   /// Invocation of a constructor on an unresolved [type] with [arguments].
   ///
-  /// For instance
-  ///   m() => new Unresolved(true, 42);
+  /// For instance:
+  ///
+  ///     m() => new Unresolved(true, 42);
   ///
   /// where [type] is the malformed type `Unresolved`.
   ///
@@ -3991,11 +4250,12 @@
 
   /// Constant invocation of a non-constant constructor.
   ///
-  /// For instance
-  ///   class C {
-  ///     C(a, b);
-  ///   }
-  ///   m() => const C(true, 42);
+  /// For instance:
+  ///
+  ///     class C {
+  ///       C(a, b);
+  ///     }
+  ///     m() => const C(true, 42);
   ///
   R errorNonConstantConstructorInvoke(
       NewExpression node,
@@ -4007,8 +4267,9 @@
 
   /// Invocation of a constructor on an abstract [type] with [arguments].
   ///
-  /// For instance
-  ///   m() => new Unresolved(true, 42);
+  /// For instance:
+  ///
+  ///     m() => new Unresolved(true, 42);
   ///
   /// where [type] is the malformed type `Unresolved`.
   ///
@@ -4024,13 +4285,14 @@
   /// [effectiveTarget] and [effectiveTargetType] are the constructor effective
   /// invoked and its type, respectively.
   ///
-  /// For instance
-  ///   class C {
-  ///     factory C(a, b) = Unresolved;
-  ///     factory C.a(a, b) = C.unresolved;
-  ///   }
-  ///   m1() => new C(true, 42);
-  ///   m2() => new C.a(true, 42);
+  /// For instance:
+  ///
+  ///     class C {
+  ///       factory C(a, b) = Unresolved;
+  ///       factory C.a(a, b) = C.unresolved;
+  ///     }
+  ///     m1() => new C(true, 42);
+  ///     m2() => new C.a(true, 42);
   ///
   R visitUnresolvedRedirectingFactoryConstructorInvoke(
       NewExpression node,
@@ -4042,11 +4304,12 @@
 
   /// Invocation of [constructor] on [type] with incompatible [arguments].
   ///
-  /// For instance
-  ///   class C {
-  ///     C(a);
-  ///   }
-  ///   m() => C(true, 42);
+  /// For instance:
+  ///
+  ///     class C {
+  ///       C(a);
+  ///     }
+  ///     m() => C(true, 42);
   ///
   R visitConstructorIncompatibleInvoke(
       NewExpression node,
@@ -4056,12 +4319,231 @@
       CallStructure callStructure,
       A arg);
 
+  /// Read access of an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     import 'foo.dart' as p;
+  ///
+  ///     m() => p;
+  ///
+  R errorInvalidGet(
+      Send node,
+      ErroneousElement error,
+      A arg);
+
+
+  /// Invocation of an invalid expression with [arguments].
+  ///
+  /// For instance:
+  ///
+  ///     import 'foo.dart' as p;
+  ///
+  ///     m() => p(null, 42);
+  ///
+  R errorInvalidInvoke(
+      Send node,
+      ErroneousElement error,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Assignment of [rhs] to an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     import 'foo.dart' as p;
+  ///
+  ///     m() { p = 42; }
+  ///
+  R errorInvalidSet(
+      Send node,
+      ErroneousElement error,
+      Node rhs,
+      A arg);
+
+  /// Prefix operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     import 'foo.dart' as p;
+  ///
+  ///     m() => ++p;
+  ///
+  R errorInvalidPrefix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      A arg);
+
+  /// Postfix operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     import 'foo.dart' as p;
+  ///
+  ///     m() => p--;
+  ///
+  R errorInvalidPostfix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      A arg);
+
+  /// Compound assignment of [operator] with [rhs] on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     import 'foo.dart' as p;
+  ///
+  ///     m() => p += 42;
+  ///
+  R errorInvalidCompound(
+      Send node,
+      ErroneousElement error,
+      AssignmentOperator operator,
+      Node rhs,
+      A arg);
+
+  /// Unary operation with [operator] on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => ~super;
+  ///     }
+  ///
+  R errorInvalidUnary(
+      Send node,
+      UnaryOperator operator,
+      ErroneousElement error,
+      A arg);
+
+  /// Equals operation on an invalid left expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super == null;
+  ///     }
+  ///
+  R errorInvalidEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      A arg);
+
+  /// Not equals operation on an invalid left expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super != null;
+  ///     }
+  ///
+  R errorInvalidNotEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      A arg);
+
+  /// Binary operation with [operator] on an invalid left expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super + 0;
+  ///     }
+  ///
+  R errorInvalidBinary(
+      Send node,
+      ErroneousElement error,
+      BinaryOperator operator,
+      Node right,
+      A arg);
+
+  /// Index operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super[0];
+  ///     }
+  ///
+  R errorInvalidIndex(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      A arg);
+
+  /// Index set operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super[0] = 42;
+  ///     }
+  ///
+  R errorInvalidIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      Node rhs,
+      A arg);
+
+  /// Compound index set operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super[0] += 42;
+  ///     }
+  ///
+  R errorInvalidCompoundIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      AssignmentOperator operator,
+      Node rhs,
+      A arg);
+
+  /// Prefix index operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => --super[0];
+  ///     }
+  ///
+  R errorInvalidIndexPrefix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      A arg);
+
+  /// Postfix index operation on an invalid expression.
+  ///
+  /// For instance:
+  ///
+  ///     class C {
+  ///       static m() => super[0]++;
+  ///     }
+  ///
+  R errorInvalidIndexPostfix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      A arg);
+
   /// Access of library through a deferred [prefix].
   ///
-  /// For instance
-  ///   import 'lib.dart' deferred as prefix;
+  /// For instance:
   ///
-  ///   m() => prefix.foo;
+  ///     import 'lib.dart' deferred as prefix;
+  ///
+  ///     m() => prefix.foo;
   ///
   /// This visit method is special in that it is called as a pre-step to calling
   /// the visit method for the actual access. Therefore this method cannot
@@ -4083,7 +4565,8 @@
 
   /// A declaration of a top level [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     get m => 42;
   ///
   R visitTopLevelGetterDeclaration(
@@ -4094,7 +4577,8 @@
 
   /// A declaration of a top level [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     set m(a) {}
   ///
   R visitTopLevelSetterDeclaration(
@@ -4106,7 +4590,8 @@
 
   /// A declaration of a top level [function].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     m(a) {}
   ///
   R visitTopLevelFunctionDeclaration(
@@ -4118,7 +4603,8 @@
 
   /// A declaration of a static [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static get m => 42;
   ///     }
@@ -4131,7 +4617,8 @@
 
   /// A declaration of a static [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static set m(a) {}
   ///     }
@@ -4145,7 +4632,8 @@
 
   /// A declaration of a static [function].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       static m(a) {}
   ///     }
@@ -4159,7 +4647,8 @@
 
   /// A declaration of an abstract instance [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     abstract class C {
   ///       get m;
   ///     }
@@ -4171,7 +4660,8 @@
 
   /// A declaration of an abstract instance [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     abstract class C {
   ///       set m(a);
   ///     }
@@ -4184,7 +4674,8 @@
 
   /// A declaration of an abstract instance [method].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     abstract class C {
   ///       m(a);
   ///     }
@@ -4197,7 +4688,8 @@
 
   /// A declaration of an instance [getter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       get m => 42;
   ///     }
@@ -4210,7 +4702,8 @@
 
   /// A declaration of an instance [setter].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       set m(a) {}
   ///     }
@@ -4224,7 +4717,8 @@
 
   /// A declaration of an instance [method].
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///     class C {
   ///       m(a) {}
   ///     }
@@ -4238,7 +4732,8 @@
 
   /// A declaration of a local [function].
   ///
-  /// For instance `local` in
+  /// For instance `local` in:
+  ///
   ///     m() {
   ///       local(a) {}
   ///     }
@@ -4252,7 +4747,8 @@
 
   /// A declaration of a [closure].
   ///
-  /// For instance `(a) {}` in
+  /// For instance `(a) {}` in:
+  ///
   ///     m() {
   ///       var closure = (a) {};
   ///     }
@@ -4267,7 +4763,8 @@
   /// A declaration of the [index]th [parameter] in a constructor, setter,
   /// method or function.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     m(a) {}
   ///
   R visitParameterDeclaration(
@@ -4281,7 +4778,8 @@
   /// method or function with the explicit [defaultValue]. If no default value
   /// is declared, [defaultValue] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     m([a = 42]) {}
   ///
   R visitOptionalParameterDeclaration(
@@ -4296,7 +4794,8 @@
   /// with the explicit [defaultValue]. If no default value is declared,
   /// [defaultValue] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     m({a: 42}) {}
   ///
   R visitNamedParameterDeclaration(
@@ -4309,7 +4808,8 @@
   /// A declaration of the [index]th [parameter] as an initializing formal in a
   /// constructor.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     class C {
   ///       var a;
   ///       C(this.a);
@@ -4326,7 +4826,8 @@
   /// formal in a constructor with the explicit [defaultValue]. If no default
   /// value is declared, [defaultValue] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     class C {
   ///       var a;
   ///       C([this.a = 42]);
@@ -4344,7 +4845,8 @@
   /// constructor with the explicit [defaultValue]. If no default value is
   /// declared, [defaultValue] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     class C {
   ///       var a;
   ///       C({this.a: 42});
@@ -4360,7 +4862,8 @@
   /// A declaration of a local [variable] with the explicit [initializer]. If
   /// no initializer is declared, [initializer] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     m() {
   ///       var a = 42;
   ///     }
@@ -4374,7 +4877,8 @@
 
   /// A declaration of a local constant [variable] initialized to [constant].
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     m() {
   ///       const a = 42;
   ///     }
@@ -4389,7 +4893,8 @@
   /// A declaration of a top level [field] with the explicit [initializer].
   /// If no initializer is declared, [initializer] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     var a = 42;
   ///
   R visitTopLevelFieldDeclaration(
@@ -4401,7 +4906,8 @@
 
   /// A declaration of a top level constant [field] initialized to [constant].
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     const a = 42;
   ///
   R visitTopLevelConstantDeclaration(
@@ -4414,7 +4920,8 @@
   /// A declaration of a static [field] with the explicit [initializer].
   /// If no initializer is declared, [initializer] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     class C {
   ///       static var a = 42;
   ///     }
@@ -4428,7 +4935,8 @@
 
   /// A declaration of a static constant [field] initialized to [constant].
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     class C {
   ///       static const a = 42;
   ///     }
@@ -4443,7 +4951,8 @@
   /// A declaration of an instance [field] with the explicit [initializer].
   /// If no initializer is declared, [initializer] is `null`.
   ///
-  /// For instance `a` in
+  /// For instance `a` in:
+  ///
   ///     class C {
   ///       var a = 42;
   ///     }
@@ -4458,7 +4967,8 @@
   /// A declaration of a generative [constructor] with the explicit constructor
   /// [initializers].
   ///
-  /// For instance `C` in
+  /// For instance `C` in:
+  ///
   ///     class C {
   ///       var a;
   ///       C(a) : this.a = a, super();
@@ -4477,7 +4987,8 @@
   /// A declaration of a redirecting generative [constructor] with
   /// [initializers] containing the redirecting constructor invocation.
   ///
-  /// For instance `C` in
+  /// For instance `C` in:
+  ///
   ///     class C {
   ///       C() : this._();
   ///       C._();
@@ -4494,7 +5005,8 @@
 
   /// A declaration of a factory [constructor].
   ///
-  /// For instance `C` in
+  /// For instance `C` in:
+  ///
   ///     class C {
   ///       factory C(a) => null;
   ///     }
@@ -4510,7 +5022,8 @@
   /// redirection target and its type is provided in [redirectionTarget] and
   /// [redirectionType], respectively.
   ///
-  /// For instance
+  /// For instance:
+  ///
   ///    class C<T> {
   ///      factory C() = C<int>.a;
   ///      factory C.a() = C<C<T>>.b;
@@ -4530,7 +5043,8 @@
   /// An initializer of [field] with [initializer] as found in constructor
   /// initializers.
   ///
-  /// For instance `this.a = 42` in
+  /// For instance `this.a = 42` in:
+  ///
   ///     class C {
   ///       var a;
   ///       C() : this.a = 42;
@@ -4545,7 +5059,8 @@
   /// An initializer of an unresolved field with [initializer] as found in
   /// generative constructor initializers.
   ///
-  /// For instance `this.a = 42` in
+  /// For instance `this.a = 42` in:
+  ///
   ///     class C {
   ///       C() : this.a = 42;
   ///     }
@@ -4559,7 +5074,8 @@
   /// An super constructor invocation of [superConstructor] with [arguments] as
   /// found in generative constructor initializers.
   ///
-  /// For instance `super(42)` in
+  /// For instance `super(42)` in:
+  ///
   ///     class B {
   ///       B(a);
   ///     }
@@ -4578,7 +5094,8 @@
   /// An implicit super constructor invocation of [superConstructor] from
   /// generative constructor initializers.
   ///
-  /// For instance `super(42)` in
+  /// For instance `super(42)` in:
+  ///
   ///     class B {
   ///       B();
   ///     }
@@ -4595,7 +5112,8 @@
   /// An super constructor invocation of an unresolved with [arguments] as
   /// found in generative constructor initializers.
   ///
-  /// For instance `super(42)` in
+  /// For instance `super(42)` in:
+  ///
   ///     class B {
   ///       B(a);
   ///     }
@@ -4613,7 +5131,8 @@
   /// An this constructor invocation of [thisConstructor] with [arguments] as
   /// found in a redirecting generative constructors initializer.
   ///
-  /// For instance `this._(42)` in
+  /// For instance `this._(42)` in:
+  ///
   ///     class C {
   ///       C() : this._(42);
   ///       C._(a);
@@ -4629,7 +5148,8 @@
   /// An this constructor invocation of an unresolved constructor with
   /// [arguments] as found in a redirecting generative constructors initializer.
   ///
-  /// For instance `this._(42)` in
+  /// For instance `this._(42)` in:
+  ///
   ///     class C {
   ///       C() : this._(42);
   ///     }
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
index c1dfa54..ec45561 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
@@ -20,7 +20,9 @@
 abstract class ErrorBulkMixin<R, A>
     implements SemanticSendVisitor<R, A>, BulkHandle<R, A> {
 
-  R bulkHandleError(Node node, A arg) {
+  // TODO(johnniwinther): Ensure that all error methods have an
+  // [ErroneousElement].
+  R bulkHandleError(Node node, ErroneousElement error, A arg) {
     return bulkHandleNode(node, "Error expression `#` unhandled.", arg);
   }
 
@@ -29,7 +31,7 @@
       Send node,
       NodeList arguments,
       A arg) {
-    return bulkHandleError(node, arg);
+    return bulkHandleError(node, null, arg);
   }
 
   @override
@@ -40,7 +42,7 @@
       NodeList arguments,
       CallStructure callStructure,
       A arg) {
-    return bulkHandleError(node, arg);
+    return bulkHandleError(node, null, arg);
   }
 
   @override
@@ -49,7 +51,7 @@
       Operator operator,
       Node expression,
       A arg) {
-    return bulkHandleError(node, arg);
+    return bulkHandleError(node, null, arg);
   }
 
   @override
@@ -59,7 +61,149 @@
       Operator operator,
       Node right,
       A arg) {
-    return bulkHandleError(node, arg);
+    return bulkHandleError(node, null, arg);
+  }
+
+  @override
+  R errorInvalidCompound(
+      Send node,
+      ErroneousElement error,
+      AssignmentOperator operator,
+      Node rhs,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidGet(
+      Send node,
+      ErroneousElement error,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidInvoke(
+      Send node,
+      ErroneousElement error,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidPostfix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidPrefix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidSet(
+      Send node,
+      ErroneousElement error,
+      Node rhs,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidUnary(
+      Send node,
+      UnaryOperator operator,
+      ErroneousElement error,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidNotEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidBinary(
+      Send node,
+      ErroneousElement error,
+      BinaryOperator operator,
+      Node right,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidIndex(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      Node rhs,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidCompoundIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      AssignmentOperator operator,
+      Node rhs,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidIndexPrefix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      A arg) {
+    return bulkHandleError(node, error, arg);
+  }
+
+  @override
+  R errorInvalidIndexPostfix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      A arg) {
+    return bulkHandleError(node, error, arg);
   }
 }
 
@@ -3534,6 +3678,161 @@
   }
 
   @override
+  R errorInvalidCompound(
+      Send node,
+      ErroneousElement error,
+      AssignmentOperator operator,
+      Node rhs,
+      A arg) {
+    apply(rhs, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidGet(
+      Send node,
+      ErroneousElement error,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R errorInvalidInvoke(
+      Send node,
+      ErroneousElement error,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidPostfix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R errorInvalidPrefix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R errorInvalidSet(
+      Send node,
+      ErroneousElement error,
+      Node rhs,
+      A arg) {
+    apply(rhs, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidUnary(
+      Send node,
+      UnaryOperator operator,
+      ErroneousElement error,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R errorInvalidEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      A arg) {
+    apply(right, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidNotEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      A arg) {
+    apply(right, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidBinary(
+      Send node,
+      ErroneousElement error,
+      BinaryOperator operator,
+      Node right,
+      A arg) {
+    apply(right, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidIndex(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      A arg) {
+    apply(index, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      Node rhs,
+      A arg) {
+    apply(index, arg);
+    apply(rhs, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidCompoundIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      AssignmentOperator operator,
+      Node rhs,
+      A arg) {
+    apply(index, arg);
+    apply(rhs, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidIndexPrefix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      A arg) {
+    apply(index, arg);
+    return null;
+  }
+
+  @override
+  R errorInvalidIndexPostfix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      A arg) {
+    apply(index, arg);
+    return null;
+  }
+
+  @override
   R visitClassTypeLiteralSet(
       SendSet node,
       ConstantExpression constant,
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index a64c293..b5134a2 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -373,6 +373,13 @@
             node.argumentsNode,
             selector,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidInvoke(
+            node,
+            semantics.element,
+            node.argumentsNode,
+            selector,
+            arg);
       case AccessKind.COMPOUND:
         // This is not a valid case.
         break;
@@ -590,6 +597,11 @@
             node,
             semantics.element,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidGet(
+            node,
+            semantics.element,
+            arg);
       case AccessKind.COMPOUND:
         // This is not a valid case.
         break;
@@ -793,6 +805,12 @@
             semantics.element,
             node.arguments.single,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidSet(
+            node,
+            semantics.element,
+            node.arguments.single,
+            arg);
       case AccessKind.COMPOUND:
         // This is not a valid case.
         break;
@@ -817,7 +835,7 @@
             node,
             node.receiver,
             arg);
-      default:
+     default:
         // This is not a valid case.
         break;
     }
@@ -858,6 +876,12 @@
             operator,
             semantics.element,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidUnary(
+            node,
+            operator,
+            semantics.element,
+            arg);
       default:
         // This is not a valid case.
         break;
@@ -913,6 +937,12 @@
             semantics.element,
             node.arguments.single,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidIndex(
+            node,
+            semantics.element,
+            node.arguments.single,
+            arg);
       default:
         // This is not a valid case.
         break;
@@ -943,6 +973,12 @@
             semantics.element,
             node.arguments.single,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidEquals(
+            node,
+            semantics.element,
+            node.arguments.single,
+            arg);
       default:
         // This is not a valid case.
         break;
@@ -975,6 +1011,12 @@
             semantics.element,
             node.arguments.single,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidNotEquals(
+            node,
+            semantics.element,
+            node.arguments.single,
+            arg);
       default:
         // This is not a valid case.
         break;
@@ -1020,6 +1062,13 @@
             operator,
             node.arguments.single,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidBinary(
+            node,
+            semantics.element,
+            operator,
+            node.arguments.single,
+            arg);
       default:
         // This is not a valid case.
         break;
@@ -1084,6 +1133,13 @@
             node.arguments.first,
             node.arguments.tail.head,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidIndexSet(
+            node,
+            semantics.element,
+            node.arguments.first,
+            node.arguments.tail.head,
+            arg);
       default:
         // This is not a valid case.
         break;
@@ -1133,6 +1189,13 @@
             node.arguments.single,
             operator,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidIndexPrefix(
+            node,
+            semantics.element,
+            node.arguments.single,
+            operator,
+            arg);
       case AccessKind.COMPOUND:
         CompoundAccessSemantics compoundSemantics = semantics;
         switch (compoundSemantics.compoundAccessKind) {
@@ -1212,6 +1275,13 @@
             node.arguments.single,
             operator,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidIndexPostfix(
+            node,
+            semantics.element,
+            node.arguments.single,
+            operator,
+            arg);
       case AccessKind.COMPOUND:
         CompoundAccessSemantics compoundSemantics = semantics;
         switch (compoundSemantics.compoundAccessKind) {
@@ -1468,6 +1538,13 @@
             operator,
             node.arguments.single,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidCompound(
+            node,
+            semantics.element,
+            operator,
+            node.arguments.single,
+            arg);
       case AccessKind.COMPOUND:
         CompoundAccessSemantics compoundSemantics = semantics;
         switch (compoundSemantics.compoundAccessKind) {
@@ -1633,6 +1710,14 @@
             operator,
             node.arguments.tail.head,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidCompoundIndexSet(
+            node,
+            semantics.element,
+            node.arguments.first,
+            operator,
+            node.arguments.tail.head,
+            arg);
       case AccessKind.COMPOUND:
         CompoundAccessSemantics compoundSemantics = semantics;
         switch (compoundSemantics.compoundAccessKind) {
@@ -1871,6 +1956,12 @@
             semantics.element,
             operator,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidPrefix(
+            node,
+            semantics.element,
+            operator,
+            arg);
       case AccessKind.COMPOUND:
         CompoundAccessSemantics compoundSemantics = semantics;
         switch (compoundSemantics.compoundAccessKind) {
@@ -2187,6 +2278,12 @@
             semantics.element,
             operator,
             arg);
+      case AccessKind.INVALID:
+        return visitor.errorInvalidPostfix(
+            node,
+            semantics.element,
+            operator,
+            arg);
       case AccessKind.COMPOUND:
         CompoundAccessSemantics compoundSemantics = semantics;
         switch (compoundSemantics.compoundAccessKind) {
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index 48c5430..e4dfb1e 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -12,8 +12,12 @@
   /// [analyzedElement].
   Iterable<Element> get allElements;
 
+  /// The set of types that this TreeElement depends on.
+  /// This includes instantiated types, types in is-checks and as-expressions
+  /// and in checked mode the types of all type-annotations.
+  Iterable<DartType> get requiredTypes;
+
   void forEachConstantNode(f(Node n, ConstantExpression c));
-  void forEachType(f(Node n, DartType t));
 
   /// A set of additional dependencies.  See [registerDependency] below.
   Iterable<Element> get otherDependencies;
@@ -71,6 +75,9 @@
   /// For example, elements that are used by a backend.
   void registerDependency(Element element);
 
+  /// Register a dependency on [type].
+  void addRequiredType(DartType type);
+
   /// Returns a list of nodes that potentially mutate [element] anywhere in its
   /// scope.
   List<Node> getPotentialMutations(VariableElement element);
@@ -112,6 +119,7 @@
   Setlet<Element> _elements;
   Setlet<Send> _asserts;
   Maplet<Send, SendStructure> _sendStructureMap;
+  Setlet<DartType> _requiredTypes;
 
   /// Map from nodes to the targets they define.
   Map<Node, JumpTarget> _definedTargets;
@@ -175,9 +183,16 @@
 
   DartType getType(Node node) => _types != null ? _types[node] : null;
 
-  void forEachType(f(Node n, DartType t)) {
-    if (_types != null) {
-      _types.forEach(f);
+  void addRequiredType(DartType type) {
+    if (_requiredTypes == null) _requiredTypes = new Setlet<DartType>();
+    _requiredTypes.add(type);
+  }
+
+  Iterable<DartType> get requiredTypes {
+    if (_requiredTypes == null) {
+      return const <DartType>[];
+    } else {
+      return _requiredTypes;
     }
   }
 
diff --git a/pkg/compiler/lib/src/resolved_visitor.dart b/pkg/compiler/lib/src/resolved_visitor.dart
index dd60417..5eb6a13 100644
--- a/pkg/compiler/lib/src/resolved_visitor.dart
+++ b/pkg/compiler/lib/src/resolved_visitor.dart
@@ -327,10 +327,13 @@
       Node node,
       String message,
       ResolvedKindVisitor<R> visitor) {
-    return bulkHandleError(node, visitor);
+    return bulkHandleError(node, null, visitor);
   }
 
-  R bulkHandleError(Node node, ResolvedKindVisitor<R> visitor) {
+  R bulkHandleError(
+      Node node,
+      ErroneousElement error,
+      ResolvedKindVisitor<R> visitor) {
     if (node.asSendSet() != null) {
       return visitor.handleSendSet(node);
     } else if (node.asNewExpression() != null) {
diff --git a/pkg/compiler/lib/src/scanner/listener.dart b/pkg/compiler/lib/src/scanner/listener.dart
index ef9b651..c3299a3 100644
--- a/pkg/compiler/lib/src/scanner/listener.dart
+++ b/pkg/compiler/lib/src/scanner/listener.dart
@@ -693,7 +693,8 @@
   void reportError(Spannable spannable,
                    MessageKind messageKind,
                    [Map arguments = const {}]) {
-    String message = messageKind.message(arguments, true).toString();
+    MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
+    String message = template.message(arguments, true).toString();
     Token token;
     if (spannable is Token) {
       token = spannable;
@@ -1131,8 +1132,8 @@
     } else {
       reportFatalError(
           token,
-          MessageKind.MISSING_TOKEN_BEFORE_THIS.message(
-              {'token': string}, true).toString());
+          MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS]
+              .message({'token': string}, true).toString());
     }
     return skipToEof(token);
   }
@@ -2565,12 +2566,17 @@
 
   Node parseNode(DiagnosticListener listener) {
     if (cachedNode != null) return cachedNode;
-    Metadata metadata = parse(listener,
-                              annotatedElement,
-                              declarationSite,
-                              (p) => p.parseMetadata(beginToken));
-    cachedNode = metadata.expression;
-    return cachedNode;
+    var metadata = parse(listener,
+                         annotatedElement,
+                         declarationSite,
+                         (p) => p.parseMetadata(beginToken));
+    if (metadata is Metadata) {
+      cachedNode = metadata.expression;
+      return cachedNode;
+    } else {
+      assert (metadata is ErrorNode);
+      return metadata;
+    }
   }
 
   bool get hasNode => cachedNode != null;
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 932864a..2269a9e 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -170,8 +170,8 @@
   }
 
   @override
-  void report(Uri uri, int begin, int end, String message,
-                        api.Diagnostic kind) {
+  void report(var code, Uri uri, int begin, int end, String message,
+              api.Diagnostic kind) {
     // TODO(ahe): Remove this when source map is handled differently.
     if (identical(kind.name, 'source map')) return;
 
@@ -236,7 +236,7 @@
   // TODO(johnniwinther): Remove this when no longer needed for the old compiler
   // API.
   void call(Uri uri, int begin, int end, String message, api.Diagnostic kind) {
-    return report(uri, begin, end, message, kind);
+    return report(null, uri, begin, end, message, kind);
   }
 }
 
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 573bde0..435b4bb 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -492,7 +492,12 @@
               "Cannot find value $local.");
         }
       }
-      return directLocals[local];
+      HInstruction value = directLocals[local];
+      if (sourceInformation != null) {
+        value = new HRef(value, sourceInformation);
+        builder.add(value);
+      }
+      return value;
     } else if (isStoredInClosureField(local)) {
       ClosureFieldElement redirect = redirectionMapping[local];
       HInstruction receiver = readLocal(closureData.closureElement);
@@ -518,9 +523,9 @@
       assert(isUsedInTryOrGenerator(local));
       HLocalValue localValue = getLocal(local);
       HInstruction instruction = new HLocalGet(
-          local, localValue, builder.backend.dynamicType);
+          local, localValue, builder.backend.dynamicType, sourceInformation);
       builder.add(instruction);
-      return instruction..sourceInformation = sourceInformation;
+      return instruction;
     }
   }
 
@@ -562,6 +567,10 @@
    */
   void updateLocal(Local local, HInstruction value,
                    {SourceInformation sourceInformation}) {
+    if (value is HRef) {
+      HRef ref = value;
+      value = ref.value;
+    }
     assert(!isStoredInClosureField(local));
     if (isAccessedDirectly(local)) {
       directLocals[local] = value;
@@ -1029,7 +1038,8 @@
     with BaseImplementationOfCompoundsMixin,
          SendResolverMixin,
          SemanticSendResolvedMixin,
-         NewBulkMixin
+         NewBulkMixin,
+         ErrorBulkMixin
     implements SemanticSendVisitor {
   final Compiler compiler;
   final JavaScriptBackend backend;
@@ -1649,12 +1659,13 @@
                   backend.boolType));
             },
             visitThen: () {
-              // TODO(johnniwinther): Add source information.
               closeAndGotoExit(new HReturn(
                   graph.addConstantBool(false, compiler),
-                  null));
+                  sourceInformationBuilder
+                      .buildImplicitReturn(functionElement)));
             },
-            visitElse: null);
+            visitElse: null,
+            sourceInformation: sourceInformationBuilder.buildIf(function.body));
       }
     }
     function.body.accept(this);
@@ -4898,7 +4909,13 @@
     // The new object will now be referenced through the
     // `setRuntimeTypeInfo` call. We therefore set the type of that
     // instruction to be of the object's type.
-    assert(stack.last is HInvokeStatic || stack.last == newObject);
+    assert(invariant(
+        CURRENT_ELEMENT_SPANNABLE,
+        stack.last is HInvokeStatic || stack.last == newObject,
+        message:
+          "Unexpected `stack.last`: Found ${stack.last}, "
+          "expected ${newObject} or an HInvokeStatic. "
+          "State: element=$element, rtiInputs=$rtiInputs, stack=$stack."));
     stack.last.instructionType = newObject.instructionType;
     return pop();
   }
@@ -5620,7 +5637,8 @@
             noSuchMethodTargetSymbolString(error, 'constructor'),
             argumentNodes: node.send.arguments);
       } else {
-        Message message = error.messageKind.message(error.messageArguments);
+        MessageTemplate template = MessageTemplate.TEMPLATES[error.messageKind];
+        Message message = template.message(error.messageArguments);
         generateRuntimeError(node.send, message.toString());
       }
     } else if (node.isConst) {
@@ -8257,6 +8275,12 @@
       _) {
     visitNode(node);
   }
+
+  @override
+  void bulkHandleError(ast.Node node, ErroneousElement error, _) {
+    // TODO(johnniwinther): Use an uncatchable error when supported.
+    generateRuntimeError(node, error.message);
+  }
 }
 
 /**
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 6057d6f..998ed36 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1911,8 +1911,12 @@
         registry.registerTypeConstant(element);
       }
     }
-    push(backend.emitter.constantReference(constant)
-            .withSourceInformation(sourceInformation));
+    js.Expression expression = backend.emitter.constantReference(constant);
+    if (!constant.isDummy) {
+      // TODO(johnniwinther): Support source information on synthetic constants.
+      expression = expression.withSourceInformation(sourceInformation);
+    }
+    push(expression);
   }
 
   visitConstant(HConstant node) {
@@ -2709,7 +2713,9 @@
       js.Statement body = new js.Block.empty();
       currentContainer = body;
       if (node.isArgumentTypeCheck) {
-        generateThrowWithHelper('iae', node.checkedInput);
+        generateThrowWithHelper('iae',
+            node.checkedInput,
+            sourceInformation: node.sourceInformation);
       } else if (node.isReceiverTypeCheck) {
         use(node.checkedInput);
         js.Name methodName =
@@ -2859,4 +2865,9 @@
     registry.registerStaticUse(helper);
     return backend.emitter.staticFunctionAccess(helper);
   }
+
+  @override
+  void visitRef(HRef node) {
+    visit(node.value);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 0adc6e3..b23f32d 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -56,6 +56,7 @@
   R visitPhi(HPhi node);
   R visitRangeConversion(HRangeConversion node);
   R visitReadModifyWrite(HReadModifyWrite node);
+  R visitRef(HRef node);
   R visitReturn(HReturn node);
   R visitShiftLeft(HShiftLeft node);
   R visitShiftRight(HShiftRight node);
@@ -347,6 +348,7 @@
   visitParameterValue(HParameterValue node) => visitLocalValue(node);
   visitRangeConversion(HRangeConversion node) => visitCheck(node);
   visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
+  visitRef(HRef node) => node.value.accept(this);
   visitReturn(HReturn node) => visitControlFlow(node);
   visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
   visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
@@ -1307,6 +1309,32 @@
   }
 }
 
+/// A reference to a [HInstruction] that can hold its own source information.
+///
+/// This used for attaching source information to reads of locals.
+class HRef extends HInstruction {
+  HRef(HInstruction value, SourceInformation sourceInformation)
+      : super([value], value.instructionType) {
+    this.sourceInformation = sourceInformation;
+  }
+
+  HInstruction get value => inputs[0];
+
+  @override
+  HInstruction convertType(Compiler compiler, DartType type, int kind) {
+    HInstruction converted = value.convertType(compiler, type, kind);
+    if (converted == value) return this;
+    HTypeConversion conversion = converted;
+    conversion.inputs[0] = this;
+    return conversion;
+  }
+
+  @override
+  accept(HVisitor visitor) => visitor.visitRef(this);
+
+  String toString() => 'HRef(${value})';
+}
+
 /**
  * Late instructions are used after the main optimization phases.  They capture
  * codegen decisions just prior to generating JavaScript.
@@ -1714,8 +1742,11 @@
 class HLocalGet extends HLocalAccess {
   // No need to use GVN for a [HLocalGet], it is just a local
   // access.
-  HLocalGet(Local variable, HLocalValue local, TypeMask type)
-      : super(variable, <HInstruction>[local], type);
+  HLocalGet(Local variable, HLocalValue local, TypeMask type,
+            SourceInformation sourceInformation)
+      : super(variable, <HInstruction>[local], type) {
+    this.sourceInformation = sourceInformation;
+  }
 
   accept(HVisitor visitor) => visitor.visitLocalGet(this);
 
@@ -1795,6 +1826,8 @@
   bool get isAllocation => nativeBehavior != null &&
       nativeBehavior.isAllocation &&
       !canBeNull();
+
+  String toString() => 'HForeignCode("${codeTemplate.source}",$inputs)';
 }
 
 class HForeignNew extends HForeign {
@@ -2396,8 +2429,10 @@
   //     (a && C.JSArray_methods).get$first(a)
   //
 
-  HInterceptor(HInstruction receiver, TypeMask type)
+  HInterceptor(HInstruction receiver,
+               TypeMask type)
       : super(<HInstruction>[receiver], type) {
+    this.sourceInformation = receiver.sourceInformation;
     sideEffects.clearAllSideEffects();
     sideEffects.clearAllDependencies();
     setUseGvn();
@@ -2717,7 +2752,14 @@
   HInstruction get context => inputs[1];
 
   HInstruction convertType(Compiler compiler, DartType type, int kind) {
-    if (typeExpression == type) return this;
+    if (typeExpression == type) {
+      // Don't omit a boolean conversion (which doesn't allow `null`) unless
+      // this type conversion is already a boolean conversion.
+      if (kind != BOOLEAN_CONVERSION_CHECK ||
+          isBooleanConversionCheck) {
+        return this;
+      }
+    }
     return super.convertType(compiler, type, kind);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 0b50f8c..830c6c7 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -389,6 +389,10 @@
     return buffer.toString();
   }
 
+  String visitRef(HRef node) {
+    return 'Ref ${temporaryId(node.value)}';
+  }
+
   String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}";
 
   String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<');
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 8556472..2fb2d11 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -218,7 +218,8 @@
         ? instruction.selector
         : null;
     HTypeConversion converted = new HTypeConversion(
-        null, kind, type, input, selector);
+        null, kind, type, input, selector)
+        ..sourceInformation = instruction.sourceInformation;
     instruction.block.addBefore(instruction, converted);
     input.replaceAllUsersDominatedBy(instruction, converted);
   }
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 1141665..6c864be 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -368,7 +368,29 @@
            isEffectivelyConstant(node.value);
   }
 
-  Statement visitExpressionStatement(ExpressionStatement stmt) {
+  Statement visitExpressionStatement(ExpressionStatement inputNode) {
+    // Analyze chains of expression statements.
+    // To avoid deep recursion, [processExpressionStatement] returns a callback
+    // to invoke after its successor node has been processed.
+    // These callbacks are stored in a list and invoked in reverse at the end.
+    List<Function> stack = [];
+    Statement node = inputNode;
+    while (node is ExpressionStatement) {
+      stack.add(processExpressionStatement(node));
+      node = node.next;
+    }
+    Statement result = visitStatement(node);
+    for (Function fun in stack.reversed) {
+      result = fun(result);
+    }
+    return result;
+  }
+
+  /// Attempts to propagate an assignment in an expression statement.
+  /// 
+  /// Returns a callback to be invoked after the sucessor statement has
+  /// been processed.
+  Function processExpressionStatement(ExpressionStatement stmt) {
     Variable leftHand = getLeftHand(stmt.expression);
     pushDominatingAssignment(leftHand);
     if (isEffectivelyConstantAssignment(stmt.expression) &&
@@ -380,44 +402,50 @@
       if (assign.variable.readCount == 1) {
         // A single-use constant should always be propagated to its use site.
         constantEnvironment[assign.variable] = assign.value;
-        Statement next = visitStatement(stmt.next);
-        popDominatingAssignment(leftHand);
-        if (assign.variable.readCount > 0) {
-          // The assignment could not be propagated into the successor, either
-          // because it has an unsafe variable use (see [hasUnsafeVariableUse])
-          // or because the use is outside the current try block, and we do
-          // not currently support constant propagation out of a try block.
-          constantEnvironment.remove(assign.variable);
-          assign.value = visitExpression(assign.value);
-          stmt.next = next;
-          return stmt;
-        } else {
-          --assign.variable.writeCount;
-          return next;
-        }
+        return (Statement next) {
+          popDominatingAssignment(leftHand);
+          if (assign.variable.readCount > 0) {
+            // The assignment could not be propagated into the successor, 
+            // either because it [hasUnsafeVariableUse] or because the
+            // use is outside the current try block, and we do not currently
+            // support constant propagation out of a try block.
+            constantEnvironment.remove(assign.variable);
+            assign.value = visitExpression(assign.value);
+            stmt.next = next;
+            return stmt;
+          } else {
+            --assign.variable.writeCount;
+            return next;
+          }
+        };
       } else {
         // With more than one use, we cannot propagate the constant.
         // Visit the following statement without polluting [environment] so
         // that any preceding non-constant assignments might still propagate.
-        stmt.next = visitStatement(stmt.next);
-        popDominatingAssignment(leftHand);
-        assign.value = visitExpression(assign.value);
-        return stmt;
+        return (Statement next) {
+          stmt.next = next;
+          popDominatingAssignment(leftHand);
+          assign.value = visitExpression(assign.value);
+          return stmt;
+        };
       }
-    }
-    // Try to propagate the expression, and block previous impure expressions
-    // until this has propagated.
-    environment.add(stmt.expression);
-    stmt.next = visitStatement(stmt.next);
-    popDominatingAssignment(leftHand);
-    if (!environment.isEmpty && environment.last == stmt.expression) {
-      // Retain the expression statement.
-      environment.removeLast();
-      stmt.expression = visitExpression(stmt.expression);
-      return stmt;
     } else {
-      // Expression was propagated into the successor.
-      return stmt.next;
+      // Try to propagate the expression, and block previous impure expressions
+      // until this has propagated.
+      environment.add(stmt.expression);
+      return (Statement next) {
+        stmt.next = next;
+        popDominatingAssignment(leftHand);
+        if (!environment.isEmpty && environment.last == stmt.expression) {
+          // Retain the expression statement.
+          environment.removeLast();
+          stmt.expression = visitExpression(stmt.expression);
+          return stmt;
+        } else {
+          // Expression was propagated into the successor.
+          return stmt.next;
+        }
+      };
     }
   }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 73e4cfe..921e830 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -10,6 +10,8 @@
 import '../util/util.dart' show CURRENT_ELEMENT_SPANNABLE;
 import 'tree_ir_nodes.dart';
 
+typedef Statement NodeCallback(Statement next);
+
 /**
  * Builder translates from CPS-based IR to direct-style Tree.
  *
@@ -42,7 +44,7 @@
  * particular, intermediate values and blocks used for local control flow are
  * still all named.
  */
-class Builder implements cps_ir.Visitor<Node> {
+class Builder implements cps_ir.Visitor/*<NodeCallback|Node>*/ {
   final dart2js.InternalErrorFunction internalError;
 
   final Map<cps_ir.Primitive, Variable> primitive2variable =
@@ -109,6 +111,10 @@
     return new VariableUse(getVariable(reference.definition));
   }
 
+  Label getLabel(cps_ir.Continuation cont) {
+    return labels.putIfAbsent(cont, () => new Label());
+  }
+
   Variable addFunctionParameter(cps_ir.Definition variable) {
     if (variable is cps_ir.Parameter) {
       return getVariable(variable);
@@ -130,7 +136,7 @@
         node.parameters.map(addFunctionParameter).toList();
     returnContinuation = node.returnContinuation;
     phiTempVar = new Variable(node.element, null);
-    Statement body = visit(node.body);
+    Statement body = translateExpression(node.body);
     return new FunctionDefinition(node.element, parameters, body);
   }
 
@@ -147,19 +153,6 @@
          growable: false);
   }
 
-  Statement buildContinuationAssignment(
-      cps_ir.Parameter parameter,
-      Expression argument,
-      Statement buildRest()) {
-    Expression expr;
-    if (parameter.hasAtLeastOneUse) {
-      expr = new Assign(getVariable(parameter), argument);
-    } else {
-      expr = argument;
-    }
-    return new ExpressionStatement(expr, buildRest());
-  }
-
   /// Simultaneously assigns each argument to the corresponding parameter,
   /// then continues at the statement created by [buildRest].
   Statement buildPhiAssignments(
@@ -252,109 +245,134 @@
     return first;
   }
 
-  visit(cps_ir.Node node) => node.accept(this);
+  visit(cps_ir.Node node) => throw 'Use translateXXX instead of visit';
 
-  unexpectedNode(cps_ir.Node node) {
-    internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node');
+  /// Translates a CPS expression into a tree statement.
+  /// 
+  /// To avoid deep recursion, we traverse each basic blocks without
+  /// recursion.
+  /// 
+  /// Non-tail expressions evaluate to a callback to be invoked once the
+  /// successor statement has been constructed. These callbacks are stored
+  /// in a stack until the block's tail expression has been translated.
+  Statement translateExpression(cps_ir.Expression node) {
+    List<NodeCallback> stack = <NodeCallback>[];
+    while (node is! cps_ir.TailExpression) {
+      stack.add(node.accept(this));
+      node = node.next;
+    }
+    Statement result = node.accept(this); // Translate the tail expression.
+    for (NodeCallback fun in stack.reversed) {
+      result = fun(result);
+    }
+    return result;
   }
 
-  Expression visitSetField(cps_ir.SetField node) {
-    return new SetField(getVariableUse(node.object),
-                        node.field,
-                        getVariableUse(node.value));
-  }
-  
-  Expression visitInterceptor(cps_ir.Interceptor node) {
-    return new Interceptor(getVariableUse(node.input), node.interceptedClasses);
+  /// Translates a CPS primitive to a tree expression.
+  /// 
+  /// This simply calls the visit method for the primitive.
+  Expression translatePrimitive(cps_ir.Primitive prim) {
+    return prim.accept(this);
   }
 
-  Expression visitCreateInstance(cps_ir.CreateInstance node) {
-    return new CreateInstance(
-        node.classElement,
-        translateArguments(node.arguments),
-        translateArguments(node.typeInformation),
-        node.sourceInformation);
+  /// Translates a condition to a tree expression.
+  Expression translateCondition(cps_ir.Condition condition) {
+    cps_ir.IsTrue isTrue = condition;
+    return getVariableUse(isTrue.value);
   }
 
-  Expression visitGetField(cps_ir.GetField node) {
-    return new GetField(getVariableUse(node.object), node.field,
-        objectIsNotNull: node.objectIsNotNull);
-  }
+  /************************ INTERIOR EXPRESSIONS  ************************/
+  //
+  // Visit methods for interior expressions must return a function:
+  //
+  //    (Statement next) => <result statement>
+  //
 
-  Expression visitCreateBox(cps_ir.CreateBox node) {
-    return new CreateBox();
-  }
-
-  visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
-    return new CreateInvocationMirror(
-        node.selector,
-        translateArguments(node.arguments));
-  }
-
-  // Executable definitions are not visited directly.  They have 'build'
-  // functions as entry points.
-  visitFunctionDefinition(cps_ir.FunctionDefinition node) {
-    return unexpectedNode(node);
-  }
-
-  Statement visitLetPrim(cps_ir.LetPrim node) {
+  NodeCallback visitLetPrim(cps_ir.LetPrim node) => (Statement next) {
     Variable variable = getVariable(node.primitive);
-    Expression value = visit(node.primitive);
+    Expression value = translatePrimitive(node.primitive);
     if (node.primitive.hasAtLeastOneUse) {
-      return Assign.makeStatement(variable, value, visit(node.body));
+      return Assign.makeStatement(variable, value, next);
     } else {
-      return new ExpressionStatement(value, visit(node.body));
+      return new ExpressionStatement(value, next);
     }
-  }
+  };
 
-  Statement visitLetCont(cps_ir.LetCont node) {
-    // Introduce labels for continuations that need them.
+  // Continuations are bound at the same level, but they have to be
+  // translated as if nested.  This is because the body can invoke any
+  // of them from anywhere, so it must be nested inside all of them.
+  //
+  // The continuation bodies are not always translated directly here because
+  // they may have been already translated:
+  //   * For singly-used continuations, the continuation's body is
+  //     translated at the site of the continuation invocation.
+  //   * For recursive continuations, there is a single non-recursive
+  //     invocation.  The continuation's body is translated at the site
+  //     of the non-recursive continuation invocation.
+  // See [visitInvokeContinuation] for the implementation.
+  NodeCallback visitLetCont(cps_ir.LetCont node) => (Statement next) {
     for (cps_ir.Continuation continuation in node.continuations) {
-      if (continuation.hasMultipleUses || continuation.isRecursive) {
-        labels[continuation] = new Label();
-      }
-    }
-    Statement body = visit(node.body);
-    // Continuations are bound at the same level, but they have to be
-    // translated as if nested.  This is because the body can invoke any
-    // of them from anywhere, so it must be nested inside all of them.
-    //
-    // The continuation bodies are not always translated directly here because
-    // they may have been already translated:
-    //   * For singly-used continuations, the continuation's body is
-    //     translated at the site of the continuation invocation.
-    //   * For recursive continuations, there is a single non-recursive
-    //     invocation.  The continuation's body is translated at the site
-    //     of the non-recursive continuation invocation.
-    // See visitInvokeContinuation for the implementation.
-    Statement current = body;
-    for (cps_ir.Continuation continuation in node.continuations.reversed) {
+      // This happens after the body of the LetCont has been translated.
+      // Labels are created on-demand if the continuation could not be inlined,
+      // so the existence of the label indicates if a labeled statement should
+      // be emitted.
       Label label = labels[continuation];
       if (label != null && !continuation.isRecursive) {
-        current =
-            new LabeledStatement(label, current, visit(continuation.body));
+        // Recursively build the body. We only do this for join continuations,
+        // so we should not risk overly deep recursion.
+        next = new LabeledStatement(
+            label, 
+            next, 
+            translateExpression(continuation.body));
       }
     }
-    return current;
-  }
+    return next;
+  };
 
-  Statement visitLetHandler(cps_ir.LetHandler node) {
-    Statement tryBody = visit(node.body);
+  NodeCallback visitLetHandler(cps_ir.LetHandler node) => (Statement next) {
     List<Variable> catchParameters =
         node.handler.parameters.map(getVariable).toList();
-    Statement catchBody = visit(node.handler.body);
-    return new Try(tryBody, catchParameters, catchBody);
+    Statement catchBody = translateExpression(node.handler.body);
+    return new Try(next, catchParameters, catchBody);
+  };
+
+  NodeCallback visitLetMutable(cps_ir.LetMutable node) {
+    Variable variable = addMutableVariable(node.variable);
+    Expression value = getVariableUse(node.value);
+    return (Statement next) => Assign.makeStatement(variable, value, next);
   }
 
-  Statement visitInvokeStatic(cps_ir.InvokeStatic node) {
-    // Calls are translated to direct style.
+
+  /************************ CALL EXPRESSIONS  ************************/
+  //
+  // Visit methods for call expressions must return a function:
+  //
+  //    (Statement next) => <result statement>
+  //
+  // The result statement must include an assignment to the continuation
+  // parameter, if the parameter is used.
+  //
+
+  NodeCallback makeCallExpression(cps_ir.CallExpression call,
+                                  Expression expression) {
+    return (Statement next) {
+      cps_ir.Parameter result = call.continuation.definition.parameters.single;
+      if (result.hasAtLeastOneUse) {
+        return Assign.makeStatement(getVariable(result), expression, next);
+      } else {
+        return new ExpressionStatement(expression, next);
+      }
+    };
+  }
+
+  NodeCallback visitInvokeStatic(cps_ir.InvokeStatic node) {
     List<Expression> arguments = translateArguments(node.arguments);
     Expression invoke = new InvokeStatic(node.target, node.selector, arguments,
                                          node.sourceInformation);
-    return continueWithExpression(node.continuation, invoke);
+    return makeCallExpression(node, invoke);
   }
 
-  Statement visitInvokeMethod(cps_ir.InvokeMethod node) {
+  NodeCallback visitInvokeMethod(cps_ir.InvokeMethod node) {
     InvokeMethod invoke = new InvokeMethod(
         getVariableUse(node.receiver),
         node.selector,
@@ -362,17 +380,71 @@
         translateArguments(node.arguments),
         node.sourceInformation);
     invoke.receiverIsNotNull = node.receiverIsNotNull;
-    return continueWithExpression(node.continuation, invoke);
+    return makeCallExpression(node, invoke);
   }
 
-  Statement visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
+  NodeCallback visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
     Expression receiver = getVariableUse(node.receiver);
     List<Expression> arguments = translateArguments(node.arguments);
     Expression invoke = new InvokeMethodDirectly(receiver, node.target,
         node.selector, arguments, node.sourceInformation);
-    return continueWithExpression(node.continuation, invoke);
+    return makeCallExpression(node, invoke);
   }
 
+  NodeCallback visitTypeCast(cps_ir.TypeCast node) {
+    Expression value = getVariableUse(node.value);
+    List<Expression> typeArgs = translateArguments(node.typeArguments);
+    Expression expression =
+        new TypeOperator(value, node.type, typeArgs, isTypeTest: false);
+    return makeCallExpression(node, expression);
+  }
+
+  NodeCallback visitInvokeConstructor(cps_ir.InvokeConstructor node) {
+    List<Expression> arguments = translateArguments(node.arguments);
+    Expression invoke = new InvokeConstructor(
+        node.type,
+        node.target,
+        node.selector,
+        arguments,
+        node.sourceInformation);
+    return makeCallExpression(node, invoke);
+  }
+
+  NodeCallback visitForeignCode(cps_ir.ForeignCode node) {
+    if (node.codeTemplate.isExpression) {
+      Expression foreignCode = new ForeignExpression(
+          node.codeTemplate,
+          node.type,
+          node.arguments.map(getVariableUse).toList(growable: false),
+          node.nativeBehavior,
+          node.dependency);
+      return makeCallExpression(node, foreignCode);
+    } else {
+      return (Statement next) {
+        assert(next is Unreachable); // We are not using the `next` statement.
+        return new ForeignStatement(
+            node.codeTemplate,
+            node.type,
+            node.arguments.map(getVariableUse).toList(growable: false),
+            node.nativeBehavior,
+            node.dependency);
+      };
+    }
+  }
+
+  NodeCallback visitGetLazyStatic(cps_ir.GetLazyStatic node) {
+    // In the tree IR, GetStatic handles lazy fields because we do not need
+    // as fine-grained control over side effects.
+    GetStatic value = new GetStatic(node.element, node.sourceInformation);
+    return makeCallExpression(node, value);
+  }
+
+
+  /************************** TAIL EXPRESSIONS  **************************/
+  //
+  // Visit methods for tail expressions must return a statement directly
+  // (not a function like interior and call expressions).
+
   Statement visitThrow(cps_ir.Throw node) {
     Expression value = getVariableUse(node.value);
     return new Throw(value);
@@ -386,66 +458,6 @@
     return new Unreachable();
   }
 
-  Expression visitNonTailThrow(cps_ir.NonTailThrow node) {
-    return unexpectedNode(node);
-  }
-
-  Statement continueWithExpression(cps_ir.Reference continuation,
-                                   Expression expression) {
-    cps_ir.Continuation cont = continuation.definition;
-    if (cont == returnContinuation) {
-      return new Return(expression);
-    } else {
-      assert(cont.parameters.length == 1);
-      Function nextBuilder = cont.hasExactlyOneUse ?
-          () => visit(cont.body) : () => new Break(labels[cont]);
-      return buildContinuationAssignment(cont.parameters.single, expression,
-          nextBuilder);
-    }
-  }
-
-  Statement visitLetMutable(cps_ir.LetMutable node) {
-    Variable variable = addMutableVariable(node.variable);
-    Expression value = getVariableUse(node.value);
-    Statement body = visit(node.body);
-    return Assign.makeStatement(variable, value, body);
-  }
-
-  Expression visitGetMutable(cps_ir.GetMutable node) {
-    return getMutableVariableUse(node.variable);
-  }
-
-  Expression visitSetMutable(cps_ir.SetMutable node) {
-    Variable variable = getMutableVariable(node.variable.definition);
-    Expression value = getVariableUse(node.value);
-    return new Assign(variable, value);
-  }
-
-  Statement visitTypeCast(cps_ir.TypeCast node) {
-    Expression value = getVariableUse(node.value);
-    List<Expression> typeArgs = translateArguments(node.typeArguments);
-    Expression expression =
-        new TypeOperator(value, node.type, typeArgs, isTypeTest: false);
-    return continueWithExpression(node.continuation, expression);
-  }
-
-  Expression visitTypeTest(cps_ir.TypeTest node) {
-    Expression value = getVariableUse(node.value);
-    List<Expression> typeArgs = translateArguments(node.typeArguments);
-    return new TypeOperator(value, node.type, typeArgs, isTypeTest: true);
-  }
-
-  Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) {
-    List<Expression> arguments = translateArguments(node.arguments);
-    Expression invoke = new InvokeConstructor(
-        node.type,
-        node.target,
-        node.selector,
-        arguments,
-        node.sourceInformation);
-    return continueWithExpression(node.continuation, invoke);
-  }
-
   Statement visitInvokeContinuation(cps_ir.InvokeContinuation node) {
     // Invocations of the return continuation are translated to returns.
     // Other continuation invocations are replaced with assignments of the
@@ -474,35 +486,85 @@
             //     - Translate the recursive invocations to Continue.
             if (cont.isRecursive) {
               return node.isRecursive
-                  ? new Continue(labels[cont])
-                  : new WhileTrue(labels[cont], visit(cont.body));
+                  ? new Continue(getLabel(cont))
+                  : new WhileTrue(getLabel(cont), 
+                                  translateExpression(cont.body));
             } else {
-              if (cont.hasExactlyOneUse) {
-                if (!node.isEscapingTry) {
-                  return visit(cont.body);
-                }
-                labels[cont] = new Label();
-              }
-              return new Break(labels[cont]);
+              return cont.hasExactlyOneUse && !node.isEscapingTry
+                  ? translateExpression(cont.body)
+                  : new Break(getLabel(cont));
             }
           });
     }
   }
 
   Statement visitBranch(cps_ir.Branch node) {
-    Expression condition = visit(node.condition);
+    Expression condition = translateCondition(node.condition);
     Statement thenStatement, elseStatement;
     cps_ir.Continuation cont = node.trueContinuation.definition;
     assert(cont.parameters.isEmpty);
-    thenStatement =
-        cont.hasExactlyOneUse ? visit(cont.body) : new Break(labels[cont]);
+    thenStatement = cont.hasExactlyOneUse 
+        ? translateExpression(cont.body) 
+        : new Break(labels[cont]);
     cont = node.falseContinuation.definition;
     assert(cont.parameters.isEmpty);
-    elseStatement =
-        cont.hasExactlyOneUse ? visit(cont.body) : new Break(labels[cont]);
+    elseStatement = cont.hasExactlyOneUse 
+        ? translateExpression(cont.body) 
+        : new Break(labels[cont]);
     return new If(condition, thenStatement, elseStatement);
   }
 
+
+  /************************** PRIMITIVES  **************************/
+  // 
+  // Visit methods for primitives must return an expression.
+  //
+
+  Expression visitSetField(cps_ir.SetField node) {
+    return new SetField(getVariableUse(node.object),
+                        node.field,
+                        getVariableUse(node.value));
+  }
+  
+  Expression visitInterceptor(cps_ir.Interceptor node) {
+    return new Interceptor(getVariableUse(node.input), 
+                           node.interceptedClasses,
+                           node.sourceInformation);
+  }
+
+  Expression visitCreateInstance(cps_ir.CreateInstance node) {
+    return new CreateInstance(
+        node.classElement,
+        translateArguments(node.arguments),
+        translateArguments(node.typeInformation),
+        node.sourceInformation);
+  }
+
+  Expression visitGetField(cps_ir.GetField node) {
+    return new GetField(getVariableUse(node.object), node.field,
+        objectIsNotNull: node.objectIsNotNull);
+  }
+
+  Expression visitCreateBox(cps_ir.CreateBox node) {
+    return new CreateBox();
+  }
+
+  Expression visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
+    return new CreateInvocationMirror(
+        node.selector,
+        translateArguments(node.arguments));
+  }
+
+  Expression visitGetMutable(cps_ir.GetMutable node) {
+    return getMutableVariableUse(node.variable);
+  }
+
+  Expression visitSetMutable(cps_ir.SetMutable node) {
+    Variable variable = getMutableVariable(node.variable.definition);
+    Expression value = getVariableUse(node.value);
+    return new Assign(variable, value);
+  }
+
   Expression visitConstant(cps_ir.Constant node) {
     return new Constant(node.value, sourceInformation: node.sourceInformation);
   }
@@ -533,28 +595,6 @@
     return new FunctionExpression(def);
   }
 
-  visitParameter(cps_ir.Parameter node) {
-    // Continuation parameters are not visited (continuations themselves are
-    // not visited yet).
-    unexpectedNode(node);
-  }
-
-  visitContinuation(cps_ir.Continuation node) {
-    // Until continuations with multiple uses are supported, they are not
-    // visited.
-    unexpectedNode(node);
-  }
-
-  visitMutableVariable(cps_ir.MutableVariable node) {
-    // These occur as parameters or bound by LetMutable.  They are not visited
-    // directly.
-    unexpectedNode(node);
-  }
-
-  Expression visitIsTrue(cps_ir.IsTrue node) {
-    return getVariableUse(node.value);
-  }
-
   Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
     return new ReifyRuntimeType(
         getVariableUse(node.value), node.sourceInformation);
@@ -567,22 +607,20 @@
         node.sourceInformation);
   }
 
-  @override
-  Node visitTypeExpression(cps_ir.TypeExpression node) {
+  Expression visitTypeExpression(cps_ir.TypeExpression node) {
     return new TypeExpression(
         node.dartType,
         node.arguments.map(getVariableUse).toList());
   }
 
-  Expression visitGetStatic(cps_ir.GetStatic node) {
-    return new GetStatic(node.element, node.sourceInformation);
+  Expression visitTypeTest(cps_ir.TypeTest node) {
+    Expression value = getVariableUse(node.value);
+    List<Expression> typeArgs = translateArguments(node.typeArguments);
+    return new TypeOperator(value, node.type, typeArgs, isTypeTest: true);
   }
 
-  Statement visitGetLazyStatic(cps_ir.GetLazyStatic node) {
-    // In the tree IR, GetStatic handles lazy fields because tree
-    // expressions are allowed to have side effects.
-    GetStatic value = new GetStatic(node.element, node.sourceInformation);
-    return continueWithExpression(node.continuation, value);
+  Expression visitGetStatic(cps_ir.GetStatic node) {
+    return new GetStatic(node.element, node.sourceInformation);
   }
 
   Expression visitSetStatic(cps_ir.SetStatic node) {
@@ -600,26 +638,6 @@
                                     translateArguments(node.arguments));
   }
 
-  Statement visitForeignCode(cps_ir.ForeignCode node) {
-    if (node.codeTemplate.isExpression) {
-      Expression foreignCode = new ForeignExpression(
-          node.codeTemplate,
-          node.type,
-          node.arguments.map(getVariableUse).toList(growable: false),
-          node.nativeBehavior,
-          node.dependency);
-      return continueWithExpression(node.continuation, foreignCode);
-    } else {
-      assert(node.continuation.definition.body is cps_ir.Unreachable);
-      return new ForeignStatement(
-          node.codeTemplate,
-          node.type,
-          node.arguments.map(getVariableUse).toList(growable: false),
-          node.nativeBehavior,
-          node.dependency);
-    }
-  }
-
   Expression visitGetLength(cps_ir.GetLength node) {
     return new GetLength(getVariableUse(node.object));
   }
@@ -634,5 +652,19 @@
                         getVariableUse(node.index),
                         getVariableUse(node.value));
   }
+
+  /********** UNUSED VISIT METHODS *************/
+
+  unexpectedNode(cps_ir.Node node) {
+    internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node');
+  }
+
+  visitFunctionDefinition(cps_ir.FunctionDefinition node) {
+    unexpectedNode(node);
+  }
+  visitParameter(cps_ir.Parameter node) => unexpectedNode(node);
+  visitContinuation(cps_ir.Continuation node) => unexpectedNode(node);
+  visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node);
+  visitIsTrue(cps_ir.IsTrue node) => unexpectedNode(node);
 }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
index 07a5168..c23efd5 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -4,7 +4,6 @@
 
 library tree_ir_nodes;
 
-import '../constants/expressions.dart';
 import '../constants/values.dart' as values;
 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
 import '../elements/elements.dart';
@@ -816,8 +815,9 @@
 class Interceptor extends Expression {
   Expression input;
   Set<ClassElement> interceptedClasses;
+  final SourceInformation sourceInformation;
 
-  Interceptor(this.input, this.interceptedClasses);
+  Interceptor(this.input, this.interceptedClasses, this.sourceInformation);
 
   accept(ExpressionVisitor visitor) {
     return visitor.visitInterceptor(this);
@@ -1108,9 +1108,15 @@
     visitStatement(node.next);
   }
 
-  visitExpressionStatement(ExpressionStatement node) {
-    visitExpression(node.expression);
-    visitStatement(node.next);
+  visitExpressionStatement(ExpressionStatement inputNode) {
+    // Iterate over chains of expression statements to avoid deep recursion.
+    Statement node = inputNode;
+    while (node is ExpressionStatement) {
+      ExpressionStatement stmt = node;
+      visitExpression(stmt.expression);
+      node = stmt.next;
+    }
+    visitStatement(node);
   }
 
   visitTry(Try node) {
@@ -1326,9 +1332,18 @@
   }
 
   visitExpressionStatement(ExpressionStatement node) {
-    node.expression = visitExpression(node.expression);
+    // Iterate over chains of expression statements to avoid deep recursion.
+    Statement first = node;
+    while (true) {
+      node.expression = visitExpression(node.expression);
+      if (node.next is ExpressionStatement) {
+        node = node.next;
+      } else {
+        break;
+      }
+    }
     node.next = visitStatement(node.next);
-    return node;
+    return first;
   }
 
   visitTry(Try node) {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index 63d1a05..f07a030 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -92,7 +92,9 @@
 
   visitBreak(Break node) {
     _addStatement(node);
-    blocks.last.addEdgeTo(breakTargets[node.target]);
+    if (breakTargets.containsKey(node.target)) {
+      blocks.last.addEdgeTo(breakTargets[node.target]);
+    }
   }
 
   visitContinue(Continue node) {
@@ -274,7 +276,9 @@
   }
 
   visitBreak(Break node) {
-    printStatement(null, "break ${collector.breakTargets[node.target].name}");
+    Block block = collector.breakTargets[node.target];
+    String name = block != null ? block.name : '<missing label>';
+    printStatement(null, "break $name");
   }
 
   visitContinue(Continue node) {
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
new file mode 100644
index 0000000..11d9e09
--- /dev/null
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -0,0 +1,165 @@
+// 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.world.class_set;
+
+import 'dart:collection' show IterableBase;
+import '../elements/elements.dart' show ClassElement;
+import '../util/util.dart' show Link;
+
+/// Node for [cls] in a tree forming the subclass relation of [ClassElement]s.
+///
+/// This is used by the [ClassWorld] to perform queries on subclass and subtype
+/// relations.
+// TODO(johnniwinther): Use this for `ClassWorld.subtypesOf`.
+class ClassHierarchyNode {
+  final ClassElement cls;
+
+  /// `true` if [cls] has been directly instantiated.
+  ///
+  /// For instance `C` but _not_ `B` in:
+  ///   class B {}
+  ///   class C extends B {}
+  ///   main() => new C();
+  ///
+  bool isDirectlyInstantiated = false;
+
+  /// `true` if [cls] has been instantiated through subclasses.
+  ///
+  /// For instance `A` and `B` but _not_ `C` in:
+  ///   class A {}
+  ///   class B extends A {}
+  ///   class C extends B {}
+  ///   main() => [new B(), new C()];
+  ///
+  bool isIndirectlyInstantiated = false;
+
+  /// The nodes for the direct subclasses of [cls].
+  Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
+
+  ClassHierarchyNode(this.cls);
+
+  /// Adds [subclass] as a direct subclass of [cls].
+  void addDirectSubclass(ClassHierarchyNode subclass) {
+    assert(subclass.cls.superclass == cls);
+    assert(!_directSubclasses.contains(subclass));
+    _directSubclasses = _directSubclasses.prepend(subclass);
+  }
+
+  /// `true` if [cls] has been directly or indirectly instantiated.
+  bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated;
+
+  /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
+  /// If [directlyInstantiated] is `true`, the iterable only returns the
+  /// directly instantiated subclasses of [cls].
+  Iterable<ClassElement> subclasses({bool directlyInstantiated: true}) {
+    return new ClassHierarchyNodeIterable(
+        this, directlyInstantiatedOnly: directlyInstantiated);
+  }
+
+  /// Returns an [Iterable] of the strict subclasses of [cls] _not_ including
+  /// [cls] itself. If [directlyInstantiated] is `true`, the iterable only
+  /// returns the directly instantiated subclasses of [cls].
+  Iterable<ClassElement> strictSubclasses(
+      {bool directlyInstantiated: true}) {
+    return new ClassHierarchyNodeIterable(this,
+        includeRoot: false, directlyInstantiatedOnly: directlyInstantiated);
+  }
+
+  String toString() => cls.toString();
+}
+
+/// Iterable for subclasses of a [ClassHierarchyNode].
+class ClassHierarchyNodeIterable extends IterableBase<ClassElement> {
+  final ClassHierarchyNode root;
+  final bool includeRoot;
+  final bool directlyInstantiatedOnly;
+
+  ClassHierarchyNodeIterable(
+      this.root,
+      {this.includeRoot: true,
+       this.directlyInstantiatedOnly: false}) {
+    if (root == null) throw new StateError("No root for iterable.");
+  }
+
+  @override
+  Iterator<ClassElement> get iterator {
+    return new ClassHierarchyNodeIterator(this);
+  }
+}
+
+/// Iterator for subclasses of a [ClassHierarchyNode].
+///
+/// Classes are returned in pre-order DFS fashion.
+class ClassHierarchyNodeIterator implements Iterator<ClassElement> {
+  final ClassHierarchyNodeIterable iterable;
+
+  /// The class node holding the [current] class.
+  ///
+  /// This is `null` before the first call to [moveNext] and at the end of
+  /// iteration, i.e. after [moveNext] has returned `false`.
+  ClassHierarchyNode currentNode;
+
+  /// Stack of pending class nodes.
+  ///
+  /// This is `null` before the first call to [moveNext].
+  Link<ClassHierarchyNode> stack;
+
+  ClassHierarchyNodeIterator(this.iterable);
+
+  ClassHierarchyNode get root => iterable.root;
+
+  bool get includeRoot => iterable.includeRoot;
+
+  bool get directlyInstantiatedOnly => iterable.directlyInstantiatedOnly;
+
+  @override
+  ClassElement get current {
+    return currentNode != null ? currentNode.cls : null;
+  }
+
+  @override
+  bool moveNext() {
+    if (stack == null) {
+      // First call to moveNext
+      stack = const Link<ClassHierarchyNode>().prepend(root);
+      return _findNext();
+    } else {
+      // Initialized state.
+      if (currentNode == null) return false;
+      return _findNext();
+    }
+  }
+
+  /// Find the next class using the [stack].
+  bool _findNext() {
+    while (true) {
+      if (stack.isEmpty) {
+        // No more classes. Set [currentNode] to `null` to signal the end of
+        // iteration.
+        currentNode = null;
+        return false;
+      }
+      currentNode = stack.head;
+      stack = stack.tail;
+      for (Link<ClassHierarchyNode> link = currentNode._directSubclasses;
+           !link.isEmpty;
+           link = link.tail) {
+        stack = stack.prepend(link.head);
+      }
+      if (_isValid(currentNode)) {
+        return true;
+      }
+    }
+  }
+
+  /// Returns `true` if the class of [node] is a valid result for this iterator.
+  bool _isValid(ClassHierarchyNode node) {
+    if (!includeRoot && node == root) return false;
+    if (directlyInstantiatedOnly && !node.isDirectlyInstantiated) return false;
+    return true;
+  }
+}
+
+
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index 28715e6..aa90f73 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -4,6 +4,8 @@
 
 library universe;
 
+import 'dart:collection';
+
 import '../elements/elements.dart';
 import '../dart2jslib.dart';
 import '../dart_types.dart';
@@ -277,8 +279,21 @@
     return masks.add(mask);
   }
 
+  Map<Selector, TypeMaskSet> _asUnmodifiable(Map<Selector, TypeMaskSet> map) {
+    if (map == null) return null;
+    return new UnmodifiableMapView(map);
+  }
+
   Map<Selector, TypeMaskSet> invocationsByName(String name) {
-    return _invokedNames[name];
+    return _asUnmodifiable(_invokedNames[name]);
+  }
+
+  Map<Selector, TypeMaskSet> getterInvocationsByName(String name) {
+    return _asUnmodifiable(_invokedGetters[name]);
+  }
+
+  Map<Selector, TypeMaskSet> setterInvocationsByName(String name) {
+    return _asUnmodifiable(_invokedSetters[name]);
   }
 
   void forEachInvokedName(
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index ffbcb5e..570ccf4 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -260,6 +260,8 @@
   source_file_provider.SourceFileProvider sourceFileProvider = null;
   sourceFileProvider.getSourceFile(null);
   world.hasAnyUserDefinedGetter(null, null);
+  world.subclassesOf(null);
+  world.classHierarchyNode(null);
   typeGraphInferrer.getCallersOf(null);
   dart_types.Types.sorted(null);
   new dart_types.Types(compiler).copy(compiler);
@@ -284,8 +286,7 @@
 
 useIr(ir_builder.IrBuilder builder) {
   builder
-    ..buildStringConstant(null)
-    ..buildDynamicGet(null, null, null);
+    ..buildStringConstant(null);
 }
 
 useCompiler(dart2jslib.Compiler compiler) {
diff --git a/pkg/compiler/lib/src/warnings.dart b/pkg/compiler/lib/src/warnings.dart
index e2f2fb3..5e5d603 100644
--- a/pkg/compiler/lib/src/warnings.dart
+++ b/pkg/compiler/lib/src/warnings.dart
@@ -2,9 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of dart2js;
-
-const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
 
 /**
  * The messages in this file should meet the following guide lines:
@@ -63,9 +60,388 @@
  * 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we
  * combine the first two in [template] and the last in [howToFix].
  */
+
+library dart2js.messages;
+
+import 'dart2jslib.dart';
+import 'scanner/scannerlib.dart';
+
+const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
+
+/// Keys for the [MessageTemplate]s.
+enum MessageKind {
+  ABSTRACT_CLASS_INSTANTIATION,
+  ABSTRACT_GETTER,
+  ABSTRACT_METHOD,
+  ABSTRACT_SETTER,
+  ACCESSED_IN_CLOSURE,
+  ACCESSED_IN_CLOSURE_HERE,
+  ADDITIONAL_ARGUMENT,
+  ADDITIONAL_TYPE_ARGUMENT,
+  ALREADY_INITIALIZED,
+  AMBIGUOUS_LOCATION,
+  AMBIGUOUS_REEXPORT,
+  ASSERT_IS_GIVEN_NAMED_ARGUMENTS,
+  ASSIGNING_METHOD,
+  ASSIGNING_METHOD_IN_SUPER,
+  ASSIGNING_TYPE,
+  ASYNC_KEYWORD_AS_IDENTIFIER,
+  ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
+  ASYNC_MODIFIER_ON_CONSTRUCTOR,
+  ASYNC_MODIFIER_ON_SETTER,
+  AWAIT_MEMBER_NOT_FOUND,
+  AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE,
+  BAD_INPUT_CHARACTER,
+  BEFORE_TOP_LEVEL,
+  BINARY_OPERATOR_BAD_ARITY,
+  BODY_EXPECTED,
+  CALL_NOT_SUPPORTED_ON_NATIVE_CLASS,
+  CANNOT_EXTEND,
+  CANNOT_EXTEND_ENUM,
+  CANNOT_EXTEND_MALFORMED,
+  CANNOT_FIND_CONSTRUCTOR,
+  CANNOT_IMPLEMENT,
+  CANNOT_IMPLEMENT_ENUM,
+  CANNOT_IMPLEMENT_MALFORMED,
+  CANNOT_INSTANTIATE_ENUM,
+  CANNOT_INSTANTIATE_TYPE_VARIABLE,
+  CANNOT_INSTANTIATE_TYPEDEF,
+  CANNOT_MIXIN,
+  CANNOT_MIXIN_ENUM,
+  CANNOT_MIXIN_MALFORMED,
+  CANNOT_OVERRIDE_FIELD_WITH_METHOD,
+  CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT,
+  CANNOT_OVERRIDE_GETTER_WITH_METHOD,
+  CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT,
+  CANNOT_OVERRIDE_METHOD_WITH_FIELD,
+  CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT,
+  CANNOT_OVERRIDE_METHOD_WITH_GETTER,
+  CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT,
+  CANNOT_RESOLVE,
+  CANNOT_RESOLVE_AWAIT,
+  CANNOT_RESOLVE_AWAIT_IN_CLOSURE,
+  CANNOT_RESOLVE_CONSTRUCTOR,
+  CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT,
+  CANNOT_RESOLVE_GETTER,
+  CANNOT_RESOLVE_IN_INITIALIZER,
+  CANNOT_RESOLVE_SETTER,
+  CANNOT_RESOLVE_TYPE,
+  CANNOT_RETURN_FROM_CONSTRUCTOR,
+  CLASS_NAME_EXPECTED,
+  COMPILER_CRASHED,
+  COMPLEX_RETURNING_NSM,
+  COMPLEX_THROWING_NSM,
+  CONSIDER_ANALYZE_ALL,
+  CONST_CALLS_NON_CONST,
+  CONST_CALLS_NON_CONST_FOR_IMPLICIT,
+  CONST_CONSTRUCTOR_HAS_BODY,
+  CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
+  CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR,
+  CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD,
+  CONST_MAP_KEY_OVERRIDES_EQUALS,
+  CONST_WITHOUT_INITIALIZER,
+  CONSTRUCTOR_CALL_EXPECTED,
+  CONSTRUCTOR_IS_NOT_CONST,
+  CONSTRUCTOR_WITH_RETURN_TYPE,
+  CYCLIC_CLASS_HIERARCHY,
+  CYCLIC_COMPILE_TIME_CONSTANTS,
+  CYCLIC_REDIRECTING_FACTORY,
+  CYCLIC_TYPE_VARIABLE,
+  CYCLIC_TYPEDEF,
+  CYCLIC_TYPEDEF_ONE,
+  DART_EXT_NOT_SUPPORTED,
+  DEFERRED_COMPILE_TIME_CONSTANT,
+  DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION,
+  DEFERRED_LIBRARY_DART_2_DART,
+  DEFERRED_LIBRARY_DUPLICATE_PREFIX,
+  DEFERRED_LIBRARY_WITHOUT_PREFIX,
+  DEFERRED_OLD_SYNTAX,
+  DEFERRED_TYPE_ANNOTATION,
+  DEPRECATED_TYPEDEF_MIXIN_SYNTAX,
+  DIRECTLY_THROWING_NSM,
+  DUPLICATE_DEFINITION,
+  DUPLICATE_EXPORT,
+  DUPLICATE_EXPORT_CONT,
+  DUPLICATE_EXPORT_DECL,
+  DUPLICATE_EXTENDS_IMPLEMENTS,
+  DUPLICATE_IMPLEMENTS,
+  DUPLICATE_IMPORT,
+  DUPLICATE_INITIALIZER,
+  DUPLICATE_LABEL,
+  DUPLICATE_SUPER_INITIALIZER,
+  DUPLICATE_TYPE_VARIABLE_NAME,
+  DUPLICATED_LIBRARY_NAME,
+  DUPLICATED_LIBRARY_RESOURCE,
+  DUPLICATED_PART_OF,
+  DUPLICATED_RESOURCE,
+  EMPTY_CATCH_DECLARATION,
+  EMPTY_ENUM_DECLARATION,
+  EQUAL_MAP_ENTRY_KEY,
+  EXISTING_DEFINITION,
+  EXISTING_LABEL,
+  EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
+  EXPONENT_MISSING,
+  EXPORT_BEFORE_PARTS,
+  EXTERNAL_WITH_BODY,
+  EXTRA_CATCH_DECLARATION,
+  EXTRA_FORMALS,
+  EXTRANEOUS_MODIFIER,
+  EXTRANEOUS_MODIFIER_REPLACE,
+  FACTORY_REDIRECTION_IN_NON_FACTORY,
+  FINAL_FUNCTION_TYPE_PARAMETER,
+  FINAL_WITHOUT_INITIALIZER,
+  FORMAL_DECLARED_CONST,
+  FORMAL_DECLARED_STATIC,
+  FUNCTION_TYPE_FORMAL_WITH_DEFAULT,
+  FUNCTION_WITH_INITIALIZER,
+  GENERIC,
+  GETTER_MISMATCH,
+  GETTER_NOT_FOUND,
+  HEX_DIGIT_EXPECTED,
+  HIDDEN_HINTS,
+  HIDDEN_IMPLICIT_IMPORT,
+  HIDDEN_IMPORT,
+  HIDDEN_WARNINGS,
+  HIDDEN_WARNINGS_HINTS,
+  IF_NULL_ASSIGNING_TYPE,
+  ILLEGAL_CONST_FIELD_MODIFIER,
+  ILLEGAL_CONSTRUCTOR_MODIFIERS,
+  ILLEGAL_FINAL_METHOD_MODIFIER,
+  ILLEGAL_MIXIN_APPLICATION_MODIFIERS,
+  ILLEGAL_MIXIN_CONSTRUCTOR,
+  ILLEGAL_MIXIN_CYCLE,
+  ILLEGAL_MIXIN_OBJECT,
+  ILLEGAL_MIXIN_SUPER_USE,
+  ILLEGAL_MIXIN_SUPERCLASS,
+  ILLEGAL_MIXIN_WITH_SUPER,
+  ILLEGAL_SETTER_FORMALS,
+  ILLEGAL_STATIC,
+  ILLEGAL_SUPER_SEND,
+  IMPORT_BEFORE_PARTS,
+  IMPORT_EXPERIMENTAL_MIRRORS,
+  IMPORT_PART_OF,
+  IMPORTED_HERE,
+  INHERIT_GETTER_AND_METHOD,
+  INHERITED_EXPLICIT_GETTER,
+  INHERITED_IMPLICIT_GETTER,
+  INHERITED_METHOD,
+  INIT_STATIC_FIELD,
+  INITIALIZING_FORMAL_NOT_ALLOWED,
+  INSTANCE_STATIC_SAME_NAME,
+  INSTANCE_STATIC_SAME_NAME_CONT,
+  INTERNAL_LIBRARY,
+  INTERNAL_LIBRARY_FROM,
+  INVALID_ARGUMENT_AFTER_NAMED,
+  INVALID_AWAIT_FOR,
+  INVALID_BREAK,
+  INVALID_CASE_DEFAULT,
+  INVALID_CONSTRUCTOR_ARGUMENTS,
+  INVALID_CONSTRUCTOR_NAME,
+  INVALID_CONTINUE,
+  INVALID_FOR_IN,
+  INVALID_INITIALIZER,
+  INVALID_OVERRIDDEN_FIELD,
+  INVALID_OVERRIDDEN_GETTER,
+  INVALID_OVERRIDDEN_METHOD,
+  INVALID_OVERRIDDEN_SETTER,
+  INVALID_OVERRIDE_FIELD,
+  INVALID_OVERRIDE_FIELD_WITH_GETTER,
+  INVALID_OVERRIDE_FIELD_WITH_SETTER,
+  INVALID_OVERRIDE_GETTER,
+  INVALID_OVERRIDE_GETTER_WITH_FIELD,
+  INVALID_OVERRIDE_METHOD,
+  INVALID_OVERRIDE_SETTER,
+  INVALID_OVERRIDE_SETTER_WITH_FIELD,
+  INVALID_PACKAGE_URI,
+  INVALID_PARAMETER,
+  INVALID_RECEIVER_IN_INITIALIZER,
+  INVALID_SOURCE_FILE_LOCATION,
+  INVALID_SYMBOL,
+  INVALID_SYNC_MODIFIER,
+  INVALID_TYPE_VARIABLE_BOUND,
+  INVALID_UNNAMED_CONSTRUCTOR_NAME,
+  INVALID_URI,
+  INVALID_USE_OF_SUPER,
+  LIBRARY_NAME_MISMATCH,
+  LIBRARY_NOT_FOUND,
+  LIBRARY_TAG_MUST_BE_FIRST,
+  MAIN_NOT_A_FUNCTION,
+  MAIN_WITH_EXTRA_PARAMETER,
+  MALFORMED_STRING_LITERAL,
+  MEMBER_NOT_FOUND,
+  MEMBER_NOT_STATIC,
+  MEMBER_USES_CLASS_NAME,
+  METHOD_NOT_FOUND,
+  MINUS_OPERATOR_BAD_ARITY,
+  MIRROR_BLOAT,
+  MIRROR_IMPORT,
+  MIRROR_IMPORT_NO_USAGE,
+  MIRRORS_CANNOT_FIND_IN_ELEMENT,
+  MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY,
+  MIRRORS_CANNOT_RESOLVE_IN_LIBRARY,
+  MIRRORS_EXPECTED_STRING,
+  MIRRORS_EXPECTED_STRING_OR_LIST,
+  MIRRORS_EXPECTED_STRING_OR_TYPE,
+  MIRRORS_EXPECTED_STRING_TYPE_OR_LIST,
+  MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND,
+  MISSING_ARGUMENT,
+  MISSING_ENUM_CASES,
+  MISSING_FACTORY_KEYWORD,
+  MISSING_FORMALS,
+  MISSING_LIBRARY_NAME,
+  MISSING_MAIN,
+  MISSING_PART_OF_TAG,
+  MISSING_TOKEN_AFTER_THIS,
+  MISSING_TOKEN_BEFORE_THIS,
+  MISSING_TYPE_ARGUMENT,
+  MULTI_INHERITANCE,
+  NAMED_ARGUMENT_NOT_FOUND,
+  NAMED_FUNCTION_EXPRESSION,
+  NAMED_PARAMETER_WITH_EQUALS,
+  NATIVE_NOT_SUPPORTED,
+  NO_BREAK_TARGET,
+  NO_CATCH_NOR_FINALLY,
+  NO_CONTINUE_TARGET,
+  NO_INSTANCE_AVAILABLE,
+  NO_MATCHING_CONSTRUCTOR,
+  NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT,
+  NO_STATIC_OVERRIDE,
+  NO_STATIC_OVERRIDE_CONT,
+  NO_SUCH_LIBRARY_MEMBER,
+  NO_SUCH_METHOD_IN_NATIVE,
+  NO_SUCH_SUPER_MEMBER,
+  NO_SUPER_IN_STATIC,
+  NO_THIS_AVAILABLE,
+  NON_CONST_BLOAT,
+  NOT_A_COMPILE_TIME_CONSTANT,
+  NOT_A_FIELD,
+  NOT_A_PREFIX,
+  NOT_A_TYPE,
+  NOT_ASSIGNABLE,
+  NOT_CALLABLE,
+  NOT_INSTANCE_FIELD,
+  NOT_MORE_SPECIFIC,
+  NOT_MORE_SPECIFIC_SUBTYPE,
+  NOT_MORE_SPECIFIC_SUGGESTION,
+  NULL_NOT_ALLOWED,
+  ONLY_ONE_LIBRARY_TAG,
+  OPERATOR_NAMED_PARAMETERS,
+  OPERATOR_NOT_FOUND,
+  OPERATOR_OPTIONAL_PARAMETERS,
+  OPTIONAL_PARAMETER_IN_CATCH,
+  OVERRIDE_EQUALS_NOT_HASH_CODE,
+  PARAMETER_NAME_EXPECTED,
+  PARAMETER_WITH_MODIFIER_IN_CATCH,
+  PARAMETER_WITH_TYPE_IN_CATCH,
+  PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION,
+  PATCH_NO_GETTER,
+  PATCH_NO_SETTER,
+  PATCH_NON_CLASS,
+  PATCH_NON_CONSTRUCTOR,
+  PATCH_NON_EXISTING,
+  PATCH_NON_EXTERNAL,
+  PATCH_NON_FUNCTION,
+  PATCH_NON_GETTER,
+  PATCH_NON_SETTER,
+  PATCH_NONPATCHABLE,
+  PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH,
+  PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH,
+  PATCH_PARAMETER_MISMATCH,
+  PATCH_PARAMETER_TYPE_MISMATCH,
+  PATCH_POINT_TO_CLASS,
+  PATCH_POINT_TO_CONSTRUCTOR,
+  PATCH_POINT_TO_FUNCTION,
+  PATCH_POINT_TO_GETTER,
+  PATCH_POINT_TO_PARAMETER,
+  PATCH_POINT_TO_SETTER,
+  PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH,
+  PATCH_RETURN_TYPE_MISMATCH,
+  PLEASE_REPORT_THE_CRASH,
+  POSITIONAL_PARAMETER_WITH_EQUALS,
+  POTENTIAL_MUTATION,
+  POTENTIAL_MUTATION_HERE,
+  POTENTIAL_MUTATION_IN_CLOSURE,
+  POTENTIAL_MUTATION_IN_CLOSURE_HERE,
+  PREAMBLE,
+  PREFIX_AS_EXPRESSION,
+  PRIVATE_ACCESS,
+  PRIVATE_IDENTIFIER,
+  PRIVATE_NAMED_PARAMETER,
+  READ_SCRIPT_ERROR,
+  READ_SELF_ERROR,
+  REDIRECTING_CONSTRUCTOR_CYCLE,
+  REDIRECTING_CONSTRUCTOR_HAS_BODY,
+  REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER,
+  REDIRECTING_FACTORY_WITH_DEFAULT,
+  REFERENCE_IN_INITIALIZATION,
+  REQUIRED_PARAMETER_WITH_DEFAULT,
+  RETURN_IN_GENERATOR,
+  RETURN_NOTHING,
+  RETURN_VALUE_IN_VOID,
+  SETTER_MISMATCH,
+  SETTER_NOT_FOUND,
+  SETTER_NOT_FOUND_IN_SUPER,
+  STATIC_FUNCTION_BLOAT,
+  STRING_EXPECTED,
+  SUPER_INITIALIZER_IN_OBJECT,
+  SWITCH_CASE_FORBIDDEN,
+  SWITCH_CASE_TYPES_NOT_EQUAL,
+  SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
+  SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
+  TERNARY_OPERATOR_BAD_ARITY,
+  THIS_IS_THE_DECLARATION,
+  THIS_IS_THE_METHOD,
+  THIS_IS_THE_PART_OF_TAG,
+  THIS_PROPERTY,
+  THROW_WITHOUT_EXPRESSION,
+  TOP_LEVEL_VARIABLE_DECLARED_STATIC,
+  TYPE_ARGUMENT_COUNT_MISMATCH,
+  TYPE_VARIABLE_IN_CONSTANT,
+  TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
+  TYPEDEF_FORMAL_WITH_DEFAULT,
+  UNARY_OPERATOR_BAD_ARITY,
+  UNBOUND_LABEL,
+  UNIMPLEMENTED_EXPLICIT_GETTER,
+  UNIMPLEMENTED_EXPLICIT_SETTER,
+  UNIMPLEMENTED_GETTER,
+  UNIMPLEMENTED_GETTER_ONE,
+  UNIMPLEMENTED_IMPLICIT_GETTER,
+  UNIMPLEMENTED_IMPLICIT_SETTER,
+  UNIMPLEMENTED_METHOD,
+  UNIMPLEMENTED_METHOD_CONT,
+  UNIMPLEMENTED_METHOD_ONE,
+  UNIMPLEMENTED_SETTER,
+  UNIMPLEMENTED_SETTER_ONE,
+  UNMATCHED_TOKEN,
+  UNSUPPORTED_BANG_EQ_EQ,
+  UNSUPPORTED_EQ_EQ_EQ,
+  UNSUPPORTED_LITERAL_SYMBOL,
+  UNSUPPORTED_PREFIX_PLUS,
+  UNSUPPORTED_THROW_WITHOUT_EXP,
+  UNTERMINATED_COMMENT,
+  UNTERMINATED_STRING,
+  UNTERMINATED_TOKEN,
+  UNUSED_CLASS,
+  UNUSED_LABEL,
+  UNUSED_METHOD,
+  UNUSED_TYPEDEF,
+  VAR_FUNCTION_TYPE_PARAMETER,
+  VOID_EXPRESSION,
+  VOID_NOT_ALLOWED,
+  VOID_VARIABLE,
+  WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT,
+  WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT,
+  YIELDING_MODIFIER_ON_ARROW_BODY,
+}
+
+/// A message template for an error, warning, hint or info message generated
+/// by the compiler. Each template is associated with a [MessageKind] that
+/// uniquely identifies the message template.
 // TODO(johnnniwinther): For Infos, consider adding a reference to the
 // error/warning/hint that they belong to.
-class MessageKind {
+class MessageTemplate {
+  final MessageKind kind;
+
   /// Should describe what is wrong and why.
   final String template;
 
@@ -85,141 +461,180 @@
   /// Additional options needed for the examples to work.
   final List<String> options;
 
-  const MessageKind(this.template,
-                    {this.howToFix,
-                     this.examples,
-                     this.options: const <String>[]});
+  const MessageTemplate(
+      this.kind,
+      this.template,
+      {this.howToFix,
+       this.examples,
+       this.options: const <String>[]});
 
-  /// Do not use this. It is here for legacy and debugging. It violates item 4
-  /// above.
-  static const MessageKind GENERIC = const MessageKind('#{text}');
+  /// All templates used by the compiler.
+  ///
+  /// The map is complete mapping from [MessageKind] to their corresponding
+  /// [MessageTemplate].
+  static const Map<MessageKind, MessageTemplate> TEMPLATES =
+    const <MessageKind, MessageTemplate>{
+      /// Do not use this. It is here for legacy and debugging. It violates item
+      /// 4 of the guide lines for error messages in the beginning of the file.
+      MessageKind.GENERIC:
+        const MessageTemplate(MessageKind.GENERIC, '#{text}'),
 
-  static const MessageKind NOT_ASSIGNABLE = const MessageKind(
-      "'#{fromType}' is not assignable to '#{toType}'.");
+      MessageKind.NOT_ASSIGNABLE:
+        const MessageTemplate(MessageKind.NOT_ASSIGNABLE,
+          "'#{fromType}' is not assignable to '#{toType}'."),
 
-  static const MessageKind VOID_EXPRESSION = const MessageKind(
-      "Expression does not yield a value.");
+      MessageKind.VOID_EXPRESSION:
+        const MessageTemplate(MessageKind.VOID_EXPRESSION,
+          "Expression does not yield a value."),
 
-  static const MessageKind VOID_VARIABLE = const MessageKind(
-      "Variable cannot be of type void.");
+      MessageKind.VOID_VARIABLE:
+        const MessageTemplate(MessageKind.VOID_VARIABLE,
+          "Variable cannot be of type void."),
 
-  static const MessageKind RETURN_VALUE_IN_VOID = const MessageKind(
-      "Cannot return value from void function.");
+      MessageKind.RETURN_VALUE_IN_VOID:
+        const MessageTemplate(MessageKind.RETURN_VALUE_IN_VOID,
+          "Cannot return value from void function."),
 
-  static const MessageKind RETURN_NOTHING = const MessageKind(
-      "Value of type '#{returnType}' expected.");
+      MessageKind.RETURN_NOTHING:
+        const MessageTemplate(MessageKind.RETURN_NOTHING,
+          "Value of type '#{returnType}' expected."),
 
-  static const MessageKind MISSING_ARGUMENT = const MessageKind(
-      "Missing argument of type '#{argumentType}'.");
+      MessageKind.MISSING_ARGUMENT:
+        const MessageTemplate(MessageKind.MISSING_ARGUMENT,
+          "Missing argument of type '#{argumentType}'."),
 
-  static const MessageKind ADDITIONAL_ARGUMENT = const MessageKind(
-      "Additional argument.");
+      MessageKind.ADDITIONAL_ARGUMENT:
+        const MessageTemplate(MessageKind.ADDITIONAL_ARGUMENT,
+          "Additional argument."),
 
-  static const MessageKind NAMED_ARGUMENT_NOT_FOUND = const MessageKind(
-      "No named argument '#{argumentName}' found on method.");
+      MessageKind.NAMED_ARGUMENT_NOT_FOUND:
+        const MessageTemplate(MessageKind.NAMED_ARGUMENT_NOT_FOUND,
+          "No named argument '#{argumentName}' found on method."),
 
-  static const MessageKind MEMBER_NOT_FOUND = const MessageKind(
-      "No member named '#{memberName}' in class '#{className}'.");
+      MessageKind.MEMBER_NOT_FOUND:
+        const MessageTemplate(MessageKind.MEMBER_NOT_FOUND,
+          "No member named '#{memberName}' in class '#{className}'."),
 
-  static const MessageKind AWAIT_MEMBER_NOT_FOUND = const MessageKind(
-      "No member named 'await' in class '#{className}'.",
-      howToFix: "Did you mean to add the 'async' marker "
-                "to '#{functionName}'?",
-      examples: const ["""
+      MessageKind.AWAIT_MEMBER_NOT_FOUND:
+        const MessageTemplate(MessageKind.AWAIT_MEMBER_NOT_FOUND,
+          "No member named 'await' in class '#{className}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to '#{functionName}'?",
+          examples: const ["""
 class A {
   m() => await -3;
 }
 main() => new A().m();
-"""]);
+"""]),
 
-  static const MessageKind AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE =
-      const MessageKind("No member named 'await' in class '#{className}'.",
-      howToFix: "Did you mean to add the 'async' marker "
-                "to the enclosing function?",
-      examples: const ["""
+      MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE:
+        const MessageTemplate(MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE,
+          "No member named 'await' in class '#{className}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to the enclosing function?",
+          examples: const ["""
 class A {
   m() => () => await -3;
 }
 main() => new A().m();
-"""]);
+"""]),
 
-  static const MessageKind METHOD_NOT_FOUND = const MessageKind(
-      "No method named '#{memberName}' in class '#{className}'.");
+      MessageKind.METHOD_NOT_FOUND:
+        const MessageTemplate(MessageKind.METHOD_NOT_FOUND,
+          "No method named '#{memberName}' in class '#{className}'."),
 
-  static const MessageKind OPERATOR_NOT_FOUND = const MessageKind(
-      "No operator '#{memberName}' in class '#{className}'.");
+      MessageKind.OPERATOR_NOT_FOUND:
+        const MessageTemplate(MessageKind.OPERATOR_NOT_FOUND,
+          "No operator '#{memberName}' in class '#{className}'."),
 
-  static const MessageKind SETTER_NOT_FOUND = const MessageKind(
-      "No setter named '#{memberName}' in class '#{className}'.");
+      MessageKind.SETTER_NOT_FOUND:
+        const MessageTemplate(MessageKind.SETTER_NOT_FOUND,
+          "No setter named '#{memberName}' in class '#{className}'."),
 
-  static const MessageKind SETTER_NOT_FOUND_IN_SUPER = const MessageKind(
-      "No setter named '#{name}' in superclass of '#{className}'.");
+      MessageKind.SETTER_NOT_FOUND_IN_SUPER:
+        const MessageTemplate(MessageKind.SETTER_NOT_FOUND_IN_SUPER,
+          "No setter named '#{name}' in superclass of '#{className}'."),
 
-  static const MessageKind GETTER_NOT_FOUND = const MessageKind(
-      "No getter named '#{memberName}' in class '#{className}'.");
+      MessageKind.GETTER_NOT_FOUND:
+        const MessageTemplate(MessageKind.GETTER_NOT_FOUND,
+          "No getter named '#{memberName}' in class '#{className}'."),
 
-  static const MessageKind NOT_CALLABLE = const MessageKind(
-      "'#{elementName}' is not callable.");
+      MessageKind.NOT_CALLABLE:
+        const MessageTemplate(MessageKind.NOT_CALLABLE,
+          "'#{elementName}' is not callable."),
 
-  static const MessageKind MEMBER_NOT_STATIC = const MessageKind(
-      "'#{className}.#{memberName}' is not static.");
+      MessageKind.MEMBER_NOT_STATIC:
+        const MessageTemplate(MessageKind.MEMBER_NOT_STATIC,
+          "'#{className}.#{memberName}' is not static."),
 
-  static const MessageKind NO_INSTANCE_AVAILABLE = const MessageKind(
-      "'#{name}' is only available in instance methods.");
+      MessageKind.NO_INSTANCE_AVAILABLE:
+        const MessageTemplate(MessageKind.NO_INSTANCE_AVAILABLE,
+          "'#{name}' is only available in instance methods."),
 
-  static const MessageKind NO_THIS_AVAILABLE = const MessageKind(
-      "'this' is only available in instance methods.");
+      MessageKind.NO_THIS_AVAILABLE:
+        const MessageTemplate(MessageKind.NO_THIS_AVAILABLE,
+          "'this' is only available in instance methods."),
 
-  static const MessageKind PRIVATE_ACCESS = const MessageKind(
-      "'#{name}' is declared private within library "
-      "'#{libraryName}'.");
+      MessageKind.PRIVATE_ACCESS:
+        const MessageTemplate(MessageKind.PRIVATE_ACCESS,
+          "'#{name}' is declared private within library "
+          "'#{libraryName}'."),
 
-  static const MessageKind THIS_IS_THE_DECLARATION = const MessageKind(
-      "This is the declaration of '#{name}'.");
+      MessageKind.THIS_IS_THE_DECLARATION:
+        const MessageTemplate(MessageKind.THIS_IS_THE_DECLARATION,
+          "This is the declaration of '#{name}'."),
 
-  static const MessageKind THIS_IS_THE_METHOD = const MessageKind(
-      "This is the method declaration.");
+      MessageKind.THIS_IS_THE_METHOD:
+        const MessageTemplate(MessageKind.THIS_IS_THE_METHOD,
+          "This is the method declaration."),
 
-  static const MessageKind CANNOT_RESOLVE = const MessageKind(
-      "Cannot resolve '#{name}'.");
+      MessageKind.CANNOT_RESOLVE:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE,
+          "Cannot resolve '#{name}'."),
 
-  static const MessageKind CANNOT_RESOLVE_AWAIT = const MessageKind(
-      "Cannot resolve '#{name}'.",
-      howToFix: "Did you mean to add the 'async' marker "
-                "to '#{functionName}'?",
-      examples: const [
-          "main() => await -3;",
-          "foo() => await -3; main() => foo();"
-      ]);
+      MessageKind.CANNOT_RESOLVE_AWAIT:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_AWAIT,
+          "Cannot resolve '#{name}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to '#{functionName}'?",
+          examples: const [
+              "main() => await -3;",
+              "foo() => await -3; main() => foo();"
+          ]),
 
-  static const MessageKind CANNOT_RESOLVE_AWAIT_IN_CLOSURE = const MessageKind(
-      "Cannot resolve '#{name}'.",
-      howToFix: "Did you mean to add the 'async' marker "
-                "to the enclosing function?",
-      examples: const [
-          "main() { (() => await -3)(); }",
-      ]);
+      MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE,
+          "Cannot resolve '#{name}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to the enclosing function?",
+          examples: const [
+              "main() { (() => await -3)(); }",
+          ]),
 
-  static const MessageKind CANNOT_RESOLVE_IN_INITIALIZER = const MessageKind(
-      "Cannot resolve '#{name}'. It would be implicitly looked up on this "
-      "instance, but instances are not available in initializers.",
-      howToFix: "Try correcting the unresolved reference or move the "
-          "initialization to a constructor body.",
-      examples: const ["""
+      MessageKind.CANNOT_RESOLVE_IN_INITIALIZER:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_IN_INITIALIZER,
+          "Cannot resolve '#{name}'. It would be implicitly looked up on this "
+          "instance, but instances are not available in initializers.",
+          howToFix: "Try correcting the unresolved reference or move the "
+              "initialization to a constructor body.",
+          examples: const ["""
 class A {
   var test = unresolvedName;
 }
 main() => new A();
-"""]);
+"""]),
 
-  static const MessageKind CANNOT_RESOLVE_CONSTRUCTOR = const MessageKind(
-      "Cannot resolve constructor '#{constructorName}'.");
+      MessageKind.CANNOT_RESOLVE_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_CONSTRUCTOR,
+          "Cannot resolve constructor '#{constructorName}'."),
 
-  static const MessageKind CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT =
-      const MessageKind("cannot resolve constructor '#{constructorName}'"
-          " for implicit super call.",
-      howToFix: "Try explicitly invoking a constructor of the super class",
-      examples: const ["""
+      MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT:
+        const MessageTemplate(
+          MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT,
+          "cannot resolve constructor '#{constructorName}' "
+          "for implicit super call.",
+          howToFix: "Try explicitly invoking a constructor of the super class",
+          examples: const ["""
 class A {
   A.foo() {}
 }
@@ -227,21 +642,25 @@
   B();
 }
 main() => new B();
-"""]);
+"""]),
 
-  static const MessageKind INVALID_UNNAMED_CONSTRUCTOR_NAME = const MessageKind(
-      "Unnamed constructor name must be '#{name}'.");
+      MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME:
+        const MessageTemplate(MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
+          "Unnamed constructor name must be '#{name}'."),
 
-  static const MessageKind INVALID_CONSTRUCTOR_NAME = const MessageKind(
-      "Constructor name must start with '#{name}'.");
+      MessageKind.INVALID_CONSTRUCTOR_NAME:
+        const MessageTemplate(MessageKind.INVALID_CONSTRUCTOR_NAME,
+          "Constructor name must start with '#{name}'."),
 
-  static const MessageKind CANNOT_RESOLVE_TYPE = const MessageKind(
-      "Cannot resolve type '#{typeName}'.");
+      MessageKind.CANNOT_RESOLVE_TYPE:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_TYPE,
+          "Cannot resolve type '#{typeName}'."),
 
-  static const MessageKind DUPLICATE_DEFINITION = const MessageKind(
-      "Duplicate definition of '#{name}'.",
-      howToFix: "Try to rename or remove this definition.",
-      examples: const ["""
+      MessageKind.DUPLICATE_DEFINITION:
+        const MessageTemplate(MessageKind.DUPLICATE_DEFINITION,
+          "Duplicate definition of '#{name}'.",
+          howToFix: "Try to rename or remove this definition.",
+          examples: const ["""
 class C {
   void f() {}
   int get f => 1;
@@ -251,20 +670,24 @@
   new C();
 }
 
-"""]);
+"""]),
 
-  static const MessageKind EXISTING_DEFINITION = const MessageKind(
-      "Existing definition of '#{name}'.");
+      MessageKind.EXISTING_DEFINITION:
+        const MessageTemplate(MessageKind.EXISTING_DEFINITION,
+          "Existing definition of '#{name}'."),
 
-  static const MessageKind DUPLICATE_IMPORT = const MessageKind(
-      "Duplicate import of '#{name}'.");
+      MessageKind.DUPLICATE_IMPORT:
+        const MessageTemplate(MessageKind.DUPLICATE_IMPORT,
+          "Duplicate import of '#{name}'."),
 
-  static const MessageKind HIDDEN_IMPORT = const MessageKind(
-      "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
-      "from library '#{hidingUri}'.",
-      howToFix: "Try adding 'hide #{name}' to the import of '#{hiddenUri}'.",
-      examples: const [
-          const {
+      MessageKind.HIDDEN_IMPORT:
+        const MessageTemplate(MessageKind.HIDDEN_IMPORT,
+          "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
+          "from library '#{hidingUri}'.",
+          howToFix:
+            "Try adding 'hide #{name}' to the import of '#{hiddenUri}'.",
+          examples: const [
+              const {
 'main.dart':
 """
 import 'dart:async'; // This imports a class Future.
@@ -324,16 +747,17 @@
 """
 library future;
 
-class Future {}"""}]);
+class Future {}"""}]),
 
 
-  static const MessageKind HIDDEN_IMPLICIT_IMPORT = const MessageKind(
-      "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
-      "from library '#{hidingUri}'.",
-      howToFix: "Try adding an explicit "
-                "'import \"#{hiddenUri}\" hide #{name}'.",
-      examples: const [
-          const {
+      MessageKind.HIDDEN_IMPLICIT_IMPORT:
+        const MessageTemplate(MessageKind.HIDDEN_IMPLICIT_IMPORT,
+          "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
+          "from library '#{hidingUri}'.",
+          howToFix: "Try adding an explicit "
+                    "'import \"#{hiddenUri}\" hide #{name}'.",
+          examples: const [
+              const {
 'main.dart':
 """
 // This hides the implicit import of class Type from dart:core.
@@ -375,122 +799,150 @@
 main() {
   print("Hail Caesar ${Duration.x}");
 }
-"""}]);
+"""}]),
 
-  static const MessageKind DUPLICATE_EXPORT = const MessageKind(
-      "Duplicate export of '#{name}'.",
-      howToFix: "Trying adding 'hide #{name}' to one of the exports.",
-      examples: const [const {
+      MessageKind.DUPLICATE_EXPORT:
+        const MessageTemplate(MessageKind.DUPLICATE_EXPORT,
+          "Duplicate export of '#{name}'.",
+          howToFix: "Trying adding 'hide #{name}' to one of the exports.",
+          examples: const [const {
 'main.dart': """
 export 'decl1.dart';
 export 'decl2.dart';
 
 main() {}""",
 'decl1.dart': "class Class {}",
-'decl2.dart': "class Class {}"}]);
+'decl2.dart': "class Class {}"}]),
 
-  static const MessageKind DUPLICATE_EXPORT_CONT = const MessageKind(
-      "This is another export of '#{name}'.");
+      MessageKind.DUPLICATE_EXPORT_CONT:
+        const MessageTemplate(MessageKind.DUPLICATE_EXPORT_CONT,
+          "This is another export of '#{name}'."),
 
-  static const MessageKind DUPLICATE_EXPORT_DECL = const MessageKind(
-      "The exported '#{name}' from export #{uriString} is defined here.");
+      MessageKind.DUPLICATE_EXPORT_DECL:
+        const MessageTemplate(MessageKind.DUPLICATE_EXPORT_DECL,
+          "The exported '#{name}' from export #{uriString} is defined here."),
 
-  static const MessageKind NOT_A_TYPE = const MessageKind(
-      "'#{node}' is not a type.");
+      MessageKind.NOT_A_TYPE:
+        const MessageTemplate(MessageKind.NOT_A_TYPE,
+          "'#{node}' is not a type."),
 
-  static const MessageKind NOT_A_PREFIX = const MessageKind(
-      "'#{node}' is not a prefix.");
+      MessageKind.NOT_A_PREFIX:
+        const MessageTemplate(MessageKind.NOT_A_PREFIX,
+          "'#{node}' is not a prefix."),
 
-  static const MessageKind PREFIX_AS_EXPRESSION = const MessageKind(
-      "Library prefix '#{prefix}' is not a valid expression.");
+      MessageKind.PREFIX_AS_EXPRESSION:
+        const MessageTemplate(MessageKind.PREFIX_AS_EXPRESSION,
+          "Library prefix '#{prefix}' is not a valid expression."),
 
-  static const MessageKind CANNOT_FIND_CONSTRUCTOR = const MessageKind(
-      "Cannot find constructor '#{constructorName}'.");
+      MessageKind.CANNOT_FIND_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.CANNOT_FIND_CONSTRUCTOR,
+          "Cannot find constructor '#{constructorName}'."),
 
-  static const MessageKind CYCLIC_CLASS_HIERARCHY = const MessageKind(
-      "'#{className}' creates a cycle in the class hierarchy.");
+      MessageKind.CYCLIC_CLASS_HIERARCHY:
+        const MessageTemplate(MessageKind.CYCLIC_CLASS_HIERARCHY,
+          "'#{className}' creates a cycle in the class hierarchy."),
 
-  static const MessageKind CYCLIC_REDIRECTING_FACTORY = const MessageKind(
-      'Redirecting factory leads to a cyclic redirection.');
+      MessageKind.CYCLIC_REDIRECTING_FACTORY:
+        const MessageTemplate(MessageKind.CYCLIC_REDIRECTING_FACTORY,
+          'Redirecting factory leads to a cyclic redirection.'),
 
-  static const MessageKind INVALID_RECEIVER_IN_INITIALIZER = const MessageKind(
-      "Field initializer expected.");
+      MessageKind.INVALID_RECEIVER_IN_INITIALIZER:
+        const MessageTemplate(MessageKind.INVALID_RECEIVER_IN_INITIALIZER,
+          "Field initializer expected."),
 
-  static const MessageKind NO_SUPER_IN_STATIC = const MessageKind(
-      "'super' is only available in instance methods.");
+      MessageKind.NO_SUPER_IN_STATIC:
+        const MessageTemplate(MessageKind.NO_SUPER_IN_STATIC,
+          "'super' is only available in instance methods."),
 
-  static const MessageKind DUPLICATE_INITIALIZER = const MessageKind(
-      "Field '#{fieldName}' is initialized more than once.");
+      MessageKind.DUPLICATE_INITIALIZER:
+        const MessageTemplate(MessageKind.DUPLICATE_INITIALIZER,
+          "Field '#{fieldName}' is initialized more than once."),
 
-  static const MessageKind ALREADY_INITIALIZED = const MessageKind(
-      "'#{fieldName}' was already initialized here.");
+      MessageKind.ALREADY_INITIALIZED:
+        const MessageTemplate(MessageKind.ALREADY_INITIALIZED,
+          "'#{fieldName}' was already initialized here."),
 
-  static const MessageKind INIT_STATIC_FIELD = const MessageKind(
-      "Cannot initialize static field '#{fieldName}'.");
+      MessageKind.INIT_STATIC_FIELD:
+        const MessageTemplate(MessageKind.INIT_STATIC_FIELD,
+          "Cannot initialize static field '#{fieldName}'."),
 
-  static const MessageKind NOT_A_FIELD = const MessageKind(
-      "'#{fieldName}' is not a field.");
+      MessageKind.NOT_A_FIELD:
+        const MessageTemplate(MessageKind.NOT_A_FIELD,
+          "'#{fieldName}' is not a field."),
 
-  static const MessageKind CONSTRUCTOR_CALL_EXPECTED = const MessageKind(
-      "only call to 'this' or 'super' constructor allowed.");
+      MessageKind.CONSTRUCTOR_CALL_EXPECTED:
+        const MessageTemplate(MessageKind.CONSTRUCTOR_CALL_EXPECTED,
+          "only call to 'this' or 'super' constructor allowed."),
 
-  static const MessageKind INVALID_FOR_IN = const MessageKind(
-      "Invalid for-in variable declaration.");
+      MessageKind.INVALID_FOR_IN:
+        const MessageTemplate(MessageKind.INVALID_FOR_IN,
+          "Invalid for-in variable declaration."),
 
-  static const MessageKind INVALID_INITIALIZER = const MessageKind(
-      "Invalid initializer.");
+      MessageKind.INVALID_INITIALIZER:
+        const MessageTemplate(MessageKind.INVALID_INITIALIZER,
+          "Invalid initializer."),
 
-  static const MessageKind FUNCTION_WITH_INITIALIZER = const MessageKind(
-      "Only constructors can have initializers.");
+      MessageKind.FUNCTION_WITH_INITIALIZER:
+        const MessageTemplate(MessageKind.FUNCTION_WITH_INITIALIZER,
+          "Only constructors can have initializers."),
 
-  static const MessageKind REDIRECTING_CONSTRUCTOR_CYCLE = const MessageKind(
-      "Cyclic constructor redirection.");
+      MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE:
+        const MessageTemplate(MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE,
+          "Cyclic constructor redirection."),
 
-  static const MessageKind REDIRECTING_CONSTRUCTOR_HAS_BODY = const MessageKind(
-      "Redirecting constructor can't have a body.");
+      MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY:
+        const MessageTemplate(MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY,
+          "Redirecting constructor can't have a body."),
 
-  static const MessageKind CONST_CONSTRUCTOR_HAS_BODY = const MessageKind(
-      "Const constructor or factory can't have a body.",
-      howToFix: "Remove the 'const' keyword or the body",
-      examples: const ["""
+      MessageKind.CONST_CONSTRUCTOR_HAS_BODY:
+        const MessageTemplate(MessageKind.CONST_CONSTRUCTOR_HAS_BODY,
+          "Const constructor or factory can't have a body.",
+          howToFix: "Remove the 'const' keyword or the body",
+          examples: const ["""
 class C {
   const C() {}
 }
 
-main() => new C();"""]);
+main() => new C();"""]),
 
-  static const MessageKind REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER =
-      const MessageKind(
-          "Redirecting constructor cannot have other initializers.");
+      MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER:
+        const MessageTemplate(
+          MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER,
+          "Redirecting constructor cannot have other initializers."),
 
-  static const MessageKind SUPER_INITIALIZER_IN_OBJECT = const MessageKind(
-      "'Object' cannot have a super initializer.");
+      MessageKind.SUPER_INITIALIZER_IN_OBJECT:
+        const MessageTemplate(MessageKind.SUPER_INITIALIZER_IN_OBJECT,
+          "'Object' cannot have a super initializer."),
 
-  static const MessageKind DUPLICATE_SUPER_INITIALIZER = const MessageKind(
-      "Cannot have more than one super initializer.");
+      MessageKind.DUPLICATE_SUPER_INITIALIZER:
+        const MessageTemplate(MessageKind.DUPLICATE_SUPER_INITIALIZER,
+          "Cannot have more than one super initializer."),
 
-  static const MessageKind INVALID_CONSTRUCTOR_ARGUMENTS = const MessageKind(
-      "Arguments do not match the expected parameters of constructor "
-      "'#{constructorName}'.");
+      MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS:
+        const MessageTemplate(MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS,
+          "Arguments do not match the expected parameters of constructor "
+          "'#{constructorName}'."),
 
-  static const MessageKind NO_MATCHING_CONSTRUCTOR = const MessageKind(
-      "'super' call arguments and constructor parameters do not match.");
+      MessageKind.NO_MATCHING_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.NO_MATCHING_CONSTRUCTOR,
+          "'super' call arguments and constructor parameters do not match."),
 
-  static const MessageKind NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT =
-      const MessageKind(
-          "Implicit 'super' call arguments and constructor parameters "
-          "do not match.");
+      MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT:
+        const MessageTemplate(MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT,
+              "Implicit 'super' call arguments and constructor parameters "
+              "do not match."),
 
-  static const MessageKind CONST_CALLS_NON_CONST = const MessageKind(
-      "'const' constructor cannot call a non-const constructor.");
+      MessageKind.CONST_CALLS_NON_CONST:
+        const MessageTemplate(MessageKind.CONST_CALLS_NON_CONST,
+          "'const' constructor cannot call a non-const constructor."),
 
-  static const MessageKind CONST_CALLS_NON_CONST_FOR_IMPLICIT =
-      const MessageKind(
-          "'const' constructor cannot call a non-const constructor. "
-          "This constructor has an implicit call to a "
-          "super non-const constructor.",
-          howToFix: "Try making the super constructor const.",
-          examples: const ["""
+      MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT:
+        const MessageTemplate(MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT,
+              "'const' constructor cannot call a non-const constructor. "
+              "This constructor has an implicit call to a "
+              "super non-const constructor.",
+              howToFix: "Try making the super constructor const.",
+              examples: const ["""
 class C {
   C(); // missing const
 }
@@ -498,10 +950,11 @@
   final d;
   const D(this.d);
 }
-main() => new D(0);"""]);
+main() => new D(0);"""]),
 
-  static const MessageKind CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS =
-      const MessageKind(
+      MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS:
+        const MessageTemplate(
+          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
           "Can't declare constructor 'const' on class #{className} "
           "because the class contains non-final instance fields.",
           howToFix: "Try making all fields final.",
@@ -512,89 +965,113 @@
   const C(this.a);
 }
 
-main() => new C(0);"""]);
+main() => new C(0);"""]),
 
-  static const MessageKind CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD =
-      const MessageKind("This non-final field prevents using const "
-                        "constructors.");
+      MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD:
+        const MessageTemplate(
+          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD,
+          "This non-final field prevents using const constructors."),
 
-  static const MessageKind CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR =
-      const MessageKind("This const constructor is not allowed due to "
-                        "non-final fields.");
+      MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR:
+        const MessageTemplate(
+          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR,
+          "This const constructor is not allowed due to "
+          "non-final fields."),
 
 
-  static const MessageKind INITIALIZING_FORMAL_NOT_ALLOWED = const MessageKind(
-      "Initializing formal parameter only allowed in generative "
-      "constructor.");
+      MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED:
+        const MessageTemplate(MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED,
+          "Initializing formal parameter only allowed in generative "
+          "constructor."),
 
-  static const MessageKind INVALID_PARAMETER = const MessageKind(
-      "Cannot resolve parameter.");
+      MessageKind.INVALID_PARAMETER:
+        const MessageTemplate(MessageKind.INVALID_PARAMETER,
+          "Cannot resolve parameter."),
 
-  static const MessageKind NOT_INSTANCE_FIELD = const MessageKind(
-      "'#{fieldName}' is not an instance field.");
+      MessageKind.NOT_INSTANCE_FIELD:
+        const MessageTemplate(MessageKind.NOT_INSTANCE_FIELD,
+          "'#{fieldName}' is not an instance field."),
 
-  static const MessageKind THIS_PROPERTY = const MessageKind(
-      "Expected an identifier.");
+      MessageKind.THIS_PROPERTY:
+        const MessageTemplate(MessageKind.THIS_PROPERTY,
+          "Expected an identifier."),
 
-  static const MessageKind NO_CATCH_NOR_FINALLY = const MessageKind(
-      "Expected 'catch' or 'finally'.");
+      MessageKind.NO_CATCH_NOR_FINALLY:
+        const MessageTemplate(MessageKind.NO_CATCH_NOR_FINALLY,
+          "Expected 'catch' or 'finally'."),
 
-  static const MessageKind EMPTY_CATCH_DECLARATION = const MessageKind(
-      "Expected an identifier in catch declaration.");
+      MessageKind.EMPTY_CATCH_DECLARATION:
+        const MessageTemplate(MessageKind.EMPTY_CATCH_DECLARATION,
+          "Expected an identifier in catch declaration."),
 
-  static const MessageKind EXTRA_CATCH_DECLARATION = const MessageKind(
-      "Extra parameter in catch declaration.");
+      MessageKind.EXTRA_CATCH_DECLARATION:
+        const MessageTemplate(MessageKind.EXTRA_CATCH_DECLARATION,
+          "Extra parameter in catch declaration."),
 
-  static const MessageKind PARAMETER_WITH_TYPE_IN_CATCH = const MessageKind(
-      "Cannot use type annotations in catch.");
+      MessageKind.PARAMETER_WITH_TYPE_IN_CATCH:
+        const MessageTemplate(MessageKind.PARAMETER_WITH_TYPE_IN_CATCH,
+          "Cannot use type annotations in catch."),
 
-  static const MessageKind PARAMETER_WITH_MODIFIER_IN_CATCH = const MessageKind(
-      "Cannot use modifiers in catch.");
+      MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH:
+        const MessageTemplate(MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH,
+          "Cannot use modifiers in catch."),
 
-  static const MessageKind OPTIONAL_PARAMETER_IN_CATCH = const MessageKind(
-      "Cannot use optional parameters in catch.");
+      MessageKind.OPTIONAL_PARAMETER_IN_CATCH:
+        const MessageTemplate(MessageKind.OPTIONAL_PARAMETER_IN_CATCH,
+          "Cannot use optional parameters in catch."),
 
-  static const MessageKind THROW_WITHOUT_EXPRESSION = const MessageKind(
-      "Cannot use re-throw outside of catch block "
-      "(expression expected after 'throw').");
+      MessageKind.THROW_WITHOUT_EXPRESSION:
+        const MessageTemplate(MessageKind.THROW_WITHOUT_EXPRESSION,
+          "Cannot use re-throw outside of catch block "
+          "(expression expected after 'throw')."),
 
-  static const MessageKind UNBOUND_LABEL = const MessageKind(
-      "Cannot resolve label '#{labelName}'.");
+      MessageKind.UNBOUND_LABEL:
+        const MessageTemplate(MessageKind.UNBOUND_LABEL,
+          "Cannot resolve label '#{labelName}'."),
 
-  static const MessageKind NO_BREAK_TARGET = const MessageKind(
-      "'break' statement not inside switch or loop.");
+      MessageKind.NO_BREAK_TARGET:
+        const MessageTemplate(MessageKind.NO_BREAK_TARGET,
+          "'break' statement not inside switch or loop."),
 
-  static const MessageKind NO_CONTINUE_TARGET = const MessageKind(
-      "'continue' statement not inside loop.");
+      MessageKind.NO_CONTINUE_TARGET:
+        const MessageTemplate(MessageKind.NO_CONTINUE_TARGET,
+          "'continue' statement not inside loop."),
 
-  static const MessageKind EXISTING_LABEL = const MessageKind(
-      "Original declaration of duplicate label '#{labelName}'.");
+      MessageKind.EXISTING_LABEL:
+        const MessageTemplate(MessageKind.EXISTING_LABEL,
+          "Original declaration of duplicate label '#{labelName}'."),
 
-  static const MessageKind DUPLICATE_LABEL = const MessageKind(
-      "Duplicate declaration of label '#{labelName}'.");
+      MessageKind.DUPLICATE_LABEL:
+        const MessageTemplate(MessageKind.DUPLICATE_LABEL,
+          "Duplicate declaration of label '#{labelName}'."),
 
-  static const MessageKind UNUSED_LABEL = const MessageKind(
-      "Unused label '#{labelName}'.");
+      MessageKind.UNUSED_LABEL:
+        const MessageTemplate(MessageKind.UNUSED_LABEL,
+          "Unused label '#{labelName}'."),
 
-  static const MessageKind INVALID_CONTINUE = const MessageKind(
-      "Target of continue is not a loop or switch case.");
+      MessageKind.INVALID_CONTINUE:
+        const MessageTemplate(MessageKind.INVALID_CONTINUE,
+          "Target of continue is not a loop or switch case."),
 
-  static const MessageKind INVALID_BREAK = const MessageKind(
-      "Target of break is not a statement.");
+      MessageKind.INVALID_BREAK:
+        const MessageTemplate(MessageKind.INVALID_BREAK,
+          "Target of break is not a statement."),
 
-  static const MessageKind DUPLICATE_TYPE_VARIABLE_NAME = const MessageKind(
-      "Type variable '#{typeVariableName}' already declared.");
+      MessageKind.DUPLICATE_TYPE_VARIABLE_NAME:
+        const MessageTemplate(MessageKind.DUPLICATE_TYPE_VARIABLE_NAME,
+          "Type variable '#{typeVariableName}' already declared."),
 
-  static const MessageKind TYPE_VARIABLE_WITHIN_STATIC_MEMBER =
-      const MessageKind(
-          "Cannot refer to type variable '#{typeVariableName}' "
-          "within a static member.");
+      MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER:
+        const MessageTemplate(MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
+              "Cannot refer to type variable '#{typeVariableName}' "
+              "within a static member."),
 
-  static const MessageKind TYPE_VARIABLE_IN_CONSTANT = const MessageKind(
-      "Constant expressions can't refer to type variables.",
-      howToFix: "Try removing the type variable or replacing it with a "
-                "concrete type.",
-      examples: const ["""
+      MessageKind.TYPE_VARIABLE_IN_CONSTANT:
+        const MessageTemplate(MessageKind.TYPE_VARIABLE_IN_CONSTANT,
+          "Constant expressions can't refer to type variables.",
+          howToFix: "Try removing the type variable or replacing it with a "
+                    "concrete type.",
+          examples: const ["""
 class C<T> {
   const C();
 
@@ -603,74 +1080,88 @@
 
 void main() => new C().m(null);
 """
-]);
+]),
 
-
-  static const MessageKind INVALID_TYPE_VARIABLE_BOUND = const MessageKind(
-      "'#{typeArgument}' is not a subtype of bound '#{bound}' for "
-      "type variable '#{typeVariable}' of type '#{thisType}'.",
-      howToFix: "Try to change or remove the type argument.",
-      examples: const ["""
+      MessageKind.INVALID_TYPE_VARIABLE_BOUND:
+        const MessageTemplate(MessageKind.INVALID_TYPE_VARIABLE_BOUND,
+          "'#{typeArgument}' is not a subtype of bound '#{bound}' for "
+          "type variable '#{typeVariable}' of type '#{thisType}'.",
+          howToFix: "Try to change or remove the type argument.",
+          examples: const ["""
 class C<T extends num> {}
 
 // 'String' is not a valid instantiation of T with bound num.'.
 main() => new C<String>();
-"""]);
+"""]),
 
-  static const MessageKind INVALID_USE_OF_SUPER = const MessageKind(
-      "'super' not allowed here.");
+      MessageKind.INVALID_USE_OF_SUPER:
+        const MessageTemplate(MessageKind.INVALID_USE_OF_SUPER,
+          "'super' not allowed here."),
 
-  static const MessageKind INVALID_CASE_DEFAULT = const MessageKind(
-      "'default' only allowed on last case of a switch.");
+      MessageKind.INVALID_CASE_DEFAULT:
+        const MessageTemplate(MessageKind.INVALID_CASE_DEFAULT,
+          "'default' only allowed on last case of a switch."),
 
-  static const MessageKind SWITCH_CASE_TYPES_NOT_EQUAL = const MessageKind(
-      "'case' expressions do not all have type '#{type}'.");
+      MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL:
+        const MessageTemplate(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL,
+          "'case' expressions do not all have type '#{type}'."),
 
-  static const MessageKind SWITCH_CASE_TYPES_NOT_EQUAL_CASE = const MessageKind(
-      "'case' expression of type '#{type}'.");
+      MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE:
+        const MessageTemplate(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
+          "'case' expression of type '#{type}'."),
 
-  static const MessageKind SWITCH_CASE_FORBIDDEN = const MessageKind(
-      "'case' expression may not be of type '#{type}'.");
+      MessageKind.SWITCH_CASE_FORBIDDEN:
+        const MessageTemplate(MessageKind.SWITCH_CASE_FORBIDDEN,
+          "'case' expression may not be of type '#{type}'."),
 
-  static const MessageKind SWITCH_CASE_VALUE_OVERRIDES_EQUALS =
-      const MessageKind(
-          "'case' expression type '#{type}' overrides 'operator =='.");
+      MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS:
+        const MessageTemplate(MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
+              "'case' expression type '#{type}' overrides 'operator =='."),
 
-  static const MessageKind INVALID_ARGUMENT_AFTER_NAMED = const MessageKind(
-      "Unnamed argument after named argument.");
+      MessageKind.INVALID_ARGUMENT_AFTER_NAMED:
+        const MessageTemplate(MessageKind.INVALID_ARGUMENT_AFTER_NAMED,
+          "Unnamed argument after named argument."),
 
-  static const MessageKind NOT_A_COMPILE_TIME_CONSTANT = const MessageKind(
-      "Not a compile-time constant.");
+      MessageKind.NOT_A_COMPILE_TIME_CONSTANT:
+        const MessageTemplate(MessageKind.NOT_A_COMPILE_TIME_CONSTANT,
+          "Not a compile-time constant."),
 
-  static const MessageKind DEFERRED_COMPILE_TIME_CONSTANT = const MessageKind(
-      "A deferred value cannot be used as a compile-time constant.");
+      MessageKind.DEFERRED_COMPILE_TIME_CONSTANT:
+        const MessageTemplate(MessageKind.DEFERRED_COMPILE_TIME_CONSTANT,
+          "A deferred value cannot be used as a compile-time constant."),
 
-  static const MessageKind DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION =
-      const MessageKind(
+      MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION:
+        const MessageTemplate(
+          MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION,
           "A deferred class cannot be used to create a "
-          "compile-time constant.");
+          "compile-time constant."),
 
-  static const MessageKind CYCLIC_COMPILE_TIME_CONSTANTS = const MessageKind(
-      "Cycle in the compile-time constant computation.");
+      MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS:
+        const MessageTemplate(MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS,
+          "Cycle in the compile-time constant computation."),
 
-  static const MessageKind CONSTRUCTOR_IS_NOT_CONST = const MessageKind(
-      "Constructor is not a 'const' constructor.");
+      MessageKind.CONSTRUCTOR_IS_NOT_CONST:
+        const MessageTemplate(MessageKind.CONSTRUCTOR_IS_NOT_CONST,
+          "Constructor is not a 'const' constructor."),
 
-  static const MessageKind CONST_MAP_KEY_OVERRIDES_EQUALS =
-      const MessageKind(
-          "Const-map key type '#{type}' overrides 'operator =='.");
+      MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS:
+        const MessageTemplate(MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS,
+              "Const-map key type '#{type}' overrides 'operator =='."),
 
-  static const MessageKind NO_SUCH_LIBRARY_MEMBER = const MessageKind(
-      "'#{libraryName}' has no member named '#{memberName}'.");
+      MessageKind.NO_SUCH_LIBRARY_MEMBER:
+        const MessageTemplate(MessageKind.NO_SUCH_LIBRARY_MEMBER,
+          "'#{libraryName}' has no member named '#{memberName}'."),
 
-  static const MessageKind CANNOT_INSTANTIATE_TYPEDEF = const MessageKind(
-      "Cannot instantiate typedef '#{typedefName}'.");
+      MessageKind.CANNOT_INSTANTIATE_TYPEDEF:
+        const MessageTemplate(MessageKind.CANNOT_INSTANTIATE_TYPEDEF,
+          "Cannot instantiate typedef '#{typedefName}'."),
 
-  static const MessageKind REQUIRED_PARAMETER_WITH_DEFAULT = const MessageKind(
-      "Non-optional parameters can't have a default value.",
-      howToFix:
-        "Try removing the default value or making the parameter optional.",
-      examples: const ["""
+      MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT,
+          "Non-optional parameters can't have a default value.",
+          howToFix:
+            "Try removing the default value or making the parameter optional.",
+          examples: const ["""
 main() {
   foo(a: 1) => print(a);
   foo(2);
@@ -678,33 +1169,36 @@
 main() {
   foo(a = 1) => print(a);
   foo(2);
-}"""]);
+}"""]),
 
-  static const MessageKind NAMED_PARAMETER_WITH_EQUALS = const MessageKind(
-      "Named optional parameters can't use '=' to specify a default "
-      "value.",
-      howToFix: "Try replacing '=' with ':'.",
-      examples: const ["""
+      MessageKind.NAMED_PARAMETER_WITH_EQUALS:
+        const MessageTemplate(MessageKind.NAMED_PARAMETER_WITH_EQUALS,
+          "Named optional parameters can't use '=' to specify a default "
+          "value.",
+          howToFix: "Try replacing '=' with ':'.",
+          examples: const ["""
 main() {
   foo({a = 1}) => print(a);
   foo(a: 2);
-}"""]);
+}"""]),
 
-  static const MessageKind POSITIONAL_PARAMETER_WITH_EQUALS = const MessageKind(
-      "Positional optional parameters can't use ':' to specify a "
-      "default value.",
-      howToFix: "Try replacing ':' with '='.",
-      examples: const ["""
+      MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS:
+        const MessageTemplate(MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS,
+          "Positional optional parameters can't use ':' to specify a "
+          "default value.",
+          howToFix: "Try replacing ':' with '='.",
+          examples: const ["""
 main() {
   foo([a: 1]) => print(a);
   foo(2);
-}"""]);
+}"""]),
 
-  static const MessageKind TYPEDEF_FORMAL_WITH_DEFAULT = const MessageKind(
-      "A parameter of a typedef can't specify a default value.",
-      howToFix:
-        "Try removing the default value.",
-      examples: const ["""
+      MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT,
+          "A parameter of a typedef can't specify a default value.",
+          howToFix:
+            "Try removing the default value.",
+          examples: const ["""
 typedef void F([int arg = 0]);
 
 main() {
@@ -714,13 +1208,14 @@
 
 main() {
   F f;
-}"""]);
+}"""]),
 
-  static const MessageKind FUNCTION_TYPE_FORMAL_WITH_DEFAULT = const MessageKind(
-      "A function type parameter can't specify a default value.",
-      howToFix:
-        "Try removing the default value.",
-      examples: const ["""
+      MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT,
+          "A function type parameter can't specify a default value.",
+          howToFix:
+            "Try removing the default value.",
+          examples: const ["""
 foo(f(int i, [a = 1])) {}
 
 main() {
@@ -730,14 +1225,15 @@
 
 main() {
   foo(1, a: 2);
-}"""]);
+}"""]),
 
-  static const MessageKind REDIRECTING_FACTORY_WITH_DEFAULT = const MessageKind(
-      "A parameter of a redirecting factory constructor can't specify a "
-      "default value.",
-      howToFix:
-        "Try removing the default value.",
-      examples: const ["""
+      MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT,
+          "A parameter of a redirecting factory constructor can't specify a "
+          "default value.",
+          howToFix:
+            "Try removing the default value.",
+          examples: const ["""
 class A {
   A([a]);
   factory A.foo([a = 1]) = A;
@@ -753,12 +1249,13 @@
 
 main() {
   new A.foo(a: 1);
-}"""]);
+}"""]),
 
-  static const MessageKind FORMAL_DECLARED_CONST = const MessageKind(
-      "A formal parameter can't be declared const.",
-      howToFix: "Try removing 'const'.",
-      examples: const ["""
+      MessageKind.FORMAL_DECLARED_CONST:
+        const MessageTemplate(MessageKind.FORMAL_DECLARED_CONST,
+          "A formal parameter can't be declared const.",
+          howToFix: "Try removing 'const'.",
+          examples: const ["""
 foo(const x) {}
 main() => foo(42);
 """, """
@@ -767,12 +1264,13 @@
 """, """
 foo([const x]) {}
 main() => foo(42);
-"""]);
+"""]),
 
-  static const MessageKind FORMAL_DECLARED_STATIC = const MessageKind(
-      "A formal parameter can't be declared static.",
-      howToFix: "Try removing 'static'.",
-      examples: const ["""
+      MessageKind.FORMAL_DECLARED_STATIC:
+        const MessageTemplate(MessageKind.FORMAL_DECLARED_STATIC,
+          "A formal parameter can't be declared static.",
+          howToFix: "Try removing 'static'.",
+          examples: const ["""
 foo(static x) {}
 main() => foo(42);
 """, """
@@ -781,12 +1279,13 @@
 """, """
 foo([static x]) {}
 main() => foo(42);
-"""]);
+"""]),
 
-  static const MessageKind FINAL_FUNCTION_TYPE_PARAMETER = const MessageKind(
-      "A function type parameter can't be declared final.",
-      howToFix: "Try removing 'final'.",
-      examples: const ["""
+      MessageKind.FINAL_FUNCTION_TYPE_PARAMETER:
+        const MessageTemplate(MessageKind.FINAL_FUNCTION_TYPE_PARAMETER,
+          "A function type parameter can't be declared final.",
+          howToFix: "Try removing 'final'.",
+          examples: const ["""
 foo(final int x(int a)) {}
 main() => foo((y) => 42);
 """, """
@@ -795,12 +1294,13 @@
 """, """
 foo([final int x(int a)]) {}
 main() => foo((y) => 42);
-"""]);
+"""]),
 
-  static const MessageKind VAR_FUNCTION_TYPE_PARAMETER = const MessageKind(
-      "A function type parameter can't be declared with 'var'.",
-      howToFix: "Try removing 'var'.",
-      examples: const ["""
+      MessageKind.VAR_FUNCTION_TYPE_PARAMETER:
+        const MessageTemplate(MessageKind.VAR_FUNCTION_TYPE_PARAMETER,
+          "A function type parameter can't be declared with 'var'.",
+          howToFix: "Try removing 'var'.",
+          examples: const ["""
 foo(var int x(int a)) {}
 main() => foo((y) => 42);
 """, """
@@ -809,27 +1309,32 @@
 """, """
 foo([var int x(int a)]) {}
 main() => foo((y) => 42);
-"""]);
+"""]),
 
-  static const MessageKind CANNOT_INSTANTIATE_TYPE_VARIABLE = const MessageKind(
-      "Cannot instantiate type variable '#{typeVariableName}'.");
+      MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE:
+        const MessageTemplate(MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
+          "Cannot instantiate type variable '#{typeVariableName}'."),
 
-  static const MessageKind CYCLIC_TYPE_VARIABLE = const MessageKind(
-      "Type variable '#{typeVariableName}' is a supertype of itself.");
+      MessageKind.CYCLIC_TYPE_VARIABLE:
+        const MessageTemplate(MessageKind.CYCLIC_TYPE_VARIABLE,
+          "Type variable '#{typeVariableName}' is a supertype of itself."),
 
-  static const CYCLIC_TYPEDEF = const MessageKind(
-      "A typedef can't refer to itself.",
-      howToFix: "Try removing all references to '#{typedefName}' "
-                "in the definition of '#{typedefName}'.",
-      examples: const ["""
+      MessageKind.CYCLIC_TYPEDEF:
+        const MessageTemplate(MessageKind.CYCLIC_TYPEDEF,
+          "A typedef can't refer to itself.",
+          howToFix: "Try removing all references to '#{typedefName}' "
+                    "in the definition of '#{typedefName}'.",
+          examples: const ["""
 typedef F F(); // The return type 'F' is a self-reference.
-main() { F f = null; }"""]);
+main() { F f = null; }"""]),
 
-  static const CYCLIC_TYPEDEF_ONE = const MessageKind(
-      "A typedef can't refer to itself through another typedef.",
-      howToFix: "Try removing all references to "
-                "'#{otherTypedefName}' in the definition of '#{typedefName}'.",
-      examples: const ["""
+      MessageKind.CYCLIC_TYPEDEF_ONE:
+        const MessageTemplate(MessageKind.CYCLIC_TYPEDEF_ONE,
+          "A typedef can't refer to itself through another typedef.",
+          howToFix:
+            "Try removing all references to "
+            "'#{otherTypedefName}' in the definition of '#{typedefName}'.",
+          examples: const ["""
 typedef G F(); // The return type 'G' is a self-reference through typedef 'G'.
 typedef F G(); // The return type 'F' is a self-reference through typedef 'F'.
 main() { F f = null; }""",
@@ -837,49 +1342,59 @@
 typedef G F(); // The return type 'G' creates a self-reference.
 typedef H G(); // The return type 'H' creates a self-reference.
 typedef H(F f); // The argument type 'F' creates a self-reference.
-main() { F f = null; }"""]);
+main() { F f = null; }"""]),
 
-  static const MessageKind CLASS_NAME_EXPECTED = const MessageKind(
-      "Class name expected.");
+      MessageKind.CLASS_NAME_EXPECTED:
+        const MessageTemplate(MessageKind.CLASS_NAME_EXPECTED,
+          "Class name expected."),
 
-  static const MessageKind CANNOT_EXTEND = const MessageKind(
-      "'#{type}' cannot be extended.");
+      MessageKind.CANNOT_EXTEND:
+        const MessageTemplate(MessageKind.CANNOT_EXTEND,
+          "'#{type}' cannot be extended."),
 
-  static const MessageKind CANNOT_IMPLEMENT = const MessageKind(
-      "'#{type}' cannot be implemented.");
+      MessageKind.CANNOT_IMPLEMENT:
+        const MessageTemplate(MessageKind.CANNOT_IMPLEMENT,
+          "'#{type}' cannot be implemented."),
 
-  // TODO(johnnwinther): Split messages into reasons for malformedness.
-  static const MessageKind CANNOT_EXTEND_MALFORMED = const MessageKind(
-      "Class '#{className}' can't extend the type '#{malformedType}' because "
-      "it is malformed.",
-      howToFix: "Try correcting the malformed type annotation or removing the "
-        "'extends' clause.",
-      examples: const ["""
+      // TODO(johnnwinther): Split messages into reasons for malformedness.
+      MessageKind.CANNOT_EXTEND_MALFORMED:
+        const MessageTemplate(MessageKind.CANNOT_EXTEND_MALFORMED,
+          "Class '#{className}' can't extend the type '#{malformedType}' "
+          "because it is malformed.",
+          howToFix:
+            "Try correcting the malformed type annotation or removing the "
+            "'extends' clause.",
+          examples: const ["""
 class A extends Malformed {}
-main() => new A();"""]);
+main() => new A();"""]),
 
-  static const MessageKind CANNOT_IMPLEMENT_MALFORMED = const MessageKind(
-      "Class '#{className}' can't implement the type '#{malformedType}' "
-      "because it is malformed.",
-      howToFix: "Try correcting the malformed type annotation or removing the "
-        "type from the 'implements' clause.",
-      examples: const ["""
+      MessageKind.CANNOT_IMPLEMENT_MALFORMED:
+        const MessageTemplate(MessageKind.CANNOT_IMPLEMENT_MALFORMED,
+          "Class '#{className}' can't implement the type '#{malformedType}' "
+          "because it is malformed.",
+          howToFix:
+            "Try correcting the malformed type annotation or removing the "
+            "type from the 'implements' clause.",
+          examples: const ["""
 class A implements Malformed {}
-main() => new A();"""]);
+main() => new A();"""]),
 
-  static const MessageKind CANNOT_MIXIN_MALFORMED = const MessageKind(
-      "Class '#{className}' can't mixin the type '#{malformedType}' because it "
-      "is malformed.",
-      howToFix: "Try correcting the malformed type annotation or removing the "
-        "type from the 'with' clause.",
-      examples: const ["""
+      MessageKind.CANNOT_MIXIN_MALFORMED:
+        const MessageTemplate(MessageKind.CANNOT_MIXIN_MALFORMED,
+          "Class '#{className}' can't mixin the type '#{malformedType}' "
+          "because it is malformed.",
+          howToFix:
+            "Try correcting the malformed type annotation or removing the "
+            "type from the 'with' clause.",
+          examples: const ["""
 class A extends Object with Malformed {}
-main() => new A();"""]);
+main() => new A();"""]),
 
-  static const MessageKind CANNOT_MIXIN = const MessageKind(
-      "The type '#{type}' can't be mixed in.",
-      howToFix: "Try removing '#{type}' from the 'with' clause.",
-      examples: const ["""
+      MessageKind.CANNOT_MIXIN:
+        const MessageTemplate(MessageKind.CANNOT_MIXIN,
+          "The type '#{type}' can't be mixed in.",
+          howToFix: "Try removing '#{type}' from the 'with' clause.",
+          examples: const ["""
 class C extends Object with String {}
 
 main() => new C();
@@ -887,60 +1402,66 @@
 typedef C = Object with String;
 
 main() => new C();
-"""]);
+"""]),
 
-  static const MessageKind CANNOT_EXTEND_ENUM = const MessageKind(
-      "Class '#{className}' can't extend the type '#{enumType}' because "
-      "it is declared by an enum.",
-      howToFix: "Try making '#{enumType}' a normal class or removing the "
-        "'extends' clause.",
-      examples: const ["""
+      MessageKind.CANNOT_EXTEND_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_EXTEND_ENUM,
+          "Class '#{className}' can't extend the type '#{enumType}' because "
+          "it is declared by an enum.",
+          howToFix: "Try making '#{enumType}' a normal class or removing the "
+            "'extends' clause.",
+          examples: const ["""
 enum Enum { A }
 class B extends Enum {}
-main() => new B();"""]);
+main() => new B();"""]),
 
-  static const MessageKind CANNOT_IMPLEMENT_ENUM = const MessageKind(
-      "Class '#{className}' can't implement the type '#{enumType}' "
-      "because it is declared by an enum.",
-      howToFix: "Try making '#{enumType}' a normal class or removing the "
-        "type from the 'implements' clause.",
-      examples: const ["""
+      MessageKind.CANNOT_IMPLEMENT_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_IMPLEMENT_ENUM,
+          "Class '#{className}' can't implement the type '#{enumType}' "
+          "because it is declared by an enum.",
+          howToFix: "Try making '#{enumType}' a normal class or removing the "
+            "type from the 'implements' clause.",
+          examples: const ["""
 enum Enum { A }
 class B implements Enum {}
-main() => new B();"""]);
+main() => new B();"""]),
 
-  static const MessageKind CANNOT_MIXIN_ENUM = const MessageKind(
-      "Class '#{className}' can't mixin the type '#{enumType}' because it "
-      "is declared by an enum.",
-      howToFix: "Try making '#{enumType}' a normal class or removing the "
-        "type from the 'with' clause.",
-      examples: const ["""
+      MessageKind.CANNOT_MIXIN_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_MIXIN_ENUM,
+          "Class '#{className}' can't mixin the type '#{enumType}' because it "
+          "is declared by an enum.",
+          howToFix: "Try making '#{enumType}' a normal class or removing the "
+            "type from the 'with' clause.",
+          examples: const ["""
 enum Enum { A }
 class B extends Object with Enum {}
-main() => new B();"""]);
+main() => new B();"""]),
 
-  static const MessageKind CANNOT_INSTANTIATE_ENUM = const MessageKind(
-      "Enum type '#{enumName}' cannot be instantiated.",
-      howToFix: "Try making '#{enumType}' a normal class or use an enum "
-                "constant.",
-      examples: const ["""
+      MessageKind.CANNOT_INSTANTIATE_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_INSTANTIATE_ENUM,
+          "Enum type '#{enumName}' cannot be instantiated.",
+          howToFix: "Try making '#{enumType}' a normal class or use an enum "
+                    "constant.",
+          examples: const ["""
 enum Enum { A }
 main() => new Enum(0);""", """
 enum Enum { A }
-main() => const Enum(0);"""]);
+main() => const Enum(0);"""]),
 
-  static const MessageKind EMPTY_ENUM_DECLARATION = const MessageKind(
-      "Enum '#{enumName}' must contain at least one value.",
-      howToFix: "Try adding an enum constant or making #{enumName} a "
-                "normal class.",
-      examples: const ["""
+      MessageKind.EMPTY_ENUM_DECLARATION:
+        const MessageTemplate(MessageKind.EMPTY_ENUM_DECLARATION,
+          "Enum '#{enumName}' must contain at least one value.",
+          howToFix: "Try adding an enum constant or making #{enumName} a "
+                    "normal class.",
+          examples: const ["""
 enum Enum {}
-main() { Enum e; }"""]);
+main() { Enum e; }"""]),
 
-  static const MessageKind MISSING_ENUM_CASES = const MessageKind(
-      "Missing enum constants in switch statement: #{enumValues}.",
-      howToFix: "Try adding the missing constants or a default case.",
-      examples: const ["""
+      MessageKind.MISSING_ENUM_CASES:
+        const MessageTemplate(MessageKind.MISSING_ENUM_CASES,
+          "Missing enum constants in switch statement: #{enumValues}.",
+          howToFix: "Try adding the missing constants or a default case.",
+          examples: const ["""
 enum Enum { A, B }
 main() {
   switch (Enum.A) {
@@ -952,283 +1473,343 @@
   switch (Enum.A) {
   case Enum.B: break;
   }
-}"""]);
+}"""]),
 
-  static const MessageKind DUPLICATE_EXTENDS_IMPLEMENTS = const MessageKind(
-      "'#{type}' can not be both extended and implemented.");
+      MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS:
+        const MessageTemplate(MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
+          "'#{type}' can not be both extended and implemented."),
 
-  static const MessageKind DUPLICATE_IMPLEMENTS = const MessageKind(
-      "'#{type}' must not occur more than once "
-      "in the implements clause.");
+      MessageKind.DUPLICATE_IMPLEMENTS:
+        const MessageTemplate(MessageKind.DUPLICATE_IMPLEMENTS,
+          "'#{type}' must not occur more than once "
+          "in the implements clause."),
 
-  static const MessageKind MULTI_INHERITANCE = const MessageKind(
-      "Dart2js does not currently support inheritance of the same class with "
-      "different type arguments: Both #{firstType} and #{secondType} are "
-      "supertypes of #{thisType}.");
+      MessageKind.MULTI_INHERITANCE:
+        const MessageTemplate(MessageKind.MULTI_INHERITANCE,
+          "Dart2js does not currently support inheritance of the same class "
+          "with different type arguments: Both #{firstType} and #{secondType} "
+          "are supertypes of #{thisType}."),
 
-  static const MessageKind ILLEGAL_SUPER_SEND = const MessageKind(
-      "'#{name}' cannot be called on super.");
+      MessageKind.ILLEGAL_SUPER_SEND:
+        const MessageTemplate(MessageKind.ILLEGAL_SUPER_SEND,
+          "'#{name}' cannot be called on super."),
 
-  static const MessageKind NO_SUCH_SUPER_MEMBER = const MessageKind(
-      "Cannot resolve '#{memberName}' in a superclass of '#{className}'.");
+      MessageKind.NO_SUCH_SUPER_MEMBER:
+        const MessageTemplate(MessageKind.NO_SUCH_SUPER_MEMBER,
+          "Cannot resolve '#{memberName}' in a superclass of '#{className}'."),
 
-  static const MessageKind ADDITIONAL_TYPE_ARGUMENT = const MessageKind(
-      "Additional type argument.");
+      MessageKind.ADDITIONAL_TYPE_ARGUMENT:
+        const MessageTemplate(MessageKind.ADDITIONAL_TYPE_ARGUMENT,
+          "Additional type argument."),
 
-  static const MessageKind MISSING_TYPE_ARGUMENT = const MessageKind(
-      "Missing type argument.");
+      MessageKind.MISSING_TYPE_ARGUMENT:
+        const MessageTemplate(MessageKind.MISSING_TYPE_ARGUMENT,
+          "Missing type argument."),
 
-  // TODO(johnniwinther): Use ADDITIONAL_TYPE_ARGUMENT or MISSING_TYPE_ARGUMENT
-  // instead.
-  static const MessageKind TYPE_ARGUMENT_COUNT_MISMATCH = const MessageKind(
-      "Incorrect number of type arguments on '#{type}'.");
+      // TODO(johnniwinther): Use ADDITIONAL_TYPE_ARGUMENT or
+      // MISSING_TYPE_ARGUMENT instead.
+      MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH:
+        const MessageTemplate(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
+          "Incorrect number of type arguments on '#{type}'."),
 
-  static const MessageKind GETTER_MISMATCH = const MessageKind(
-      "Setter disagrees on: '#{modifiers}'.");
+      MessageKind.GETTER_MISMATCH:
+        const MessageTemplate(MessageKind.GETTER_MISMATCH,
+          "Setter disagrees on: '#{modifiers}'."),
 
-  static const MessageKind SETTER_MISMATCH = const MessageKind(
-      "Getter disagrees on: '#{modifiers}'.");
+      MessageKind.SETTER_MISMATCH:
+        const MessageTemplate(MessageKind.SETTER_MISMATCH,
+          "Getter disagrees on: '#{modifiers}'."),
 
-  static const MessageKind ILLEGAL_SETTER_FORMALS = const MessageKind(
-      "A setter must have exactly one argument.");
+      MessageKind.ILLEGAL_SETTER_FORMALS:
+        const MessageTemplate(MessageKind.ILLEGAL_SETTER_FORMALS,
+          "A setter must have exactly one argument."),
 
-  static const MessageKind NO_STATIC_OVERRIDE = const MessageKind(
-      "Static member cannot override instance member '#{memberName}' of "
-      "'#{className}'.");
+      MessageKind.NO_STATIC_OVERRIDE:
+        const MessageTemplate(MessageKind.NO_STATIC_OVERRIDE,
+          "Static member cannot override instance member '#{memberName}' of "
+          "'#{className}'."),
 
-  static const MessageKind NO_STATIC_OVERRIDE_CONT = const MessageKind(
-      "This is the instance member that cannot be overridden "
-      "by a static member.");
+      MessageKind.NO_STATIC_OVERRIDE_CONT:
+        const MessageTemplate(MessageKind.NO_STATIC_OVERRIDE_CONT,
+          "This is the instance member that cannot be overridden "
+          "by a static member."),
 
-  static const MessageKind INSTANCE_STATIC_SAME_NAME = const MessageKind(
-      "Instance member '#{memberName}' and static member of "
-      "superclass '#{className}' have the same name.");
+      MessageKind.INSTANCE_STATIC_SAME_NAME:
+        const MessageTemplate(MessageKind.INSTANCE_STATIC_SAME_NAME,
+          "Instance member '#{memberName}' and static member of "
+          "superclass '#{className}' have the same name."),
 
-  static const MessageKind INSTANCE_STATIC_SAME_NAME_CONT = const MessageKind(
-      "This is the static member with the same name.");
+      MessageKind.INSTANCE_STATIC_SAME_NAME_CONT:
+        const MessageTemplate(MessageKind.INSTANCE_STATIC_SAME_NAME_CONT,
+          "This is the static member with the same name."),
 
-  static const MessageKind INVALID_OVERRIDE_METHOD = const MessageKind(
-      "The type '#{declaredType}' of method '#{name}' declared in "
-      "'#{class}' is not a subtype of the overridden method type "
-      "'#{inheritedType}' inherited from '#{inheritedClass}'.");
+      MessageKind.INVALID_OVERRIDE_METHOD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_METHOD,
+          "The type '#{declaredType}' of method '#{name}' declared in "
+          "'#{class}' is not a subtype of the overridden method type "
+          "'#{inheritedType}' inherited from '#{inheritedClass}'."),
 
-  static const MessageKind INVALID_OVERRIDDEN_METHOD = const MessageKind(
-      "This is the overridden method '#{name}' declared in class "
-      "'#{class}'.");
+      MessageKind.INVALID_OVERRIDDEN_METHOD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_METHOD,
+          "This is the overridden method '#{name}' declared in class "
+          "'#{class}'."),
 
-  static const MessageKind INVALID_OVERRIDE_GETTER = const MessageKind(
-      "The type '#{declaredType}' of getter '#{name}' declared in "
-      "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-      "overridden getter inherited from '#{inheritedClass}'.");
-
-  static const MessageKind INVALID_OVERRIDDEN_GETTER = const MessageKind(
-      "This is the overridden getter '#{name}' declared in class "
-      "'#{class}'.");
-
-  static const MessageKind INVALID_OVERRIDE_GETTER_WITH_FIELD =
-      const MessageKind(
-          "The type '#{declaredType}' of field '#{name}' declared in "
-          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-          "overridden getter inherited from '#{inheritedClass}'.");
-
-  static const MessageKind INVALID_OVERRIDE_FIELD_WITH_GETTER =
-      const MessageKind(
+      MessageKind.INVALID_OVERRIDE_GETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_GETTER,
           "The type '#{declaredType}' of getter '#{name}' declared in "
           "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-          "overridden field inherited from '#{inheritedClass}'.");
+          "overridden getter inherited from '#{inheritedClass}'."),
 
-  static const MessageKind INVALID_OVERRIDE_SETTER = const MessageKind(
-      "The type '#{declaredType}' of setter '#{name}' declared in "
-      "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-      "overridden setter inherited from '#{inheritedClass}'.");
+      MessageKind.INVALID_OVERRIDDEN_GETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_GETTER,
+          "This is the overridden getter '#{name}' declared in class "
+          "'#{class}'."),
 
-  static const MessageKind INVALID_OVERRIDDEN_SETTER = const MessageKind(
-      "This is the overridden setter '#{name}' declared in class "
-      "'#{class}'.");
-
-  static const MessageKind INVALID_OVERRIDE_SETTER_WITH_FIELD =
-      const MessageKind(
+      MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD,
           "The type '#{declaredType}' of field '#{name}' declared in "
           "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-          "overridden setter inherited from '#{inheritedClass}'.");
+          "overridden getter inherited from '#{inheritedClass}'."),
 
-  static const MessageKind INVALID_OVERRIDE_FIELD_WITH_SETTER =
-      const MessageKind(
+      MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER,
+          "The type '#{declaredType}' of getter '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden field inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDE_SETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_SETTER,
           "The type '#{declaredType}' of setter '#{name}' declared in "
           "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-          "overridden field inherited from '#{inheritedClass}'.");
+          "overridden setter inherited from '#{inheritedClass}'."),
 
-  static const MessageKind INVALID_OVERRIDE_FIELD = const MessageKind(
-      "The type '#{declaredType}' of field '#{name}' declared in "
-      "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-      "overridden field inherited from '#{inheritedClass}'.");
+      MessageKind.INVALID_OVERRIDDEN_SETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_SETTER,
+          "This is the overridden setter '#{name}' declared in class "
+          "'#{class}'."),
 
-  static const MessageKind INVALID_OVERRIDDEN_FIELD = const MessageKind(
-      "This is the overridden field '#{name}' declared in class "
-      "'#{class}'.");
+      MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD,
+          "The type '#{declaredType}' of field '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden setter inherited from '#{inheritedClass}'."),
 
-  static const MessageKind CANNOT_OVERRIDE_FIELD_WITH_METHOD =
-      const MessageKind(
+      MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER,
+          "The type '#{declaredType}' of setter '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden field inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDE_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_FIELD,
+          "The type '#{declaredType}' of field '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden field inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDDEN_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_FIELD,
+          "This is the overridden field '#{name}' declared in class "
+          "'#{class}'."),
+
+      MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD:
+        const MessageTemplate(MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD,
           "Method '#{name}' in '#{class}' can't override field from "
-          "'#{inheritedClass}'.");
+          "'#{inheritedClass}'."),
 
-  static const MessageKind CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT =
-      const MessageKind(
-          "This is the field that cannot be overridden by a method.");
+      MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT,
+          "This is the field that cannot be overridden by a method."),
 
-  static const MessageKind CANNOT_OVERRIDE_METHOD_WITH_FIELD =
-      const MessageKind(
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD,
           "Field '#{name}' in '#{class}' can't override method from "
-          "'#{inheritedClass}'.");
+          "'#{inheritedClass}'."),
 
-  static const MessageKind CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT =
-      const MessageKind(
-          "This is the method that cannot be overridden by a field.");
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT,
+          "This is the method that cannot be overridden by a field."),
 
-  static const MessageKind CANNOT_OVERRIDE_GETTER_WITH_METHOD =
-      const MessageKind(
-          "Method '#{name}' in '#{class}' can't override getter from "
-          "'#{inheritedClass}'.");
+      MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD:
+        const MessageTemplate(MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD,
+              "Method '#{name}' in '#{class}' can't override getter from "
+              "'#{inheritedClass}'."),
 
-  static const MessageKind CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT =
-      const MessageKind(
-          "This is the getter that cannot be overridden by a method.");
+      MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT,
+          "This is the getter that cannot be overridden by a method."),
 
-  static const MessageKind CANNOT_OVERRIDE_METHOD_WITH_GETTER =
-      const MessageKind(
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER:
+        const MessageTemplate(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER,
           "Getter '#{name}' in '#{class}' can't override method from "
-          "'#{inheritedClass}'.");
+          "'#{inheritedClass}'."),
 
-  static const MessageKind CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT =
-      const MessageKind(
-          "This is the method that cannot be overridden by a getter.");
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT,
+          "This is the method that cannot be overridden by a getter."),
 
-  static const MessageKind MISSING_FORMALS = const MessageKind(
-      "Formal parameters are missing.");
+      MessageKind.MISSING_FORMALS:
+        const MessageTemplate(MessageKind.MISSING_FORMALS,
+          "Formal parameters are missing."),
 
-  static const MessageKind EXTRA_FORMALS = const MessageKind(
-      "Formal parameters are not allowed here.");
+      MessageKind.EXTRA_FORMALS:
+        const MessageTemplate(MessageKind.EXTRA_FORMALS,
+          "Formal parameters are not allowed here."),
 
-  static const MessageKind UNARY_OPERATOR_BAD_ARITY = const MessageKind(
-      "Operator '#{operatorName}' must have no parameters.");
+      MessageKind.UNARY_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.UNARY_OPERATOR_BAD_ARITY,
+          "Operator '#{operatorName}' must have no parameters."),
 
-  static const MessageKind MINUS_OPERATOR_BAD_ARITY = const MessageKind(
-      "Operator '-' must have 0 or 1 parameters.");
+      MessageKind.MINUS_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.MINUS_OPERATOR_BAD_ARITY,
+          "Operator '-' must have 0 or 1 parameters."),
 
-  static const MessageKind BINARY_OPERATOR_BAD_ARITY = const MessageKind(
-      "Operator '#{operatorName}' must have exactly 1 parameter.");
+      MessageKind.BINARY_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.BINARY_OPERATOR_BAD_ARITY,
+          "Operator '#{operatorName}' must have exactly 1 parameter."),
 
-  static const MessageKind TERNARY_OPERATOR_BAD_ARITY = const MessageKind(
-      "Operator '#{operatorName}' must have exactly 2 parameters.");
+      MessageKind.TERNARY_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.TERNARY_OPERATOR_BAD_ARITY,
+          "Operator '#{operatorName}' must have exactly 2 parameters."),
 
-  static const MessageKind OPERATOR_OPTIONAL_PARAMETERS = const MessageKind(
-      "Operator '#{operatorName}' cannot have optional parameters.");
+      MessageKind.OPERATOR_OPTIONAL_PARAMETERS:
+        const MessageTemplate(MessageKind.OPERATOR_OPTIONAL_PARAMETERS,
+          "Operator '#{operatorName}' cannot have optional parameters."),
 
-  static const MessageKind OPERATOR_NAMED_PARAMETERS = const MessageKind(
-      "Operator '#{operatorName}' cannot have named parameters.");
+      MessageKind.OPERATOR_NAMED_PARAMETERS:
+        const MessageTemplate(MessageKind.OPERATOR_NAMED_PARAMETERS,
+          "Operator '#{operatorName}' cannot have named parameters."),
 
-  static const MessageKind CONSTRUCTOR_WITH_RETURN_TYPE = const MessageKind(
-      "Cannot have return type for constructor.");
+      MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE:
+        const MessageTemplate(MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE,
+          "Cannot have return type for constructor."),
 
-  static const MessageKind CANNOT_RETURN_FROM_CONSTRUCTOR = const MessageKind(
-      "Constructors can't return values.",
-      howToFix: "Remove the return statement or use a factory constructor.",
-      examples: const ["""
+      MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR,
+          "Constructors can't return values.",
+          howToFix: "Remove the return statement or use a factory constructor.",
+          examples: const ["""
 class C {
   C() {
     return 1;
   }
 }
 
-main() => new C();"""]);
+main() => new C();"""]),
 
-  static const MessageKind ILLEGAL_FINAL_METHOD_MODIFIER = const MessageKind(
-      "Cannot have final modifier on method.");
+      MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER:
+        const MessageTemplate(MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER,
+          "Cannot have final modifier on method."),
 
-  static const MessageKind ILLEGAL_CONST_FIELD_MODIFIER = const MessageKind(
-      "Cannot have const modifier on non-static field.",
-      howToFix: "Try adding a static modifier, or removing the const modifier.",
-      examples: const ["""
+      MessageKind.ILLEGAL_CONST_FIELD_MODIFIER:
+        const MessageTemplate(MessageKind.ILLEGAL_CONST_FIELD_MODIFIER,
+          "Cannot have const modifier on non-static field.",
+          howToFix:
+            "Try adding a static modifier, or removing the const modifier.",
+          examples: const ["""
 class C {
   const int a = 1;
 }
 
-main() => new C();"""]);
+main() => new C();"""]),
 
-  static const MessageKind ILLEGAL_CONSTRUCTOR_MODIFIERS = const MessageKind(
-      "Illegal constructor modifiers: '#{modifiers}'.");
+      MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS:
+        const MessageTemplate(MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS,
+          "Illegal constructor modifiers: '#{modifiers}'."),
 
-  static const MessageKind ILLEGAL_MIXIN_APPLICATION_MODIFIERS =
-      const MessageKind(
-          "Illegal mixin application modifiers: '#{modifiers}'.");
+      MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS,
+              "Illegal mixin application modifiers: '#{modifiers}'."),
 
-  static const MessageKind ILLEGAL_MIXIN_SUPERCLASS = const MessageKind(
-      "Class used as mixin must have Object as superclass.");
+      MessageKind.ILLEGAL_MIXIN_SUPERCLASS:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_SUPERCLASS,
+          "Class used as mixin must have Object as superclass."),
 
-  static const MessageKind ILLEGAL_MIXIN_OBJECT = const MessageKind(
-      "Cannot use Object as mixin.");
+      MessageKind.ILLEGAL_MIXIN_OBJECT:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_OBJECT,
+          "Cannot use Object as mixin."),
 
-  static const MessageKind ILLEGAL_MIXIN_CONSTRUCTOR = const MessageKind(
-      "Class used as mixin cannot have non-factory constructor.");
+      MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR,
+          "Class used as mixin cannot have non-factory constructor."),
 
-  static const MessageKind ILLEGAL_MIXIN_CYCLE = const MessageKind(
-      "Class used as mixin introduces mixin cycle: "
-      "'#{mixinName1}' <-> '#{mixinName2}'.");
+      MessageKind.ILLEGAL_MIXIN_CYCLE:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_CYCLE,
+          "Class used as mixin introduces mixin cycle: "
+          "'#{mixinName1}' <-> '#{mixinName2}'."),
 
-  static const MessageKind ILLEGAL_MIXIN_WITH_SUPER = const MessageKind(
-      "Cannot use class '#{className}' as a mixin because it uses "
-      "'super'.");
+      MessageKind.ILLEGAL_MIXIN_WITH_SUPER:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_WITH_SUPER,
+          "Cannot use class '#{className}' as a mixin because it uses "
+          "'super'."),
 
-  static const MessageKind ILLEGAL_MIXIN_SUPER_USE = const MessageKind(
-      "Use of 'super' in class used as mixin.");
+      MessageKind.ILLEGAL_MIXIN_SUPER_USE:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_SUPER_USE,
+          "Use of 'super' in class used as mixin."),
 
-  static const MessageKind PARAMETER_NAME_EXPECTED = const MessageKind(
-      "parameter name expected.");
+      MessageKind.PARAMETER_NAME_EXPECTED:
+        const MessageTemplate(MessageKind.PARAMETER_NAME_EXPECTED,
+          "parameter name expected."),
 
-  static const MessageKind CANNOT_RESOLVE_GETTER = const MessageKind(
-      "Cannot resolve getter.");
+      MessageKind.CANNOT_RESOLVE_GETTER:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_GETTER,
+          "Cannot resolve getter."),
 
-  static const MessageKind CANNOT_RESOLVE_SETTER = const MessageKind(
-      "Cannot resolve setter.");
+      MessageKind.CANNOT_RESOLVE_SETTER:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_SETTER,
+          "Cannot resolve setter."),
 
-  static const MessageKind ASSIGNING_METHOD = const MessageKind(
-      "Cannot assign a value to a method.");
+      MessageKind.ASSIGNING_METHOD:
+        const MessageTemplate(MessageKind.ASSIGNING_METHOD,
+          "Cannot assign a value to a method."),
 
-  static const MessageKind ASSIGNING_METHOD_IN_SUPER = const MessageKind(
-      "Cannot assign a value to method '#{name}' "
-      "in superclass '#{superclassName}'.");
+      MessageKind.ASSIGNING_METHOD_IN_SUPER:
+        const MessageTemplate(MessageKind.ASSIGNING_METHOD_IN_SUPER,
+          "Cannot assign a value to method '#{name}' "
+          "in superclass '#{superclassName}'."),
 
-  static const MessageKind ASSIGNING_TYPE = const MessageKind(
-      "Cannot assign a value to a type.");
+      MessageKind.ASSIGNING_TYPE:
+        const MessageTemplate(MessageKind.ASSIGNING_TYPE,
+          "Cannot assign a value to a type."),
 
-  static const MessageKind IF_NULL_ASSIGNING_TYPE = const MessageKind(
-      "Cannot assign a value to a type. Note that types are never null, "
-      "so this ??= assignment has no effect.",
-      howToFix: "Try removing the '??=' assignment.",
-      examples: const [
-          "class A {} main() { print(A ??= 3);}",
-      ]);
+      MessageKind.IF_NULL_ASSIGNING_TYPE:
+        const MessageTemplate(MessageKind.IF_NULL_ASSIGNING_TYPE,
+          "Cannot assign a value to a type. Note that types are never null, "
+          "so this ??= assignment has no effect.",
+          howToFix: "Try removing the '??=' assignment.",
+          examples: const [
+              "class A {} main() { print(A ??= 3);}",
+          ]),
 
-  static const MessageKind VOID_NOT_ALLOWED = const MessageKind(
-      "Type 'void' can't be used here because it isn't a return type.",
-      howToFix: "Try removing 'void' keyword or replace it with 'var', 'final',"
-          " or a type.",
-      examples: const [
-          "void x; main() {}",
-          "foo(void x) {} main() { foo(null); }",
-      ]);
+      MessageKind.VOID_NOT_ALLOWED:
+        const MessageTemplate(MessageKind.VOID_NOT_ALLOWED,
+          "Type 'void' can't be used here because it isn't a return type.",
+          howToFix:
+            "Try removing 'void' keyword or replace it with 'var', 'final', "
+            "or a type.",
+          examples: const [
+              "void x; main() {}",
+              "foo(void x) {} main() { foo(null); }",
+          ]),
 
-  static const MessageKind NULL_NOT_ALLOWED = const MessageKind(
-      "`null` can't be used here.");
+      MessageKind.NULL_NOT_ALLOWED:
+        const MessageTemplate(MessageKind.NULL_NOT_ALLOWED,
+          "`null` can't be used here."),
 
-  static const MessageKind BEFORE_TOP_LEVEL = const MessageKind(
-      "Part header must come before top-level definitions.");
+      MessageKind.BEFORE_TOP_LEVEL:
+        const MessageTemplate(MessageKind.BEFORE_TOP_LEVEL,
+          "Part header must come before top-level definitions."),
 
-  static const MessageKind IMPORT_PART_OF = const MessageKind(
-      "The imported library must not have a 'part-of' directive.",
-      howToFix: "Try removing the 'part-of' directive or replacing the "
-                "import of the library with a 'part' directive.",
-      examples: const [const {
+      MessageKind.IMPORT_PART_OF:
+        const MessageTemplate(MessageKind.IMPORT_PART_OF,
+          "The imported library must not have a 'part-of' directive.",
+          howToFix: "Try removing the 'part-of' directive or replacing the "
+                    "import of the library with a 'part' directive.",
+          examples: const [const {
 'main.dart': """
 library library;
 
@@ -1239,12 +1820,13 @@
 
 'part.dart': """
 part of library;
-"""}]);
+"""}]),
 
-  static const MessageKind LIBRARY_NAME_MISMATCH = const MessageKind(
-      "Expected part of library name '#{libraryName}'.",
-      howToFix: "Try changing the directive to 'part of #{libraryName};'.",
-      examples: const [const {
+      MessageKind.LIBRARY_NAME_MISMATCH:
+        const MessageTemplate(MessageKind.LIBRARY_NAME_MISMATCH,
+          "Expected part of library name '#{libraryName}'.",
+          howToFix: "Try changing the directive to 'part of #{libraryName};'.",
+          examples: const [const {
 'main.dart': """
 library lib.foo;
 
@@ -1255,13 +1837,14 @@
 
 'part.dart': """
 part of lib.bar;
-"""}]);
+"""}]),
 
-  static const MessageKind MISSING_LIBRARY_NAME = const MessageKind(
-      "Library has no name. Part directive expected library name "
-      "to be '#{libraryName}'.",
-      howToFix: "Try adding 'library #{libraryName};' to the library.",
-      examples: const [const {
+      MessageKind.MISSING_LIBRARY_NAME:
+        const MessageTemplate(MessageKind.MISSING_LIBRARY_NAME,
+          "Library has no name. Part directive expected library name "
+          "to be '#{libraryName}'.",
+          howToFix: "Try adding 'library #{libraryName};' to the library.",
+          examples: const [const {
 'main.dart': """
 part 'part.dart';
 
@@ -1270,74 +1853,85 @@
 
 'part.dart': """
 part of lib.foo;
-"""}]);
+"""}]),
 
-  static const MessageKind THIS_IS_THE_PART_OF_TAG = const MessageKind(
-      "This is the part of directive.");
+      MessageKind.THIS_IS_THE_PART_OF_TAG:
+        const MessageTemplate(MessageKind.THIS_IS_THE_PART_OF_TAG,
+          "This is the part of directive."),
 
-  static const MessageKind MISSING_PART_OF_TAG = const MessageKind(
-      "This file has no part-of tag, but it is being used as a part.");
+      MessageKind.MISSING_PART_OF_TAG:
+        const MessageTemplate(MessageKind.MISSING_PART_OF_TAG,
+          "This file has no part-of tag, but it is being used as a part."),
 
-  static const MessageKind DUPLICATED_PART_OF = const MessageKind(
-      "Duplicated part-of directive.");
+      MessageKind.DUPLICATED_PART_OF:
+        const MessageTemplate(MessageKind.DUPLICATED_PART_OF,
+          "Duplicated part-of directive."),
 
-  static const MessageKind DUPLICATED_LIBRARY_NAME = const MessageKind(
-      "Duplicated library name '#{libraryName}'.");
+      MessageKind.DUPLICATED_LIBRARY_NAME:
+        const MessageTemplate(MessageKind.DUPLICATED_LIBRARY_NAME,
+          "Duplicated library name '#{libraryName}'."),
 
-  static const MessageKind DUPLICATED_RESOURCE = const MessageKind(
-      "The resource '#{resourceUri}' is loaded through both "
-      "'#{canonicalUri1}' and '#{canonicalUri2}'.");
+      MessageKind.DUPLICATED_RESOURCE:
+        const MessageTemplate(MessageKind.DUPLICATED_RESOURCE,
+          "The resource '#{resourceUri}' is loaded through both "
+          "'#{canonicalUri1}' and '#{canonicalUri2}'."),
 
-  static const MessageKind DUPLICATED_LIBRARY_RESOURCE =
-      const MessageKind(
+      MessageKind.DUPLICATED_LIBRARY_RESOURCE:
+        const MessageTemplate(MessageKind.DUPLICATED_LIBRARY_RESOURCE,
           "The library '#{libraryName}' in '#{resourceUri}' is loaded through "
-          "both '#{canonicalUri1}' and '#{canonicalUri2}'.");
+          "both '#{canonicalUri1}' and '#{canonicalUri2}'."),
 
-  // This is used as an exception.
-  static const MessageKind INVALID_SOURCE_FILE_LOCATION = const MessageKind('''
+      // This is used as an exception.
+      MessageKind.INVALID_SOURCE_FILE_LOCATION:
+        const MessageTemplate(MessageKind.INVALID_SOURCE_FILE_LOCATION, '''
 Invalid offset (#{offset}) in source map.
 File: #{fileName}
-Length: #{length}''');
+Length: #{length}'''),
 
-  static const MessageKind TOP_LEVEL_VARIABLE_DECLARED_STATIC =
-      const MessageKind(
-          "Top-level variable cannot be declared static.");
+      MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC:
+        const MessageTemplate(MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC,
+              "Top-level variable cannot be declared static."),
 
-  static const MessageKind REFERENCE_IN_INITIALIZATION = const MessageKind(
-       "Variable '#{variableName}' is referenced during its "
-       "initialization.",
-       howToFix: "If you are trying to reference a shadowed variable, rename"
-         " one of the variables.",
-       examples: const ["""
+      MessageKind.REFERENCE_IN_INITIALIZATION:
+        const MessageTemplate(MessageKind.REFERENCE_IN_INITIALIZATION,
+           "Variable '#{variableName}' is referenced during its "
+           "initialization.",
+           howToFix:
+             "If you are trying to reference a shadowed variable, rename "
+             "one of the variables.",
+           examples: const ["""
 foo(t) {
   var t = t;
   return t;
 }
 
 main() => foo(1);
-"""]);
+"""]),
 
-  static const MessageKind CONST_WITHOUT_INITIALIZER = const MessageKind(
-      "A constant variable must be initialized.",
-      howToFix: "Try adding an initializer or "
-                "removing the 'const' modifier.",
-      examples: const ["""
+      MessageKind.CONST_WITHOUT_INITIALIZER:
+        const MessageTemplate(MessageKind.CONST_WITHOUT_INITIALIZER,
+          "A constant variable must be initialized.",
+          howToFix: "Try adding an initializer or "
+                    "removing the 'const' modifier.",
+          examples: const ["""
 void main() {
   const c; // This constant variable must be initialized.
-}"""]);
+}"""]),
 
-  static const MessageKind FINAL_WITHOUT_INITIALIZER = const MessageKind(
-      "A final variable must be initialized.",
-      howToFix: "Try adding an initializer or "
-                "removing the 'final' modifier.",
-      examples: const [
-          "class C { static final field; } main() => C.field;"]);
+      MessageKind.FINAL_WITHOUT_INITIALIZER:
+        const MessageTemplate(MessageKind.FINAL_WITHOUT_INITIALIZER,
+          "A final variable must be initialized.",
+          howToFix: "Try adding an initializer or "
+                    "removing the 'final' modifier.",
+          examples: const [
+              "class C { static final field; } main() => C.field;"]),
 
-  static const MessageKind MEMBER_USES_CLASS_NAME = const MessageKind(
-      "Member variable can't have the same name as the class it is "
-      "declared in.",
-      howToFix: "Try renaming the variable.",
-      examples: const ["""
+      MessageKind.MEMBER_USES_CLASS_NAME:
+        const MessageTemplate(MessageKind.MEMBER_USES_CLASS_NAME,
+          "Member variable can't have the same name as the class it is "
+          "declared in.",
+          howToFix: "Try renaming the variable.",
+          examples: const ["""
 class A { var A; }
 main() {
   var a = new A();
@@ -1346,161 +1940,182 @@
 """, """
 class A { static var A; }
 main() => A.A = 1;
-"""]);
+"""]),
 
-  static const MessageKind WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT =
-      const MessageKind(
+      MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT:
+        const MessageTemplate(
+          MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT,
           "Wrong number of arguments to assert. Should be 1, but given "
-          "#{argumentCount}.");
+          "#{argumentCount}."),
 
-  static const MessageKind ASSERT_IS_GIVEN_NAMED_ARGUMENTS = const MessageKind(
-      "'assert' takes no named arguments, but given #{argumentCount}.");
+      MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS:
+        const MessageTemplate(MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS,
+          "'assert' takes no named arguments, but given #{argumentCount}."),
 
-  static const MessageKind FACTORY_REDIRECTION_IN_NON_FACTORY =
-      const MessageKind(
-          "Factory redirection only allowed in factories.");
+      MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY:
+        const MessageTemplate(MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY,
+          "Factory redirection only allowed in factories."),
 
-  static const MessageKind MISSING_FACTORY_KEYWORD = const MessageKind(
-      "Did you forget a factory keyword here?");
+      MessageKind.MISSING_FACTORY_KEYWORD:
+        const MessageTemplate(MessageKind.MISSING_FACTORY_KEYWORD,
+          "Did you forget a factory keyword here?"),
 
-  static const MessageKind NO_SUCH_METHOD_IN_NATIVE =
-      const MessageKind(
+      MessageKind.NO_SUCH_METHOD_IN_NATIVE:
+        const MessageTemplate(MessageKind.NO_SUCH_METHOD_IN_NATIVE,
           "'NoSuchMethod' is not supported for classes that extend native "
-          "classes.");
+          "classes."),
 
-  static const MessageKind DEFERRED_LIBRARY_DART_2_DART =
-      const MessageKind(
+      MessageKind.DEFERRED_LIBRARY_DART_2_DART:
+        const MessageTemplate(MessageKind.DEFERRED_LIBRARY_DART_2_DART,
           "Deferred loading is not supported by the dart backend yet. "
-          "The output will not be split.");
+          "The output will not be split."),
 
-  static const MessageKind DEFERRED_LIBRARY_WITHOUT_PREFIX =
-      const MessageKind(
+      MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX:
+        const MessageTemplate(MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX,
           "This import is deferred but there is no prefix keyword.",
-          howToFix:
-            "Try adding a prefix to the import.");
+          howToFix: "Try adding a prefix to the import."),
 
-  static const MessageKind DEFERRED_OLD_SYNTAX =
-      const MessageKind(
+      MessageKind.DEFERRED_OLD_SYNTAX:
+        const MessageTemplate(MessageKind.DEFERRED_OLD_SYNTAX,
           "The DeferredLibrary annotation is obsolete.",
           howToFix:
-            "Use the \"import 'lib.dart' deferred as prefix\" syntax instead.");
+            "Use the \"import 'lib.dart' deferred as prefix\" syntax instead."),
 
-  static const MessageKind DEFERRED_LIBRARY_DUPLICATE_PREFIX =
-      const MessageKind(
+      MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX:
+        const MessageTemplate(MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX,
           "The prefix of this deferred import is not unique.",
-          howToFix:
-            "Try changing the import prefix.");
+          howToFix: "Try changing the import prefix."),
 
-  static const MessageKind DEFERRED_TYPE_ANNOTATION =
-      const MessageKind(
+      MessageKind.DEFERRED_TYPE_ANNOTATION:
+        const MessageTemplate(MessageKind.DEFERRED_TYPE_ANNOTATION,
           "The type #{node} is deferred. "
           "Deferred types are not valid as type annotations.",
           howToFix:
-            "Try using a non-deferred abstract class as an interface.");
+            "Try using a non-deferred abstract class as an interface."),
 
-  static const MessageKind ILLEGAL_STATIC = const MessageKind(
-      "Modifier static is only allowed on functions declared in "
-      "a class.");
+      MessageKind.ILLEGAL_STATIC:
+        const MessageTemplate(MessageKind.ILLEGAL_STATIC,
+          "Modifier static is only allowed on functions declared in "
+          "a class."),
 
-  static const MessageKind STATIC_FUNCTION_BLOAT = const MessageKind(
-      "Using '#{class}.#{name}' may lead to unnecessarily large "
-      "generated code.",
-      howToFix:
-          "Try adding '@MirrorsUsed(...)' as described at "
-          "https://goo.gl/Akrrog.");
+      MessageKind.STATIC_FUNCTION_BLOAT:
+        const MessageTemplate(MessageKind.STATIC_FUNCTION_BLOAT,
+          "Using '#{class}.#{name}' may lead to unnecessarily large "
+          "generated code.",
+          howToFix:
+              "Try adding '@MirrorsUsed(...)' as described at "
+              "https://goo.gl/Akrrog."),
 
-  static const MessageKind NON_CONST_BLOAT = const MessageKind(
-      "Using 'new #{name}' may lead to unnecessarily large generated "
-      "code.",
-      howToFix:
-          "Try using 'const #{name}' or adding '@MirrorsUsed(...)' as "
-          "described at https://goo.gl/Akrrog.");
+      MessageKind.NON_CONST_BLOAT:
+        const MessageTemplate(MessageKind.NON_CONST_BLOAT,
+          "Using 'new #{name}' may lead to unnecessarily large generated "
+          "code.",
+          howToFix:
+              "Try using 'const #{name}' or adding '@MirrorsUsed(...)' as "
+              "described at https://goo.gl/Akrrog."),
 
-  static const MessageKind STRING_EXPECTED = const MessageKind(
-      "Expected a 'String', but got an instance of '#{type}'.");
+      MessageKind.STRING_EXPECTED:
+        const MessageTemplate(MessageKind.STRING_EXPECTED,
+          "Expected a 'String', but got an instance of '#{type}'."),
 
-  static const MessageKind PRIVATE_IDENTIFIER = const MessageKind(
-      "'#{value}' is not a valid Symbol name because it starts with "
-      "'_'.");
+      MessageKind.PRIVATE_IDENTIFIER:
+        const MessageTemplate(MessageKind.PRIVATE_IDENTIFIER,
+          "'#{value}' is not a valid Symbol name because it starts with "
+          "'_'."),
 
-  static const MessageKind PRIVATE_NAMED_PARAMETER = const MessageKind(
-      "Named optional parameter can't have a library private name.",
-      howToFix: "Try removing the '_' or making the parameter positional or "
-        "required.",
-      examples: const ["""foo({int _p}) {} main() => foo();"""]
-      );
+      MessageKind.PRIVATE_NAMED_PARAMETER:
+        const MessageTemplate(MessageKind.PRIVATE_NAMED_PARAMETER,
+          "Named optional parameter can't have a library private name.",
+          howToFix:
+            "Try removing the '_' or making the parameter positional or "
+            "required.",
+          examples: const ["""foo({int _p}) {} main() => foo();"""]),
 
-  static const MessageKind UNSUPPORTED_LITERAL_SYMBOL = const MessageKind(
-      "Symbol literal '##{value}' is currently unsupported by dart2js.");
+      MessageKind.UNSUPPORTED_LITERAL_SYMBOL:
+        const MessageTemplate(MessageKind.UNSUPPORTED_LITERAL_SYMBOL,
+          "Symbol literal '##{value}' is currently unsupported by dart2js."),
 
-  static const MessageKind INVALID_SYMBOL = const MessageKind('''
+      MessageKind.INVALID_SYMBOL:
+        const MessageTemplate(MessageKind.INVALID_SYMBOL, '''
 '#{value}' is not a valid Symbol name because is not:
  * an empty String,
  * a user defined operator,
  * a qualified non-private identifier optionally followed by '=', or
  * a qualified non-private identifier followed by '.' and a user-defined '''
-"operator.");
+"operator."),
 
-  static const MessageKind AMBIGUOUS_REEXPORT = const MessageKind(
-      "'#{name}' is (re)exported by multiple libraries.");
+      MessageKind.AMBIGUOUS_REEXPORT:
+        const MessageTemplate(MessageKind.AMBIGUOUS_REEXPORT,
+          "'#{name}' is (re)exported by multiple libraries."),
 
-  static const MessageKind AMBIGUOUS_LOCATION = const MessageKind(
-      "'#{name}' is defined here.");
+      MessageKind.AMBIGUOUS_LOCATION:
+        const MessageTemplate(MessageKind.AMBIGUOUS_LOCATION,
+          "'#{name}' is defined here."),
 
-  static const MessageKind IMPORTED_HERE = const MessageKind(
-      "'#{name}' is imported here.");
+      MessageKind.IMPORTED_HERE:
+        const MessageTemplate(MessageKind.IMPORTED_HERE,
+          "'#{name}' is imported here."),
 
-  static const MessageKind OVERRIDE_EQUALS_NOT_HASH_CODE = const MessageKind(
-      "The class '#{class}' overrides 'operator==', "
-      "but not 'get hashCode'.");
+      MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE:
+        const MessageTemplate(MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
+          "The class '#{class}' overrides 'operator==', "
+          "but not 'get hashCode'."),
 
-  static const MessageKind INTERNAL_LIBRARY_FROM = const MessageKind(
-      "Internal library '#{resolvedUri}' is not accessible from "
-      "'#{importingUri}'.");
+      MessageKind.INTERNAL_LIBRARY_FROM:
+        const MessageTemplate(MessageKind.INTERNAL_LIBRARY_FROM,
+          "Internal library '#{resolvedUri}' is not accessible from "
+          "'#{importingUri}'."),
 
-  static const MessageKind INTERNAL_LIBRARY = const MessageKind(
-      "Internal library '#{resolvedUri}' is not accessible.");
+      MessageKind.INTERNAL_LIBRARY:
+        const MessageTemplate(MessageKind.INTERNAL_LIBRARY,
+          "Internal library '#{resolvedUri}' is not accessible."),
 
-  static const MessageKind LIBRARY_NOT_FOUND = const MessageKind(
-      "Library not found '#{resolvedUri}'.");
+      MessageKind.LIBRARY_NOT_FOUND:
+        const MessageTemplate(MessageKind.LIBRARY_NOT_FOUND,
+          "Library not found '#{resolvedUri}'."),
 
-  static const MessageKind UNSUPPORTED_EQ_EQ_EQ = const MessageKind(
-      "'===' is not an operator. "
-      "Did you mean '#{lhs} == #{rhs}' or 'identical(#{lhs}, #{rhs})'?");
+      MessageKind.UNSUPPORTED_EQ_EQ_EQ:
+        const MessageTemplate(MessageKind.UNSUPPORTED_EQ_EQ_EQ,
+          "'===' is not an operator. "
+          "Did you mean '#{lhs} == #{rhs}' or 'identical(#{lhs}, #{rhs})'?"),
 
-  static const MessageKind UNSUPPORTED_BANG_EQ_EQ = const MessageKind(
-      "'!==' is not an operator. "
-      "Did you mean '#{lhs} != #{rhs}' or '!identical(#{lhs}, #{rhs})'?");
+      MessageKind.UNSUPPORTED_BANG_EQ_EQ:
+        const MessageTemplate(MessageKind.UNSUPPORTED_BANG_EQ_EQ,
+          "'!==' is not an operator. "
+          "Did you mean '#{lhs} != #{rhs}' or '!identical(#{lhs}, #{rhs})'?"),
 
-  static const MessageKind UNSUPPORTED_PREFIX_PLUS = const MessageKind(
-      "'+' is not a prefix operator. ",
-      howToFix: "Try removing '+'.",
-      examples: const [
-          "main() => +2;  // No longer a valid way to write '2'"
-      ]);
+      MessageKind.UNSUPPORTED_PREFIX_PLUS:
+        const MessageTemplate(MessageKind.UNSUPPORTED_PREFIX_PLUS,
+          "'+' is not a prefix operator. ",
+          howToFix: "Try removing '+'.",
+          examples: const [
+              "main() => +2;  // No longer a valid way to write '2'"
+          ]),
 
-  static const MessageKind UNSUPPORTED_THROW_WITHOUT_EXP = const MessageKind(
-      "No expression after 'throw'. "
-      "Did you mean 'rethrow'?");
+      MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP:
+        const MessageTemplate(MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP,
+          "No expression after 'throw'. "
+          "Did you mean 'rethrow'?"),
 
-  static const MessageKind DEPRECATED_TYPEDEF_MIXIN_SYNTAX = const MessageKind(
-      "'typedef' not allowed here. ",
-      howToFix: "Try replacing 'typedef' with 'class'.",
-      examples: const [
-          """
+      MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX:
+        const MessageTemplate(MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX,
+          "'typedef' not allowed here. ",
+          howToFix: "Try replacing 'typedef' with 'class'.",
+          examples: const [
+              """
 class B { }
 class M1 {  }
 typedef C = B with M1;  // Need to replace 'typedef' with 'class'.
 main() { new C(); }
-"""]
-);
+"""]),
 
-  static const MessageKind MIRRORS_EXPECTED_STRING = const MessageKind(
-      "Can't use '#{name}' here because it's an instance of '#{type}' "
-      "and a 'String' value is expected.",
-      howToFix: "Did you forget to add quotes?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_EXPECTED_STRING:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "and a 'String' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
 // 'Foo' is a type literal, not a string.
 @MirrorsUsed(symbols: const [Foo])
 import 'dart:mirrors';
@@ -1508,27 +2123,29 @@
 class Foo {}
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind MIRRORS_EXPECTED_STRING_OR_TYPE = const MessageKind(
-      "Can't use '#{name}' here because it's an instance of '#{type}' "
-      "and a 'String' or 'Type' value is expected.",
-      howToFix: "Did you forget to add quotes?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "and a 'String' or 'Type' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
 // 'main' is a method, not a class.
 @MirrorsUsed(targets: const [main])
 import 'dart:mirrors';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind MIRRORS_EXPECTED_STRING_OR_LIST = const MessageKind(
-      "Can't use '#{name}' here because it's an instance of '#{type}' "
-      "and a 'String' or 'List' value is expected.",
-      howToFix: "Did you forget to add quotes?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "and a 'String' or 'List' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
 // 'Foo' is not a string.
 @MirrorsUsed(symbols: Foo)
 import 'dart:mirrors';
@@ -1536,80 +2153,83 @@
 class Foo {}
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind MIRRORS_EXPECTED_STRING_TYPE_OR_LIST =
-      const MessageKind(
-      "Can't use '#{name}' here because it's an instance of '#{type}' "
-      "but a 'String', 'Type', or 'List' value is expected.",
-      howToFix: "Did you forget to add quotes?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "but a 'String', 'Type', or 'List' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
 // '1' is not a string.
 @MirrorsUsed(targets: 1)
 import 'dart:mirrors';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY =
-      const MessageKind(
-      "Can't find '#{name}' in the current library.",
-      // TODO(ahe): The closest identifiers in edit distance would be nice.
-      howToFix: "Did you forget to add an import?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY:
+        const MessageTemplate(
+          MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY,
+          "Can't find '#{name}' in the current library.",
+          // TODO(ahe): The closest identifiers in edit distance would be nice.
+          howToFix: "Did you forget to add an import?",
+          examples: const [
+              """
 // 'window' is not in scope because dart:html isn't imported.
 @MirrorsUsed(targets: 'window')
 import 'dart:mirrors';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind MIRRORS_CANNOT_RESOLVE_IN_LIBRARY =
-      const MessageKind(
-      "Can't find '#{name}' in the library '#{library}'.",
-      // TODO(ahe): The closest identifiers in edit distance would be nice.
-      howToFix: "Is '#{name}' spelled right?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY:
+        const MessageTemplate(MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY,
+          "Can't find '#{name}' in the library '#{library}'.",
+          // TODO(ahe): The closest identifiers in edit distance would be nice.
+          howToFix: "Is '#{name}' spelled right?",
+          examples: const [
+              """
 // 'List' is misspelled.
 @MirrorsUsed(targets: 'dart.core.Lsit')
 import 'dart:mirrors';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind MIRRORS_CANNOT_FIND_IN_ELEMENT =
-      const MessageKind(
-      "Can't find '#{name}' in '#{element}'.",
-      // TODO(ahe): The closest identifiers in edit distance would be nice.
-      howToFix: "Is '#{name}' spelled right?",
-      examples: const [
-          """
+      MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT:
+        const MessageTemplate(MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT,
+          "Can't find '#{name}' in '#{element}'.",
+          // TODO(ahe): The closest identifiers in edit distance would be nice.
+          howToFix: "Is '#{name}' spelled right?",
+          examples: const [
+              """
 // 'addAll' is misspelled.
 @MirrorsUsed(targets: 'dart.core.List.addAl')
 import 'dart:mirrors';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind INVALID_URI = const MessageKind(
-      "'#{uri}' is not a valid URI.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const [
-        """
+      MessageKind.INVALID_URI:
+        const MessageTemplate(MessageKind.INVALID_URI,
+          "'#{uri}' is not a valid URI.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+            """
 // can't have a '[' in a URI
 import '../../Udyn[mic ils/expect.dart';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind INVALID_PACKAGE_URI = const MessageKind(
-      "'#{uri}' is not a valid package URI (#{exception}).",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const [
-        """
+      MessageKind.INVALID_PACKAGE_URI:
+        const MessageTemplate(MessageKind.INVALID_PACKAGE_URI,
+          "'#{uri}' is not a valid package URI (#{exception}).",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+            """
 // can't have a 'top level' package URI
 import 'package:foo.dart';
 
@@ -1624,156 +2244,175 @@
 import 'package:not\valid/foo.dart';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind READ_SCRIPT_ERROR = const MessageKind(
-      "Can't read '#{uri}' (#{exception}).",
-      // Don't know how to fix since the underlying error is unknown.
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const [
-          """
+      MessageKind.READ_SCRIPT_ERROR:
+        const MessageTemplate(MessageKind.READ_SCRIPT_ERROR,
+          "Can't read '#{uri}' (#{exception}).",
+          // Don't know how to fix since the underlying error is unknown.
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+              """
 // 'foo.dart' does not exist.
 import 'foo.dart';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind READ_SELF_ERROR = const MessageKind(
-      "#{exception}",
-      // Don't know how to fix since the underlying error is unknown.
-      howToFix: DONT_KNOW_HOW_TO_FIX);
+      MessageKind.READ_SELF_ERROR:
+        const MessageTemplate(MessageKind.READ_SELF_ERROR,
+          "#{exception}",
+          // Don't know how to fix since the underlying error is unknown.
+          howToFix: DONT_KNOW_HOW_TO_FIX),
 
-  static const MessageKind EXTRANEOUS_MODIFIER = const MessageKind(
-      "Can't have modifier '#{modifier}' here.",
-      howToFix: "Try removing '#{modifier}'.",
-      examples: const [
-          "var String foo; main(){}",
-          // "var get foo; main(){}",
-          "var set foo; main(){}",
-          "var final foo; main(){}",
-          "var var foo; main(){}",
-          "var const foo; main(){}",
-          "var abstract foo; main(){}",
-          "var static foo; main(){}",
-          "var external foo; main(){}",
-          "get var foo; main(){}",
-          "set var foo; main(){}",
-          "final var foo; main(){}",
-          "var var foo; main(){}",
-          "const var foo; main(){}",
-          "abstract var foo; main(){}",
-          "static var foo; main(){}",
-          "external var foo; main(){}"]);
+      MessageKind.EXTRANEOUS_MODIFIER:
+        const MessageTemplate(MessageKind.EXTRANEOUS_MODIFIER,
+          "Can't have modifier '#{modifier}' here.",
+          howToFix: "Try removing '#{modifier}'.",
+          examples: const [
+              "var String foo; main(){}",
+              // "var get foo; main(){}",
+              "var set foo; main(){}",
+              "var final foo; main(){}",
+              "var var foo; main(){}",
+              "var const foo; main(){}",
+              "var abstract foo; main(){}",
+              "var static foo; main(){}",
+              "var external foo; main(){}",
+              "get var foo; main(){}",
+              "set var foo; main(){}",
+              "final var foo; main(){}",
+              "var var foo; main(){}",
+              "const var foo; main(){}",
+              "abstract var foo; main(){}",
+              "static var foo; main(){}",
+              "external var foo; main(){}"]),
 
-  static const MessageKind EXTRANEOUS_MODIFIER_REPLACE = const MessageKind(
-      "Can't have modifier '#{modifier}' here.",
-      howToFix: "Try replacing modifier '#{modifier}' with 'var', 'final',"
-          " or a type.",
-      examples: const [
-          // "get foo; main(){}",
-          "set foo; main(){}",
-          "abstract foo; main(){}",
-          "static foo; main(){}",
-          "external foo; main(){}"]);
+      MessageKind.EXTRANEOUS_MODIFIER_REPLACE:
+        const MessageTemplate(MessageKind.EXTRANEOUS_MODIFIER_REPLACE,
+          "Can't have modifier '#{modifier}' here.",
+          howToFix:
+            "Try replacing modifier '#{modifier}' with 'var', 'final', "
+            "or a type.",
+          examples: const [
+              // "get foo; main(){}",
+              "set foo; main(){}",
+              "abstract foo; main(){}",
+              "static foo; main(){}",
+              "external foo; main(){}"]),
 
-  static const MessageKind ABSTRACT_CLASS_INSTANTIATION = const MessageKind(
-      "Can't instantiate abstract class.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const ["abstract class A {} main() { new A(); }"]);
+      MessageKind.ABSTRACT_CLASS_INSTANTIATION:
+        const MessageTemplate(MessageKind.ABSTRACT_CLASS_INSTANTIATION,
+          "Can't instantiate abstract class.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["abstract class A {} main() { new A(); }"]),
 
-  static const MessageKind BODY_EXPECTED = const MessageKind(
-      "Expected a function body or '=>'.",
-      // TODO(ahe): In some scenarios, we can suggest removing the 'static'
-      // keyword.
-      howToFix: "Try adding {}.",
-      examples: const [
-          "main();"]);
+      MessageKind.BODY_EXPECTED:
+        const MessageTemplate(MessageKind.BODY_EXPECTED,
+          "Expected a function body or '=>'.",
+          // TODO(ahe): In some scenarios, we can suggest removing the 'static'
+          // keyword.
+          howToFix: "Try adding {}.",
+          examples: const [
+              "main();"]),
 
-  static const MessageKind MIRROR_BLOAT = const MessageKind(
-      "#{count} methods retained for use by dart:mirrors out of #{total}"
-      " total methods (#{percentage}%).");
+      MessageKind.MIRROR_BLOAT:
+        const MessageTemplate(MessageKind.MIRROR_BLOAT,
+          "#{count} methods retained for use by dart:mirrors out of #{total}"
+          " total methods (#{percentage}%)."),
 
-  static const MessageKind MIRROR_IMPORT = const MessageKind(
-      "Import of 'dart:mirrors'.");
+      MessageKind.MIRROR_IMPORT:
+        const MessageTemplate(MessageKind.MIRROR_IMPORT,
+          "Import of 'dart:mirrors'."),
 
-  static const MessageKind MIRROR_IMPORT_NO_USAGE = const MessageKind(
-      "This import is not annotated with @MirrorsUsed, which may lead to "
-      "unnecessarily large generated code.",
-      howToFix:
-          "Try adding '@MirrorsUsed(...)' as described at "
-          "https://goo.gl/Akrrog.");
+      MessageKind.MIRROR_IMPORT_NO_USAGE:
+        const MessageTemplate(MessageKind.MIRROR_IMPORT_NO_USAGE,
+          "This import is not annotated with @MirrorsUsed, which may lead to "
+          "unnecessarily large generated code.",
+          howToFix:
+              "Try adding '@MirrorsUsed(...)' as described at "
+              "https://goo.gl/Akrrog."),
 
-  static const MessageKind WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT =
-      const MessageKind(
-      "Argument for 'JS_INTERCEPTOR_CONSTANT' must be a type constant.");
+      MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT:
+        const MessageTemplate(
+          MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT,
+          "Argument for 'JS_INTERCEPTOR_CONSTANT' must be a type constant."),
 
-  static const MessageKind EXPECTED_IDENTIFIER_NOT_RESERVED_WORD =
-      const MessageKind(
-          "'#{keyword}' is a reserved word and can't be used here.",
-          howToFix: "Try using a different name.",
-          examples: const ["do() {} main() {}"]);
+      MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD:
+        const MessageTemplate(MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
+              "'#{keyword}' is a reserved word and can't be used here.",
+              howToFix: "Try using a different name.",
+              examples: const ["do() {} main() {}"]),
 
-  static const MessageKind  NAMED_FUNCTION_EXPRESSION =
-      const MessageKind("Function expression '#{name}' cannot be named.",
+      MessageKind. NAMED_FUNCTION_EXPRESSION:
+        const MessageTemplate(MessageKind.NAMED_FUNCTION_EXPRESSION,
+          "Function expression '#{name}' cannot be named.",
           howToFix: "Try removing the name.",
-          examples: const ["main() { var f = func() {}; }"]);
+          examples: const ["main() { var f = func() {}; }"]),
 
-  static const MessageKind UNUSED_METHOD = const MessageKind(
-      "The method '#{name}' is never called.",
-      howToFix: "Consider deleting it.",
-      examples: const ["deadCode() {} main() {}"]);
+      MessageKind.UNUSED_METHOD:
+        const MessageTemplate(MessageKind.UNUSED_METHOD,
+          "The method '#{name}' is never called.",
+          howToFix: "Consider deleting it.",
+          examples: const ["deadCode() {} main() {}"]),
 
-  static const MessageKind UNUSED_CLASS = const MessageKind(
-      "The class '#{name}' is never used.",
-      howToFix: "Consider deleting it.",
-      examples: const ["class DeadCode {} main() {}"]);
+      MessageKind.UNUSED_CLASS:
+        const MessageTemplate(MessageKind.UNUSED_CLASS,
+          "The class '#{name}' is never used.",
+          howToFix: "Consider deleting it.",
+          examples: const ["class DeadCode {} main() {}"]),
 
-  static const MessageKind UNUSED_TYPEDEF = const MessageKind(
-      "The typedef '#{name}' is never used.",
-      howToFix: "Consider deleting it.",
-      examples: const ["typedef DeadCode(); main() {}"]);
+      MessageKind.UNUSED_TYPEDEF:
+        const MessageTemplate(MessageKind.UNUSED_TYPEDEF,
+          "The typedef '#{name}' is never used.",
+          howToFix: "Consider deleting it.",
+          examples: const ["typedef DeadCode(); main() {}"]),
 
-  static const MessageKind ABSTRACT_METHOD = const MessageKind(
-      "The method '#{name}' has no implementation in "
-      "class '#{class}'.",
-      howToFix: "Try adding a body to '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.ABSTRACT_METHOD:
+        const MessageTemplate(MessageKind.ABSTRACT_METHOD,
+          "The method '#{name}' has no implementation in "
+          "class '#{class}'.",
+          howToFix: "Try adding a body to '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 class Class {
   method();
 }
 main() => new Class().method();
-"""]);
+"""]),
 
-  static const MessageKind ABSTRACT_GETTER = const MessageKind(
-      "The getter '#{name}' has no implementation in "
-      "class '#{class}'.",
-      howToFix: "Try adding a body to '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.ABSTRACT_GETTER:
+        const MessageTemplate(MessageKind.ABSTRACT_GETTER,
+          "The getter '#{name}' has no implementation in "
+          "class '#{class}'.",
+          howToFix: "Try adding a body to '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 class Class {
   get getter;
 }
 main() => new Class();
-"""]);
+"""]),
 
-  static const MessageKind ABSTRACT_SETTER = const MessageKind(
-      "The setter '#{name}' has no implementation in "
-      "class '#{class}'.",
-      howToFix: "Try adding a body to '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.ABSTRACT_SETTER:
+        const MessageTemplate(MessageKind.ABSTRACT_SETTER,
+          "The setter '#{name}' has no implementation in "
+          "class '#{class}'.",
+          howToFix: "Try adding a body to '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 class Class {
   set setter(_);
 }
 main() => new Class();
-"""]);
+"""]),
 
-  static const MessageKind INHERIT_GETTER_AND_METHOD = const MessageKind(
-      "The class '#{class}' can't inherit both getters and methods "
-      "by the named '#{name}'.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const ["""
+      MessageKind.INHERIT_GETTER_AND_METHOD:
+        const MessageTemplate(MessageKind.INHERIT_GETTER_AND_METHOD,
+          "The class '#{class}' can't inherit both getters and methods "
+          "by the named '#{name}'.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["""
 class A {
   get member => null;
 }
@@ -1783,26 +2422,30 @@
 class Class implements A, B {
 }
 main() => new Class();
-"""]);
+"""]),
 
-  static const MessageKind INHERITED_METHOD = const MessageKind(
-      "The inherited method '#{name}' is declared here in class "
-      "'#{class}'.");
+      MessageKind.INHERITED_METHOD:
+        const MessageTemplate(MessageKind.INHERITED_METHOD,
+          "The inherited method '#{name}' is declared here in class "
+          "'#{class}'."),
 
-  static const MessageKind INHERITED_EXPLICIT_GETTER = const MessageKind(
-      "The inherited getter '#{name}' is declared here in class "
-      "'#{class}'.");
+      MessageKind.INHERITED_EXPLICIT_GETTER:
+        const MessageTemplate(MessageKind.INHERITED_EXPLICIT_GETTER,
+          "The inherited getter '#{name}' is declared here in class "
+          "'#{class}'."),
 
-  static const MessageKind INHERITED_IMPLICIT_GETTER = const MessageKind(
-      "The inherited getter '#{name}' is implicitly declared by this "
-      "field in class '#{class}'.");
+      MessageKind.INHERITED_IMPLICIT_GETTER:
+        const MessageTemplate(MessageKind.INHERITED_IMPLICIT_GETTER,
+          "The inherited getter '#{name}' is implicitly declared by this "
+          "field in class '#{class}'."),
 
-  static const MessageKind UNIMPLEMENTED_METHOD_ONE = const MessageKind(
-      "'#{class}' doesn't implement '#{method}' "
-      "declared in '#{declarer}'.",
-      howToFix: "Try adding an implementation of '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.UNIMPLEMENTED_METHOD_ONE:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_METHOD_ONE,
+          "'#{class}' doesn't implement '#{method}' "
+          "declared in '#{declarer}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 abstract class I {
   m();
 }
@@ -1814,13 +2457,14 @@
 }
 class C extends I {}
 main() => new C();
-"""]);
+"""]),
 
-  static const MessageKind UNIMPLEMENTED_METHOD = const MessageKind(
-      "'#{class}' doesn't implement '#{method}'.",
-      howToFix: "Try adding an implementation of '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.UNIMPLEMENTED_METHOD:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_METHOD,
+          "'#{class}' doesn't implement '#{method}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 abstract class I {
   m();
 }
@@ -1848,17 +2492,19 @@
 main() {
  new C();
 }
-"""]);
+"""]),
 
-  static const MessageKind UNIMPLEMENTED_METHOD_CONT = const MessageKind(
-      "The method '#{name}' is declared here in class '#{class}'.");
+      MessageKind.UNIMPLEMENTED_METHOD_CONT:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_METHOD_CONT,
+          "The method '#{name}' is declared here in class '#{class}'."),
 
-  static const MessageKind UNIMPLEMENTED_SETTER_ONE = const MessageKind(
-      "'#{class}' doesn't implement the setter '#{name}' "
-      "declared in '#{declarer}'.",
-      howToFix: "Try adding an implementation of '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.UNIMPLEMENTED_SETTER_ONE:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_SETTER_ONE,
+          "'#{class}' doesn't implement the setter '#{name}' "
+          "declared in '#{declarer}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 abstract class I {
   set m(_);
 }
@@ -1870,13 +2516,14 @@
  new D().m = 0;
  new C();
 }
-"""]);
+"""]),
 
-  static const MessageKind UNIMPLEMENTED_SETTER = const MessageKind(
-      "'#{class}' doesn't implement the setter '#{name}'.",
-      howToFix: "Try adding an implementation of '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.UNIMPLEMENTED_SETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_SETTER,
+          "'#{class}' doesn't implement the setter '#{name}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 abstract class I {
   set m(_);
 }
@@ -1894,21 +2541,24 @@
 }
 class C extends I implements J {}
 main() => new C();
-"""]);
+"""]),
 
-  static const MessageKind UNIMPLEMENTED_EXPLICIT_SETTER = const MessageKind(
-      "The setter '#{name}' is declared here in class '#{class}'.");
+      MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER,
+          "The setter '#{name}' is declared here in class '#{class}'."),
 
-  static const MessageKind UNIMPLEMENTED_IMPLICIT_SETTER = const MessageKind(
-      "The setter '#{name}' is implicitly declared by this field "
-      "in class '#{class}'.");
+      MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER,
+          "The setter '#{name}' is implicitly declared by this field "
+          "in class '#{class}'."),
 
-  static const MessageKind UNIMPLEMENTED_GETTER_ONE = const MessageKind(
-      "'#{class}' doesn't implement the getter '#{name}' "
-      "declared in '#{declarer}'.",
-      howToFix: "Try adding an implementation of '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.UNIMPLEMENTED_GETTER_ONE:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_GETTER_ONE,
+          "'#{class}' doesn't implement the getter '#{name}' "
+          "declared in '#{declarer}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 abstract class I {
   get m;
 }
@@ -1920,13 +2570,14 @@
 }
 class C extends I {}
 main() => new C();
-"""]);
+"""]),
 
-  static const MessageKind UNIMPLEMENTED_GETTER = const MessageKind(
-      "'#{class}' doesn't implement the getter '#{name}'.",
-      howToFix: "Try adding an implementation of '#{name}' or declaring "
-                "'#{class}' to be 'abstract'.",
-      examples: const ["""
+      MessageKind.UNIMPLEMENTED_GETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_GETTER,
+          "'#{class}' doesn't implement the getter '#{name}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
 abstract class I {
   get m;
 }
@@ -1944,37 +2595,43 @@
 }
 class C extends I implements J {}
 main() => new C();
-"""]);
+"""]),
 
-  static const MessageKind UNIMPLEMENTED_EXPLICIT_GETTER = const MessageKind(
-      "The getter '#{name}' is declared here in class '#{class}'.");
+      MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER,
+          "The getter '#{name}' is declared here in class '#{class}'."),
 
-  static const MessageKind UNIMPLEMENTED_IMPLICIT_GETTER = const MessageKind(
-      "The getter '#{name}' is implicitly declared by this field "
-      "in class '#{class}'.");
+      MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER,
+          "The getter '#{name}' is implicitly declared by this field "
+          "in class '#{class}'."),
 
-  static const MessageKind EQUAL_MAP_ENTRY_KEY = const MessageKind(
-      "An entry with the same key already exists in the map.",
-      howToFix: "Try removing the previous entry or changing the key in one "
-                "of the entries.",
-      examples: const ["""
+      MessageKind.EQUAL_MAP_ENTRY_KEY:
+        const MessageTemplate(MessageKind.EQUAL_MAP_ENTRY_KEY,
+          "An entry with the same key already exists in the map.",
+          howToFix:
+            "Try removing the previous entry or changing the key in one "
+            "of the entries.",
+          examples: const ["""
 main() {
   var m = const {'foo': 1, 'foo': 2};
-}"""]);
+}"""]),
 
-  static const MessageKind BAD_INPUT_CHARACTER = const MessageKind(
-      "Character U+#{characterHex} isn't allowed here.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const ["""
+      MessageKind.BAD_INPUT_CHARACTER:
+        const MessageTemplate(MessageKind.BAD_INPUT_CHARACTER,
+          "Character U+#{characterHex} isn't allowed here.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["""
 main() {
   String x = ç;
 }
-"""]);
+"""]),
 
-  static const MessageKind UNTERMINATED_STRING = const MessageKind(
-      "String must end with #{quote}.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const ["""
+      MessageKind.UNTERMINATED_STRING:
+        const MessageTemplate(MessageKind.UNTERMINATED_STRING,
+          "String must end with #{quote}.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["""
 main() {
   return '
 ;
@@ -2009,46 +2666,53 @@
 """,
 """
 main() => r\"\"\"
-"""]);
+"""]),
 
-  static const MessageKind UNMATCHED_TOKEN = const MessageKind(
-      "Can't find '#{end}' to match '#{begin}'.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const[
-          "main(",
-          "main(){",
-          "main(){]}",
-        ]);
+      MessageKind.UNMATCHED_TOKEN:
+        const MessageTemplate(MessageKind.UNMATCHED_TOKEN,
+          "Can't find '#{end}' to match '#{begin}'.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const[
+              "main(",
+              "main(){",
+              "main(){]}",
+            ]),
 
-  static const MessageKind UNTERMINATED_TOKEN = const MessageKind(
-      // This is a fall-back message that shouldn't happen.
-      "Incomplete token.");
+      MessageKind.UNTERMINATED_TOKEN:
+        const MessageTemplate(MessageKind.UNTERMINATED_TOKEN,
+          // This is a fall-back message that shouldn't happen.
+          "Incomplete token."),
 
-  static const MessageKind EXPONENT_MISSING = const MessageKind(
-      "Numbers in exponential notation should always contain an exponent"
-      " (an integer number with an optional sign).",
-      howToFix: "Make sure there is an exponent, and remove any whitespace "
-      "before it.",
-      examples: const ["""
+      MessageKind.EXPONENT_MISSING:
+        const MessageTemplate(MessageKind.EXPONENT_MISSING,
+          "Numbers in exponential notation should always contain an exponent"
+          " (an integer number with an optional sign).",
+          howToFix:
+            "Make sure there is an exponent, and remove any whitespace "
+            "before it.",
+          examples: const ["""
 main() {
   var i = 1e;
 }
-"""]);
+"""]),
 
-  static const MessageKind HEX_DIGIT_EXPECTED = const MessageKind(
-      "A hex digit (0-9 or A-F) must follow '0x'.",
-      howToFix: DONT_KNOW_HOW_TO_FIX, // Seems obvious from the error message.
-      examples: const ["""
+      MessageKind.HEX_DIGIT_EXPECTED:
+        const MessageTemplate(MessageKind.HEX_DIGIT_EXPECTED,
+          "A hex digit (0-9 or A-F) must follow '0x'.",
+          howToFix:
+            DONT_KNOW_HOW_TO_FIX, // Seems obvious from the error message.
+          examples: const ["""
 main() {
   var i = 0x;
 }
-"""]);
+"""]),
 
-  static const MessageKind MALFORMED_STRING_LITERAL = const MessageKind(
-      r"A '$' has special meaning inside a string, and must be followed by an"
-      " identifier or an expression in curly braces ({}).",
-      howToFix: r"Try adding a backslash (\) to escape the '$'.",
-      examples: const [r"""
+      MessageKind.MALFORMED_STRING_LITERAL:
+        const MessageTemplate(MessageKind.MALFORMED_STRING_LITERAL,
+          r"A '$' has special meaning inside a string, and must be followed by "
+          "an identifier or an expression in curly braces ({}).",
+          howToFix: r"Try adding a backslash (\) to escape the '$'.",
+          examples: const [r"""
 main() {
   return '$';
 }
@@ -2067,34 +2731,37 @@
 main() {
   return """$""";
 }
-''']);
+''']),
 
-  static const MessageKind UNTERMINATED_COMMENT = const MessageKind(
-      "Comment starting with '/*' must end with '*/'.",
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const [r"""
+      MessageKind.UNTERMINATED_COMMENT:
+        const MessageTemplate(MessageKind.UNTERMINATED_COMMENT,
+          "Comment starting with '/*' must end with '*/'.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [r"""
 main() {
 }
-/*"""]);
+/*"""]),
 
-  static const MessageKind MISSING_TOKEN_BEFORE_THIS = const MessageKind(
-      "Expected '#{token}' before this.",
-      // Consider the second example below: the parser expects a ')' before
-      // 'y', but a ',' would also have worked. We don't have enough
-      // information to give a good suggestion.
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const [
-          "main() => true ? 1;",
-          "main() => foo(x: 1 y: 2);",
-        ]);
+      MessageKind.MISSING_TOKEN_BEFORE_THIS:
+        const MessageTemplate(MessageKind.MISSING_TOKEN_BEFORE_THIS,
+          "Expected '#{token}' before this.",
+          // Consider the second example below: the parser expects a ')' before
+          // 'y', but a ',' would also have worked. We don't have enough
+          // information to give a good suggestion.
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+              "main() => true ? 1;",
+              "main() => foo(x: 1 y: 2);",
+            ]),
 
-  static const MessageKind MISSING_TOKEN_AFTER_THIS = const MessageKind(
-      "Expected '#{token}' after this.",
-      // See [MISSING_TOKEN_BEFORE_THIS], we don't have enough information to
-      // give a good suggestion.
-      howToFix: DONT_KNOW_HOW_TO_FIX,
-      examples: const [
-          "main(x) {x}",
+      MessageKind.MISSING_TOKEN_AFTER_THIS:
+        const MessageTemplate(MessageKind.MISSING_TOKEN_AFTER_THIS,
+          "Expected '#{token}' after this.",
+          // See [MISSING_TOKEN_BEFORE_THIS], we don't have enough information
+          // to give a good suggestion.
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+              "main(x) {x}",
 """
 class S1 {}
 class S2 {}
@@ -2102,34 +2769,40 @@
 class A = S1 with S2, S3
 main() => new A();
 """
-]);
+]),
 
-  static const MessageKind CONSIDER_ANALYZE_ALL = const MessageKind(
-      "Could not find '#{main}'.  Nothing will be analyzed.",
-      howToFix: "Try using '--analyze-all' to analyze everything.",
-      examples: const ['']);
+      MessageKind.CONSIDER_ANALYZE_ALL:
+        const MessageTemplate(MessageKind.CONSIDER_ANALYZE_ALL,
+          "Could not find '#{main}'.  Nothing will be analyzed.",
+          howToFix: "Try using '--analyze-all' to analyze everything.",
+          examples: const ['']),
 
-  static const MessageKind MISSING_MAIN = const MessageKind(
-      "Could not find '#{main}'.",
-      howToFix: "Try adding a method named '#{main}' to your program."
-      /* No example, test uses '--analyze-only' which will produce the above
-       * message [CONSIDER_ANALYZE_ALL].  An example for a human operator would
-       * be an empty file. */);
+      MessageKind.MISSING_MAIN:
+        const MessageTemplate(MessageKind.MISSING_MAIN,
+          "Could not find '#{main}'.",
+          howToFix: "Try adding a method named '#{main}' to your program."
+          /* No example, test uses '--analyze-only' which will produce the above
+           * message [CONSIDER_ANALYZE_ALL].  An example for a human operator
+           * would be an empty file.*/),
 
-  static const MessageKind MAIN_NOT_A_FUNCTION = const MessageKind(
-      "'#{main}' is not a function.",
-      howToFix: DONT_KNOW_HOW_TO_FIX, /* Don't state the obvious. */
-      examples: const ['var main;']);
+      MessageKind.MAIN_NOT_A_FUNCTION:
+        const MessageTemplate(MessageKind.MAIN_NOT_A_FUNCTION,
+          "'#{main}' is not a function.",
+          howToFix: DONT_KNOW_HOW_TO_FIX, /* Don't state the obvious. */
+          examples: const ['var main;']),
 
-  static const MessageKind MAIN_WITH_EXTRA_PARAMETER = const MessageKind(
-      "'#{main}' cannot have more than two parameters.",
-      howToFix: DONT_KNOW_HOW_TO_FIX, /* Don't state the obvious. */
-      examples: const ['main(a, b, c) {}']);
+      MessageKind.MAIN_WITH_EXTRA_PARAMETER:
+        const MessageTemplate(MessageKind.MAIN_WITH_EXTRA_PARAMETER,
+          "'#{main}' cannot have more than two parameters.",
+          howToFix: DONT_KNOW_HOW_TO_FIX, /* Don't state the obvious. */
+          examples: const ['main(a, b, c) {}']),
 
-  static const MessageKind COMPILER_CRASHED = const MessageKind(
-      "The compiler crashed when compiling this element.");
+      MessageKind.COMPILER_CRASHED:
+        const MessageTemplate(MessageKind.COMPILER_CRASHED,
+          "The compiler crashed when compiling this element."),
 
-  static const MessageKind PLEASE_REPORT_THE_CRASH = const MessageKind('''
+      MessageKind.PLEASE_REPORT_THE_CRASH:
+        const MessageTemplate(MessageKind.PLEASE_REPORT_THE_CRASH, '''
 The compiler is broken.
 
 When compiling the above element, the compiler crashed. It is not
@@ -2147,84 +2820,100 @@
 
 * the entire message you see here (including the full stack trace
   below as well as the source location above).
-''');
+'''),
 
-  static const MessageKind POTENTIAL_MUTATION = const MessageKind(
-      "Variable '#{variableName}' is not known to be of type "
-      "'#{shownType}' because it is potentially mutated in the scope for "
-      "promotion.");
+      MessageKind.POTENTIAL_MUTATION:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION,
+          "Variable '#{variableName}' is not known to be of type "
+          "'#{shownType}' because it is potentially mutated in the scope for "
+          "promotion."),
 
-  static const MessageKind POTENTIAL_MUTATION_HERE = const MessageKind(
-      "Variable '#{variableName}' is potentially mutated here.");
+      MessageKind.POTENTIAL_MUTATION_HERE:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION_HERE,
+          "Variable '#{variableName}' is potentially mutated here."),
 
-  static const MessageKind POTENTIAL_MUTATION_IN_CLOSURE = const MessageKind(
-      "Variable '#{variableName}' is not known to be of type "
-      "'#{shownType}' because it is potentially mutated within a closure.");
+      MessageKind.POTENTIAL_MUTATION_IN_CLOSURE:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION_IN_CLOSURE,
+          "Variable '#{variableName}' is not known to be of type "
+          "'#{shownType}' because it is potentially mutated within a closure."),
 
-  static const MessageKind POTENTIAL_MUTATION_IN_CLOSURE_HERE =
-      const MessageKind(
-          "Variable '#{variableName}' is potentially mutated in a "
-          "closure here.");
+      MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE,
+              "Variable '#{variableName}' is potentially mutated in a "
+              "closure here."),
 
-  static const MessageKind ACCESSED_IN_CLOSURE = const MessageKind(
-      "Variable '#{variableName}' is not known to be of type "
-      "'#{shownType}' because it is accessed by a closure in the scope for "
-      "promotion and potentially mutated in the scope of '#{variableName}'.");
+      MessageKind.ACCESSED_IN_CLOSURE:
+        const MessageTemplate(MessageKind.ACCESSED_IN_CLOSURE,
+          "Variable '#{variableName}' is not known to be of type "
+          "'#{shownType}' because it is accessed by a closure in the scope for "
+          "promotion and potentially mutated in the scope of "
+          "'#{variableName}'."),
 
-  static const MessageKind ACCESSED_IN_CLOSURE_HERE = const MessageKind(
-      "Variable '#{variableName}' is accessed in a closure here.");
+      MessageKind.ACCESSED_IN_CLOSURE_HERE:
+        const MessageTemplate(MessageKind.ACCESSED_IN_CLOSURE_HERE,
+          "Variable '#{variableName}' is accessed in a closure here."),
 
-  static const MessageKind NOT_MORE_SPECIFIC = const MessageKind(
-      "Variable '#{variableName}' is not shown to have type "
-      "'#{shownType}' because '#{shownType}' is not more specific than the "
-      "known type '#{knownType}' of '#{variableName}'.");
+      MessageKind.NOT_MORE_SPECIFIC:
+        const MessageTemplate(MessageKind.NOT_MORE_SPECIFIC,
+          "Variable '#{variableName}' is not shown to have type "
+          "'#{shownType}' because '#{shownType}' is not more specific than the "
+          "known type '#{knownType}' of '#{variableName}'."),
 
-  static const MessageKind NOT_MORE_SPECIFIC_SUBTYPE = const MessageKind(
-      "Variable '#{variableName}' is not shown to have type "
-      "'#{shownType}' because '#{shownType}' is not a subtype of the "
-      "known type '#{knownType}' of '#{variableName}'.");
+      MessageKind.NOT_MORE_SPECIFIC_SUBTYPE:
+        const MessageTemplate(MessageKind.NOT_MORE_SPECIFIC_SUBTYPE,
+          "Variable '#{variableName}' is not shown to have type "
+          "'#{shownType}' because '#{shownType}' is not a subtype of the "
+          "known type '#{knownType}' of '#{variableName}'."),
 
-  static const MessageKind NOT_MORE_SPECIFIC_SUGGESTION = const MessageKind(
-      "Variable '#{variableName}' is not shown to have type "
-      "'#{shownType}' because '#{shownType}' is not more specific than the "
-      "known type '#{knownType}' of '#{variableName}'.",
-      howToFix: "Try replacing '#{shownType}' with '#{shownTypeSuggestion}'.");
+      MessageKind.NOT_MORE_SPECIFIC_SUGGESTION:
+        const MessageTemplate(MessageKind.NOT_MORE_SPECIFIC_SUGGESTION,
+          "Variable '#{variableName}' is not shown to have type "
+          "'#{shownType}' because '#{shownType}' is not more specific than the "
+          "known type '#{knownType}' of '#{variableName}'.",
+          howToFix:
+            "Try replacing '#{shownType}' with '#{shownTypeSuggestion}'."),
 
-  static const MessageKind HIDDEN_WARNINGS_HINTS = const MessageKind(
-      "#{warnings} warning(s) and #{hints} hint(s) suppressed in #{uri}.");
+      MessageKind.HIDDEN_WARNINGS_HINTS:
+        const MessageTemplate(MessageKind.HIDDEN_WARNINGS_HINTS,
+          "#{warnings} warning(s) and #{hints} hint(s) suppressed in #{uri}."),
 
-  static const MessageKind HIDDEN_WARNINGS = const MessageKind(
-      "#{warnings} warning(s) suppressed in #{uri}.");
+      MessageKind.HIDDEN_WARNINGS:
+        const MessageTemplate(MessageKind.HIDDEN_WARNINGS,
+          "#{warnings} warning(s) suppressed in #{uri}."),
 
-  static const MessageKind HIDDEN_HINTS = const MessageKind(
-      "#{hints} hint(s) suppressed in #{uri}.");
+      MessageKind.HIDDEN_HINTS:
+        const MessageTemplate(MessageKind.HIDDEN_HINTS,
+          "#{hints} hint(s) suppressed in #{uri}."),
 
-  static const MessageKind PREAMBLE = const MessageKind(
-    "When run on the command-line, the compiled output might"
-    " require a preamble file located in:\n"
-    "  <sdk>/lib/_internal/js_runtime/lib/preambles.");
+      MessageKind.PREAMBLE:
+        const MessageTemplate(MessageKind.PREAMBLE,
+        "When run on the command-line, the compiled output might"
+        " require a preamble file located in:\n"
+        "  <sdk>/lib/_internal/js_runtime/lib/preambles."),
 
-  static const MessageKind INVALID_SYNC_MODIFIER = const MessageKind(
-      "Invalid modifier 'sync'.",
-      options: const ['--enable-async'],
-      howToFix: "Try replacing 'sync' with 'sync*'.",
-      examples: const [
-        "main() sync {}"
-      ]);
+      MessageKind.INVALID_SYNC_MODIFIER:
+        const MessageTemplate(MessageKind.INVALID_SYNC_MODIFIER,
+          "Invalid modifier 'sync'.",
+          options: const ['--enable-async'],
+          howToFix: "Try replacing 'sync' with 'sync*'.",
+          examples: const [
+            "main() sync {}"
+          ]),
 
-  static const MessageKind INVALID_AWAIT_FOR = const MessageKind(
-      "'await' is only supported on for-in loops.",
-      options: const ['--enable-async'],
-      howToFix: "Try rewriting the loop as a for-in loop or removing the "
-                "'await' keyword.",
-      examples: const ["""
+      MessageKind.INVALID_AWAIT_FOR:
+        const MessageTemplate(MessageKind.INVALID_AWAIT_FOR,
+          "'await' is only supported on for-in loops.",
+          options: const ['--enable-async'],
+          howToFix: "Try rewriting the loop as a for-in loop or removing the "
+                    "'await' keyword.",
+          examples: const ["""
 main() async* {
   await for (int i = 0; i < 10; i++) {}
 }
-"""]);
+"""]),
 
-  static const MessageKind ASYNC_MODIFIER_ON_ABSTRACT_METHOD =
-      const MessageKind(
+      MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD:
+        const MessageTemplate(MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
           "The modifier '#{modifier}' is not allowed on an abstract method.",
           options: const ['--enable-async'],
           howToFix: "Try removing the '#{modifier}' modifier or adding a "
@@ -2240,14 +2929,14 @@
   A a = new B();
   a.method();
 }
-"""]);
+"""]),
 
-  static const MessageKind ASYNC_MODIFIER_ON_CONSTRUCTOR =
-      const MessageKind(
-          "The modifier '#{modifier}' is not allowed on constructors.",
-          options: const ['--enable-async'],
-          howToFix: "Try removing the '#{modifier}' modifier.",
-          examples: const ["""
+      MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR,
+              "The modifier '#{modifier}' is not allowed on constructors.",
+              options: const ['--enable-async'],
+              howToFix: "Try removing the '#{modifier}' modifier.",
+              examples: const ["""
 class A {
   A() async;
 }
@@ -2258,36 +2947,37 @@
   A();
   factory A.a() async* {}
 }
-main() => new A.a();"""]);
+main() => new A.a();"""]),
 
-  static const MessageKind ASYNC_MODIFIER_ON_SETTER =
-      const MessageKind(
-          "The modifier '#{modifier}' is not allowed on setters.",
-          options: const ['--enable-async'],
-          howToFix: "Try removing the '#{modifier}' modifier.",
-          examples: const ["""
+      MessageKind.ASYNC_MODIFIER_ON_SETTER:
+        const MessageTemplate(MessageKind.ASYNC_MODIFIER_ON_SETTER,
+              "The modifier '#{modifier}' is not allowed on setters.",
+              options: const ['--enable-async'],
+              howToFix: "Try removing the '#{modifier}' modifier.",
+              examples: const ["""
 class A {
   set foo(v) async {}
 }
-main() => new A().foo = 0;"""]);
+main() => new A().foo = 0;"""]),
 
-  static const MessageKind YIELDING_MODIFIER_ON_ARROW_BODY =
-      const MessageKind(
+      MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY:
+        const MessageTemplate(MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
           "The modifier '#{modifier}' is not allowed on methods implemented "
           "using '=>'.",
           options: const ['--enable-async'],
           howToFix: "Try removing the '#{modifier}' modifier or implementing "
                     "the method body using a block: '{ ... }'.",
-          examples: const ["main() sync* => null;", "main() async* => null;"]);
+          examples: const ["main() sync* => null;", "main() async* => null;"]),
 
-  // TODO(johnniwinther): Check for 'async' as identifier.
-  static const MessageKind ASYNC_KEYWORD_AS_IDENTIFIER = const MessageKind(
-      "'#{keyword}' cannot be used as an identifier in a function body marked "
-      "with '#{modifier}'.",
-      options: const ['--enable-async'],
-      howToFix: "Try removing the '#{modifier}' modifier or renaming the "
-                "identifier.",
-      examples: const ["""
+      // TODO(johnniwinther): Check for 'async' as identifier.
+      MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER:
+        const MessageTemplate(MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER,
+          "'#{keyword}' cannot be used as an identifier in a function body "
+          "marked with '#{modifier}'.",
+          options: const ['--enable-async'],
+          howToFix: "Try removing the '#{modifier}' modifier or renaming the "
+                    "identifier.",
+          examples: const ["""
 main() async {
  var await;
 }""",
@@ -2298,10 +2988,10 @@
 """
 main() sync* {
  var yield;
-}"""]);
+}"""]),
 
-  static const MessageKind RETURN_IN_GENERATOR =
-      const MessageKind(
+      MessageKind.RETURN_IN_GENERATOR:
+        const MessageTemplate(MessageKind.RETURN_IN_GENERATOR,
           "'return' with a value is not allowed in a method body using the "
           "'#{modifier}' modifier.",
           howToFix: "Try removing the value, replacing 'return' with 'yield' "
@@ -2315,41 +3005,45 @@
 """
 foo() sync* { return 0; }
 main() => foo();
-"""]);
+"""]),
 
-  static const MessageKind NATIVE_NOT_SUPPORTED = const MessageKind(
-      "'native' modifier is not supported.",
-      howToFix: "Try removing the 'native' implementation or analyzing the "
-                "code with the --allow-native-extensions option.",
-      examples: const ["""
+      MessageKind.NATIVE_NOT_SUPPORTED:
+        const MessageTemplate(MessageKind.NATIVE_NOT_SUPPORTED,
+          "'native' modifier is not supported.",
+          howToFix: "Try removing the 'native' implementation or analyzing the "
+                    "code with the --allow-native-extensions option.",
+          examples: const ["""
 main() native "Main";
-"""]);
+"""]),
 
-  static const MessageKind DART_EXT_NOT_SUPPORTED = const MessageKind(
-      "The 'dart-ext' scheme is not supported.",
-      howToFix: "Try analyzing the code with the --allow-native-extensions "
-                "option.",
-      examples: const ["""
+      MessageKind.DART_EXT_NOT_SUPPORTED:
+        const MessageTemplate(MessageKind.DART_EXT_NOT_SUPPORTED,
+          "The 'dart-ext' scheme is not supported.",
+          howToFix: "Try analyzing the code with the --allow-native-extensions "
+                    "option.",
+          examples: const ["""
 import 'dart-ext:main';
 
 main() {}
-"""]);
+"""]),
 
-  static const MessageKind LIBRARY_TAG_MUST_BE_FIRST = const MessageKind(
-      "The library declaration should come before other declarations.",
-      howToFix: "Try moving the declaration to the top of the file.",
-      examples: const [
+      MessageKind.LIBRARY_TAG_MUST_BE_FIRST:
+        const MessageTemplate(MessageKind.LIBRARY_TAG_MUST_BE_FIRST,
+          "The library declaration should come before other declarations.",
+          howToFix: "Try moving the declaration to the top of the file.",
+          examples: const [
 """
 import 'dart:core';
 library foo;
 main() {}
 """,
-      ]);
+      ]),
 
-  static const MessageKind ONLY_ONE_LIBRARY_TAG = const MessageKind(
-      "There can only be one library declaration.",
-      howToFix: "Try removing all other library declarations.",
-      examples: const [
+      MessageKind.ONLY_ONE_LIBRARY_TAG:
+        const MessageTemplate(MessageKind.ONLY_ONE_LIBRARY_TAG,
+          "There can only be one library declaration.",
+          howToFix: "Try removing all other library declarations.",
+          examples: const [
 """
 library foo;
 library bar;
@@ -2361,149 +3055,174 @@
 library bar;
 main() {}
 """,
-      ]);
+      ]),
 
-  static const MessageKind IMPORT_BEFORE_PARTS = const MessageKind(
-      "Import declarations should come before parts.",
-      howToFix: "Try moving this import further up in the file.",
-      examples: const [
-          const <String, String>{
-            'main.dart': """
+      MessageKind.IMPORT_BEFORE_PARTS:
+        const MessageTemplate(MessageKind.IMPORT_BEFORE_PARTS,
+          "Import declarations should come before parts.",
+          howToFix: "Try moving this import further up in the file.",
+          examples: const [
+              const <String, String>{
+                'main.dart': """
 library test.main;
 part 'part.dart';
 import 'dart:core';
 main() {}
 """,
-            'part.dart': """
+                'part.dart': """
 part of test.main;
 """,
-      }]);
+          }]),
 
-  static const MessageKind EXPORT_BEFORE_PARTS = const MessageKind(
-      "Export declarations should come before parts.",
-      howToFix: "Try moving this export further up in the file.",
-      examples: const [
-          const <String, String>{
-            'main.dart': """
+      MessageKind.EXPORT_BEFORE_PARTS:
+        const MessageTemplate(MessageKind.EXPORT_BEFORE_PARTS,
+          "Export declarations should come before parts.",
+          howToFix: "Try moving this export further up in the file.",
+          examples: const [
+              const <String, String>{
+                'main.dart': """
 library test.main;
 part 'part.dart';
 export 'dart:core';
 main() {}
 """,
-            'part.dart': """
+               'part.dart': """
 part of test.main;
 """,
-      }]);
+          }]),
 
   //////////////////////////////////////////////////////////////////////////////
   // Patch errors start.
   //////////////////////////////////////////////////////////////////////////////
 
-  static const MessageKind PATCH_RETURN_TYPE_MISMATCH = const MessageKind(
-      "Patch return type '#{patchReturnType}' does not match "
-      "'#{originReturnType}' on origin method '#{methodName}'.");
+      MessageKind.PATCH_RETURN_TYPE_MISMATCH:
+        const MessageTemplate(MessageKind.PATCH_RETURN_TYPE_MISMATCH,
+          "Patch return type '#{patchReturnType}' does not match "
+          "'#{originReturnType}' on origin method '#{methodName}'."),
 
-  static const MessageKind PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH =
-      const MessageKind(
+      MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH:
+        const MessageTemplate(
+          MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH,
           "Required parameter count of patch method "
           "(#{patchParameterCount}) does not match parameter count on origin "
-          "method '#{methodName}' (#{originParameterCount}).");
+          "method '#{methodName}' (#{originParameterCount})."),
 
-  static const MessageKind PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH =
-      const MessageKind(
+      MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH:
+        const MessageTemplate(
+          MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH,
           "Optional parameter count of patch method "
           "(#{patchParameterCount}) does not match parameter count on origin "
-          "method '#{methodName}' (#{originParameterCount}).");
+          "method '#{methodName}' (#{originParameterCount})."),
 
-  static const MessageKind PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH =
-      const MessageKind(
+      MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH:
+        const MessageTemplate(
+          MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH,
           "Optional parameters of origin and patch method "
-          "'#{methodName}' must both be either named or positional.");
+          "'#{methodName}' must both be either named or positional."),
 
-  static const MessageKind PATCH_PARAMETER_MISMATCH = const MessageKind(
-      "Patch method parameter '#{patchParameter}' does not match "
-      "'#{originParameter}' on origin method '#{methodName}'.");
+      MessageKind.PATCH_PARAMETER_MISMATCH:
+        const MessageTemplate(MessageKind.PATCH_PARAMETER_MISMATCH,
+          "Patch method parameter '#{patchParameter}' does not match "
+          "'#{originParameter}' on origin method '#{methodName}'."),
 
-  static const MessageKind PATCH_PARAMETER_TYPE_MISMATCH = const MessageKind(
-      "Patch method parameter '#{parameterName}' type "
-      "'#{patchParameterType}' does not match '#{originParameterType}' on "
-      "origin method '#{methodName}'.");
+      MessageKind.PATCH_PARAMETER_TYPE_MISMATCH:
+        const MessageTemplate(MessageKind.PATCH_PARAMETER_TYPE_MISMATCH,
+          "Patch method parameter '#{parameterName}' type "
+          "'#{patchParameterType}' does not match '#{originParameterType}' on "
+          "origin method '#{methodName}'."),
 
-  static const MessageKind PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION =
-      const MessageKind("External method without an implementation.");
+      MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION:
+        const MessageTemplate(MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION,
+          "External method without an implementation."),
 
-  static const MessageKind PATCH_POINT_TO_FUNCTION = const MessageKind(
-      "This is the function patch '#{functionName}'.");
+      MessageKind.PATCH_POINT_TO_FUNCTION:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_FUNCTION,
+          "This is the function patch '#{functionName}'."),
 
-  static const MessageKind PATCH_POINT_TO_CLASS = const MessageKind(
-      "This is the class patch '#{className}'.");
+      MessageKind.PATCH_POINT_TO_CLASS:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_CLASS,
+          "This is the class patch '#{className}'."),
 
-  static const MessageKind PATCH_POINT_TO_GETTER = const MessageKind(
-      "This is the getter patch '#{getterName}'.");
+      MessageKind.PATCH_POINT_TO_GETTER:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_GETTER,
+          "This is the getter patch '#{getterName}'."),
 
-  static const MessageKind PATCH_POINT_TO_SETTER = const MessageKind(
-      "This is the setter patch '#{setterName}'.");
+      MessageKind.PATCH_POINT_TO_SETTER:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_SETTER,
+          "This is the setter patch '#{setterName}'."),
 
-  static const MessageKind PATCH_POINT_TO_CONSTRUCTOR = const MessageKind(
-      "This is the constructor patch '#{constructorName}'.");
+      MessageKind.PATCH_POINT_TO_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_CONSTRUCTOR,
+          "This is the constructor patch '#{constructorName}'."),
 
-  static const MessageKind PATCH_POINT_TO_PARAMETER = const MessageKind(
-      "This is the patch parameter '#{parameterName}'.");
+      MessageKind.PATCH_POINT_TO_PARAMETER:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_PARAMETER,
+          "This is the patch parameter '#{parameterName}'."),
 
-  static const MessageKind PATCH_NON_EXISTING = const MessageKind(
-      "Origin does not exist for patch '#{name}'.");
+      MessageKind.PATCH_NON_EXISTING:
+        const MessageTemplate(MessageKind.PATCH_NON_EXISTING,
+          "Origin does not exist for patch '#{name}'."),
 
-  // TODO(ahe): Eventually, this error should be removed as it will be handled
-  // by the regular parser.
-  static const MessageKind PATCH_NONPATCHABLE = const MessageKind(
-      "Only classes and functions can be patched.");
+      // TODO(ahe): Eventually, this error should be removed as it will be
+      // handled by the regular parser.
+      MessageKind.PATCH_NONPATCHABLE:
+        const MessageTemplate(MessageKind.PATCH_NONPATCHABLE,
+          "Only classes and functions can be patched."),
 
-  static const MessageKind PATCH_NON_EXTERNAL = const MessageKind(
-      "Only external functions can be patched.");
+      MessageKind.PATCH_NON_EXTERNAL:
+        const MessageTemplate(MessageKind.PATCH_NON_EXTERNAL,
+          "Only external functions can be patched."),
 
-  static const MessageKind PATCH_NON_CLASS = const MessageKind(
-      "Patching non-class with class patch '#{className}'.");
+      MessageKind.PATCH_NON_CLASS:
+        const MessageTemplate(MessageKind.PATCH_NON_CLASS,
+          "Patching non-class with class patch '#{className}'."),
 
-  static const MessageKind PATCH_NON_GETTER = const MessageKind(
-      "Cannot patch non-getter '#{name}' with getter patch.");
+      MessageKind.PATCH_NON_GETTER:
+        const MessageTemplate(MessageKind.PATCH_NON_GETTER,
+          "Cannot patch non-getter '#{name}' with getter patch."),
 
-  static const MessageKind PATCH_NO_GETTER = const MessageKind(
-      "No getter found for getter patch '#{getterName}'.");
+      MessageKind.PATCH_NO_GETTER:
+        const MessageTemplate(MessageKind.PATCH_NO_GETTER,
+          "No getter found for getter patch '#{getterName}'."),
 
-  static const MessageKind PATCH_NON_SETTER = const MessageKind(
-      "Cannot patch non-setter '#{name}' with setter patch.");
+      MessageKind.PATCH_NON_SETTER:
+        const MessageTemplate(MessageKind.PATCH_NON_SETTER,
+          "Cannot patch non-setter '#{name}' with setter patch."),
 
-  static const MessageKind PATCH_NO_SETTER = const MessageKind(
-      "No setter found for setter patch '#{setterName}'.");
+      MessageKind.PATCH_NO_SETTER:
+        const MessageTemplate(MessageKind.PATCH_NO_SETTER,
+          "No setter found for setter patch '#{setterName}'."),
 
-  static const MessageKind PATCH_NON_CONSTRUCTOR = const MessageKind(
-      "Cannot patch non-constructor with constructor patch "
-      "'#{constructorName}'.");
+      MessageKind.PATCH_NON_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.PATCH_NON_CONSTRUCTOR,
+          "Cannot patch non-constructor with constructor patch "
+          "'#{constructorName}'."),
 
-  static const MessageKind PATCH_NON_FUNCTION = const MessageKind(
-      "Cannot patch non-function with function patch "
-      "'#{functionName}'.");
+      MessageKind.PATCH_NON_FUNCTION:
+        const MessageTemplate(MessageKind.PATCH_NON_FUNCTION,
+          "Cannot patch non-function with function patch "
+          "'#{functionName}'."),
 
-  static const MessageKind EXTERNAL_WITH_BODY = const MessageKind(
-      "External function '#{functionName}' cannot have a function body.",
-      options: const ["--output-type=dart"],
-      howToFix: "Try removing the 'external' modifier or the function body.",
-      examples: const ["""
+      MessageKind.EXTERNAL_WITH_BODY:
+        const MessageTemplate(MessageKind.EXTERNAL_WITH_BODY,
+          "External function '#{functionName}' cannot have a function body.",
+          options: const ["--output-type=dart"],
+          howToFix:
+            "Try removing the 'external' modifier or the function body.",
+          examples: const ["""
 external foo() => 0;
 main() => foo();
 """, """
 external foo() {}
 main() => foo();
-"""]);
+"""]),
 
   //////////////////////////////////////////////////////////////////////////////
   // Patch errors end.
   //////////////////////////////////////////////////////////////////////////////
 
-  static const String IMPORT_EXPERIMENTAL_MIRRORS_PADDING = '\n*   ';
-
-  static const MessageKind IMPORT_EXPERIMENTAL_MIRRORS =
-      const MessageKind(r'''
+      MessageKind.IMPORT_EXPERIMENTAL_MIRRORS:
+        const MessageTemplate(MessageKind.IMPORT_EXPERIMENTAL_MIRRORS, r'''
 
 ****************************************************************
 * WARNING: dart:mirrors support in dart2js is experimental,
@@ -2521,39 +3240,45 @@
 * To learn what to do next, please visit:
 *    http://dartlang.org/dart2js-reflection
 ****************************************************************
-''');
+'''),
 
 
-  static const MessageKind MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND =
-      const MessageKind(
-          "dart:mirrors library is not supported when using this backend.");
+      MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND:
+        const MessageTemplate(
+          MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND,
+          "dart:mirrors library is not supported when using this backend."),
 
-  static const MessageKind CALL_NOT_SUPPORTED_ON_NATIVE_CLASS =
-      const MessageKind(
+      MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS:
+        const MessageTemplate(MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS,
           "Non-supported 'call' member on a native class, or a "
-          "subclass of a native class.");
+          "subclass of a native class."),
 
-  static const MessageKind DIRECTLY_THROWING_NSM =
-      const MessageKind(
+      MessageKind.DIRECTLY_THROWING_NSM:
+        const MessageTemplate(MessageKind.DIRECTLY_THROWING_NSM,
           "This 'noSuchMethod' implementation is guaranteed to throw an "
           "exception. The generated code will be smaller if it is "
           "rewritten.",
           howToFix: "Rewrite to "
-                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'.");
+                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'."),
 
-  static const MessageKind COMPLEX_THROWING_NSM =
-      const MessageKind(
+      MessageKind.COMPLEX_THROWING_NSM:
+        const MessageTemplate(MessageKind.COMPLEX_THROWING_NSM,
           "This 'noSuchMethod' implementation is guaranteed to throw an "
           "exception. The generated code will be smaller and the compiler "
           "will be able to perform more optimizations if it is rewritten.",
           howToFix: "Rewrite to "
-                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'.");
+                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'."),
 
-  static const MessageKind COMPLEX_RETURNING_NSM =
-      const MessageKind(
+      MessageKind.COMPLEX_RETURNING_NSM:
+        const MessageTemplate(MessageKind.COMPLEX_RETURNING_NSM,
           "Overriding 'noSuchMethod' causes the compiler to generate "
           "more code and prevents the compiler from doing some optimizations.",
-          howToFix: "Consider removing this 'noSuchMethod' implementation.");
+          howToFix: "Consider removing this 'noSuchMethod' implementation."),
+
+
+  }; // End of TEMPLATES.
+
+  static const String IMPORT_EXPERIMENTAL_MIRRORS_PADDING = '\n*   ';
 
   toString() => template;
 
@@ -2565,18 +3290,20 @@
 }
 
 class Message {
-  final MessageKind kind;
+  final MessageTemplate template;
   final Map arguments;
   final bool terse;
   String message;
 
-  Message(this.kind, this.arguments, this.terse) {
+  Message(this.template, this.arguments, this.terse) {
     assert(() { computeMessage(); return true; });
   }
 
+  MessageKind get kind => template.kind;
+
   String computeMessage() {
     if (message == null) {
-      message = kind.template;
+      message = template.template;
       arguments.forEach((key, value) {
         message = message.replaceAll('#{${key}}', convertToString(value));
       });
@@ -2585,8 +3312,8 @@
           kind == MessageKind.GENERIC ||
             !message.contains(new RegExp(r'#\{.+\}')),
           message: 'Missing arguments in error message: "$message"'));
-      if (!terse && kind.hasHowToFix) {
-        String howToFix = kind.howToFix;
+      if (!terse && template.hasHowToFix) {
+        String howToFix = template.howToFix;
         arguments.forEach((key, value) {
           howToFix = howToFix.replaceAll('#{${key}}', convertToString(value));
         });
@@ -2602,7 +3329,7 @@
 
   bool operator==(other) {
     if (other is !Message) return false;
-    return (kind == other.kind) && (toString() == other.toString());
+    return (template == other.template) && (toString() == other.toString());
   }
 
   int get hashCode => throw new UnsupportedError('Message.hashCode');
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index b4d78dd..68d0f4d 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -46,6 +46,10 @@
   /// instance of [y].
   bool isSubtypeOf(ClassElement x, ClassElement y);
 
+  /// Returns an iterable over the live classes that extend [cls] including
+  /// [cls] itself.
+  Iterable<ClassElement> subclassesOf(ClassElement cls);
+
   /// Returns an iterable over the live classes that extend [cls] _not_
   /// including [cls] itself.
   Iterable<ClassElement> strictSubclassesOf(ClassElement cls);
@@ -145,34 +149,51 @@
     return compiler.resolverWorld.isInstantiated(cls);
   }
 
-  /// Returns an iterable over the live classes that extend [cls] _not_
-  /// including [cls] itself.
+  /// Returns an iterable over the directly instantiated classes that extend
+  /// [cls] possibly including [cls] itself, if it is live.
+  Iterable<ClassElement> subclassesOf(ClassElement cls) {
+    ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
+    if (hierarchy == null) return const <ClassElement>[];
+    assert(invariant(cls, isInstantiated(cls.declaration),
+        message: 'Class $cls has not been instantiated.'));
+    return hierarchy.subclasses();
+  }
+
+  /// Returns an iterable over the directly instantiated classes that extend
+  /// [cls] _not_ including [cls] itself.
   Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
-    Set<ClassElement> subclasses = _subclasses[cls.declaration];
+    ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
     if (subclasses == null) return const <ClassElement>[];
     assert(invariant(cls, isInstantiated(cls.declaration),
         message: 'Class $cls has not been instantiated.'));
-    return subclasses;
+    return subclasses.strictSubclasses();
   }
 
-  /// Returns an iterable over the live classes that implement [cls] _not_
-  /// including [cls] if it is live.
+  /// Returns an iterable over the directly instantiated that implement [cls]
+  /// _not_ including [cls].
   Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
     Set<ClassElement> subtypes = _subtypes[cls.declaration];
     return subtypes != null ? subtypes : const <ClassElement>[];
   }
 
-  /// Returns `true` if any live class other than [cls] extends [cls].
+  /// Returns `true` if any directly instantiated class other than [cls] extends
+  /// [cls].
   bool hasAnyStrictSubclass(ClassElement cls) {
-    return !strictSubclassesOf(cls).isEmpty;
+    ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
+    if (subclasses == null) return false;
+    assert(invariant(cls, isInstantiated(cls.declaration),
+        message: 'Class $cls has not been instantiated.'));
+    return subclasses.isIndirectlyInstantiated;
   }
 
-  /// Returns `true` if any live class other than [cls] implements [cls].
+  /// Returns `true` if any directly instantiated class other than [cls]
+  /// implements [cls].
   bool hasAnyStrictSubtype(ClassElement cls) {
     return !strictSubtypesOf(cls).isEmpty;
   }
 
-  /// Returns `true` if all live classes that implement [cls] extend it.
+  /// Returns `true` if all directly instantiated classes that implement [cls]
+  /// extend it.
   bool hasOnlySubclasses(ClassElement cls) {
     Iterable<ClassElement> subtypes = strictSubtypesOf(cls);
     if (subtypes == null) return true;
@@ -284,8 +305,8 @@
 
   // We keep track of subtype and subclass relationships in four
   // distinct sets to make class hierarchy analysis faster.
-  final Map<ClassElement, Set<ClassElement>> _subclasses =
-      new Map<ClassElement, Set<ClassElement>>();
+  final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes =
+      <ClassElement, ClassHierarchyNode>{};
   final Map<ClassElement, Set<ClassElement>> _subtypes =
       new Map<ClassElement, Set<ClassElement>>();
 
@@ -319,7 +340,40 @@
         this.compiler = compiler,
         alreadyPopulated = compiler.cacheStrategy.newSet();
 
+  ClassHierarchyNode classHierarchyNode(ClassElement cls) {
+    return _classHierarchyNodes[cls];
+  }
+
   void populate() {
+
+    /// Ensure that a [ClassHierarchyNode] exists for [cls]. Updates the
+    /// `isDirectlyInstantiated` and `isIndirectlyInstantiated` property of the
+    /// node according the provided arguments and returns the node.
+    ClassHierarchyNode createClassHierarchyNodeForClass(
+        ClassElement cls,
+        {bool directlyInstantiated: false,
+         bool indirectlyInstantiated: false}) {
+      assert(isInstantiated(cls));
+
+      ClassHierarchyNode node = _classHierarchyNodes.putIfAbsent(cls, () {
+        ClassHierarchyNode node = new ClassHierarchyNode(cls);
+        if (cls.superclass != null) {
+          createClassHierarchyNodeForClass(cls.superclass,
+              indirectlyInstantiated:
+                directlyInstantiated || indirectlyInstantiated)
+              .addDirectSubclass(node);
+        }
+        return node;
+      });
+      if (directlyInstantiated) {
+        node.isDirectlyInstantiated = true;
+      }
+      if (indirectlyInstantiated) {
+        node.isIndirectlyInstantiated = true;
+      }
+      return node;
+    }
+
     void addSubtypes(ClassElement cls) {
       if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
         return;
@@ -329,6 +383,8 @@
         compiler.internalError(cls, 'Class "${cls.name}" is not resolved.');
       }
 
+      createClassHierarchyNodeForClass(cls, directlyInstantiated: true);
+
       for (DartType type in cls.allSupertypes) {
         Set<Element> subtypesOfSupertype =
             _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>());
@@ -339,10 +395,6 @@
       // implemented by that type on the superclasses.
       ClassElement superclass = cls.superclass;
       while (superclass != null) {
-        Set<Element> subclassesOfSuperclass =
-            _subclasses.putIfAbsent(superclass, () => new Set<ClassElement>());
-        subclassesOfSuperclass.add(cls);
-
         Set<Element> typesImplementedBySubclassesOfCls =
             _typesImplementedBySubclasses.putIfAbsent(
                 superclass, () => new Set<ClassElement>());
diff --git a/pkg/js_ast/lib/src/builder.dart b/pkg/js_ast/lib/src/builder.dart
index 076ff65..67ea25c 100644
--- a/pkg/js_ast/lib/src/builder.dart
+++ b/pkg/js_ast/lib/src/builder.dart
@@ -377,6 +377,14 @@
                     List<Expression> arguments) {
     return new Call(new PropertyAccess(receiver, fieldName), arguments);
   }
+
+  ObjectInitializer objectLiteral(Map<String, Expression> map) {
+    List<Property> properties = <Property>[];
+    map.forEach((name, value) {
+      properties.add(new Property(string(name), value));
+    });
+    return new ObjectInitializer(properties);
+  }
 }
 
 LiteralString string(String value) => js.string(value);
@@ -400,6 +408,9 @@
                   List<Expression> arguments) {
   return js.propertyCall(receiver, fieldName, arguments);
 }
+ObjectInitializer objectLiteral(Map<String, Expression> map) {
+  return js.objectLiteral(map);
+}
 
 class MiniJsParserError {
   MiniJsParserError(this.parser, this.message) { }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index d5a359a..e98d307 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -88,8 +88,10 @@
 analyzer/test/generated/incremental_resolver_test: Pass, Slow # Issue 21628
 analyzer/test/generated/utilities_test: Pass, Slow # Issue 21628
 analyzer/test/generated/parser_test: Pass, Slow # Issue 21628
+analyzer/test/generated/scanner_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/dart_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/driver_test: Pass, Slow # Issue 21628
+analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
 
 [ $runtime == jsshell ]
 async/test/stream_zip_test: RuntimeError, OK # Timers are not supported.
@@ -151,44 +153,9 @@
 analyzer/test/*: PubGetError
 
 [ $compiler == dart2js && $cps_ir ]
-analyzer/test/cancelable_future_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/enum_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/file_system/memory_file_system_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/file_system/physical_resource_provider_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/file_system/resource_uri_resolver_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/all_the_rest_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/ast_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/compile_time_error_code_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/element_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/incremental_resolver_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/incremental_scanner_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/non_error_resolver_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/parser_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/resolver_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/scanner_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/source_factory_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/static_type_warning_code_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/static_warning_code_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/type_system_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/utilities_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/instrumentation/instrumentation_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/parse_compilation_unit_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/source/analysis_options_provider_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/source/package_map_provider_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/source/package_map_resolver_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/source/sdk_ext_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/context/cache_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/context/context_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/dart_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/dart_work_manager_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/driver_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/general_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/html_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/html_work_manager_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/incremental_element_builder_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/inputs_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/manager_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/task/model_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/util/asserts_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/src/util/lru_map_test: Crash # The null object does not have a getter '_element'.
+analyzer/test/cancelable_future_test: Crash # Invalid argument(s)
+analyzer/test/enum_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
+analyzer/test/file_system/physical_resource_provider_test: Crash # (Future _poll()async...  cannot handle async/sync*/async* functions
+analyzer/test/generated/all_the_rest_test: Crash # (Future test_implici...  cannot handle async/sync*/async* functions
+analyzer/test/src/context/context_test: Crash # Invalid argument(s)
 typed_data/test/typed_buffers_test/none: RuntimeError # Please triage this failure.
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 7caf19b..00c9f69 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -498,7 +498,6 @@
             '../tools/create_resources.py',
             # The following two files are used to trigger a rebuild.
             '<(PRODUCT_DIR)/observatory/deployed/web/index.html',
-            '<(PRODUCT_DIR)/observatory/deployed/web/index.html.polymer.bootstrap.dart.js',
             '<@(_sources)',
           ],
           'outputs': [
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 940556a..d678665 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -4,10 +4,18 @@
 
 library builtin;
 // NOTE: Do not import 'dart:io' in builtin.
+import 'dart:async';
 import 'dart:collection';
+import 'dart:_internal';
 import 'dart:isolate';
 import 'dart:typed_data';
 
+
+// Before handling an embedder entrypoint we finalize the setup of the
+// dart:_builtin library.
+bool _setupCompleted = false;
+
+
 // The root library (aka the script) is imported into this library. The
 // standalone embedder uses this to lookup the main entrypoint in the
 // root library's namespace.
@@ -49,10 +57,11 @@
 // The embedder forwards most loading requests to this library.
 
 // See Dart_LibraryTag in dart_api.h
-const Dart_kScriptTag = null;
-const Dart_kImportTag = 0;
-const Dart_kSourceTag = 1;
-const Dart_kCanonicalizeUrl = 2;
+const _Dart_kScriptTag = null;
+const _Dart_kImportTag = 0;
+const _Dart_kSourceTag = 1;
+const _Dart_kCanonicalizeUrl = 2;
+const _Dart_kResourceLoad = 3;
 
 // Embedder sets this to true if the --trace-loading flag was passed on the
 // command line.
@@ -78,15 +87,32 @@
 // package imports can be resolved relative to it. The root script is the basis
 // for the root library in the VM.
 Uri _rootScript;
+
+// Packages are either resolved looking up in a map or resolved from within a
+// package root.
+bool _packagesReady() => (_packageRoot != null) || (_packageMap != null);
 // The directory to look in to resolve "package:" scheme URIs. By detault it is
 // the 'packages' directory right next to the script.
-Uri _packageRoot = _rootScript.resolve('packages/');
+Uri _packageRoot = null; // Used to be _rootScript.resolve('packages/');
+// The map describing how certain package names are mapped to Uris.
+Map<String, Uri> _packageMap = null;
+// A list of pending packags which have been requested while resolving the
+// location of the package root or the contents of the package map.
+List<_LoadRequest> _pendingPackageLoads = [];
+
+// If we have outstanding loads or pending package loads waiting for resolution,
+// then we do have pending loads.
+bool _pendingLoads() => !_reqMap.isEmpty || !_pendingPackageLoads.isEmpty;
 
 // Special handling for Windows paths so that they are compatible with URI
 // handling.
 // Embedder sets this to true if we are running on Windows.
 bool _isWindows = false;
 
+// Logging from builtin.dart is prefixed with a '*'.
+_log(msg) {
+  _print("* $msg");
+}
 
 // A class wrapping the load error message in an Error object.
 class _LoadError extends Error {
@@ -102,9 +128,16 @@
   final int _id;
   final int _tag;
   final String _uri;
-  final String _libraryUri;
+  final Uri _resourceUri;
+  final _context;
 
-  _LoadRequest(this._id, this._tag, this._uri, this._libraryUri);
+  _LoadRequest(this._id,
+               this._tag,
+               this._uri,
+               this._resourceUri,
+               this._context);
+
+  toString() => "LoadRequest($_id, $_tag, $_uri, $_resourceUri, $_context)";
 }
 
 
@@ -171,12 +204,15 @@
 // Embedder Entrypoint:
 // The embedder calls this method with the current working directory.
 void _setWorkingDirectory(cwd) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   if (_traceLoading) {
-    _print('# Setting working directory: $cwd');
+    _log('Setting working directory: $cwd');
   }
   _workingDirectory = new Uri.directory(cwd);
   if (_traceLoading) {
-    _print('# Working directory URI: $_workingDirectory');
+    _log('Working directory URI: $_workingDirectory');
   }
 }
 
@@ -184,8 +220,11 @@
 // Embedder Entrypoint:
 // The embedder calls this method with a custom package root.
 _setPackageRoot(String packageRoot) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   if (_traceLoading) {
-    _print('# Setting package root: $packageRoot');
+    _log('Setting package root: $packageRoot');
   }
   packageRoot = _enforceTrailingSlash(packageRoot);
   if (packageRoot.startsWith('file:') ||
@@ -198,7 +237,7 @@
     _packageRoot = _workingDirectory.resolveUri(new Uri.file(packageRoot));
   }
   if (_traceLoading) {
-    _print('# Package root URI: $_packageRoot');
+    _log('Package root URI: $_packageRoot');
   }
 }
 
@@ -216,16 +255,36 @@
   }
 
   if (_traceLoading) {
-    _print('# Package root: $_packageRoot');
-    _print('# uri path: ${uri.path}');
+    _log('Resolving package with uri path: ${uri.path}');
   }
-  return _packageRoot.resolve(uri.path);
+  var resolvedUri;
+  if (_packageRoot != null) {
+    resolvedUri = _packageRoot.resolve(uri.path);
+  } else {
+    var packageName = uri.pathSegments[0];
+    var mapping = _packageMap[packageName];
+    if (_traceLoading) {
+      _log("Mapped '$packageName' package to '$mapping'");
+    }
+    if (mapping == null) {
+      throw "No mapping for '$packageName' package when resolving '$uri'.";
+    }
+    var path = uri.path.substring(packageName.length + 1);
+    resolvedUri = mapping.resolve(path);
+  }
+  if (_traceLoading) {
+    _log("Resolved '$uri' to '$resolvedUri'.");
+  }
+  return resolvedUri;
 }
 
 
 // Resolves the script uri in the current working directory iff the given uri
 // did not specify a scheme (e.g. a path to a script file on the command line).
 Uri _resolveScriptUri(String scriptName) {
+  if (_traceLoading) {
+    _log("Resolving script: $scriptName");
+  }
   if (_workingDirectory == null) {
     throw 'No current working directory set.';
   }
@@ -243,7 +302,7 @@
   _rootScript = scriptUri;
 
   if (_traceLoading) {
-    _print('# Resolved entry point to: $_rootScript');
+    _log('Resolved entry point to: $_rootScript');
   }
   return scriptUri;
 }
@@ -254,13 +313,14 @@
   var tmp = _reqMap.remove(req._id);
   assert(tmp == req);
   if (_traceLoading) {
-    _print("Loading of ${req._uri} finished, "
-    "${_reqMap.length} requests remaining");
+    _log("Loading of ${req._uri} finished: "
+         "${_reqMap.length} requests remaining, "
+         "${_pendingPackageLoads.length} packages pending.");
   }
 
-  if (_reqMap.isEmpty) {
+  if (!_pendingLoads()) {
     if (_traceLoading) {
-      _print("Closing loading port.");
+      _log("Closing loading port.");
     }
     _receivePort.close();
     _receivePort = null;
@@ -278,29 +338,36 @@
   var req = _reqMap[id];
   try {
     if (dataOrError is Uint8List) {
-      _loadScript(req, dataOrError);
+      // Successfully loaded the data.
+      if (req._tag == _Dart_kResourceLoad) {
+        Completer c = req._context;
+        c.complete(dataOrError);
+      } else {
+        // TODO: Currently a compilation error while loading the script is
+        // fatal for the isolate. _loadScriptCallback() does not return and
+        // the number of requests remains out of sync.
+        _loadScriptCallback(req._tag, req._uri, req._context, dataOrError);
+      }
+      _finishLoadRequest(req);
     } else {
       assert(dataOrError is String);
       var error = new _LoadError(req._uri, dataOrError.toString());
-      _asyncLoadError(req, error);
+      _asyncLoadError(req, error, null);
     }
   } catch(e, s) {
     // Wrap inside a _LoadError unless we are already propagating a
     // previous _LoadError.
     var error = (e is _LoadError) ? e : new _LoadError(req._uri, e.toString());
     assert(req != null);
-    _asyncLoadError(req, error);
+    _asyncLoadError(req, error, s);
   }
 }
 
 
-void _startLoadRequest(int tag,
-                       String uri,
-                       String libraryUri,
-                       Uri resourceUri) {
-  if (_reqMap.isEmpty) {
+void _startLoadRequest(int tag, String uri, Uri resourceUri, context) {
+  if (_receivePort == null) {
     if (_traceLoading) {
-      _print("Initializing load port.");
+      _log("Initializing load port.");
     }
     assert(_receivePort == null);
     assert(_sendPort == null);
@@ -311,59 +378,213 @@
   var curId = _reqId++;
 
   assert(_reqMap[curId] == null);
-  _reqMap[curId] = new _LoadRequest(curId, tag, uri, libraryUri);
+  _reqMap[curId] = new _LoadRequest(curId, tag, uri, resourceUri, context);
 
-  var msg = new List(3);
+  assert(_receivePort != null);
+  assert(_sendPort != null);
+
+  var msg = new List(4);
   msg[0] = _sendPort;
-  msg[1] = curId;
-  msg[2] = resourceUri.toString();
+  msg[1] = _traceLoading;
+  msg[2] = curId;
+  msg[3] = resourceUri.toString();
   _loadPort.send(msg);
 
   if (_traceLoading) {
-    _print("Loading of $resourceUri for $uri started with id: $curId, "
-           "${_reqMap.length} requests outstanding");
+    _log("Loading of $resourceUri for $uri started with id: $curId. "
+         "${_reqMap.length} requests remaining, "
+         "${_pendingPackageLoads.length} packages pending.");
   }
 }
 
 
-void _loadScript(_LoadRequest req, Uint8List data) {
-  // TODO: Currently a compilation error while loading the script is
-  // fatal for the isolate. _loadScriptCallback() does not return and
-  // the number of requests remains out of sync.
-  _loadScriptCallback(req._tag, req._uri, req._libraryUri, data);
-  _finishLoadRequest(req);
-}
+RawReceivePort _packagesPort;
 
+void _handlePackagesReply(msg) {
+  // Make sure to close the _packagePort before any other action.
+  _packagesPort.close();
 
-void _asyncLoadError(_LoadRequest req, _LoadError error) {
   if (_traceLoading) {
-    _print("_asyncLoadError(${req._uri}), error: $error");
+    _log("Got packages reply: $msg");
   }
-  var libraryUri = req._libraryUri;
-  if (req._tag == Dart_kImportTag) {
-    // When importing a library, the libraryUri is the imported
-    // uri.
-    libraryUri = req._uri;
+  if (msg is String) {
+    if (_traceLoading) {
+      _log("Got failure response on package port: '$msg'");
+    }
+    throw msg;
   }
-  _asyncLoadErrorCallback(req._uri, libraryUri, error);
+  if (msg.length == 1) {
+    if (_traceLoading) {
+      _log("Received package root: '${msg[0]}'");
+    }
+    _packageRoot = Uri.parse(msg[0]);
+  } else {
+    assert((msg.length % 2) == 0);
+    _packageMap = new Map<String, Uri>();
+    for (var i = 0; i < msg.length; i+=2) {
+      // TODO(iposva): Complain about duplicate entries.
+      _packageMap[msg[i]] = Uri.parse(msg[i+1]);
+    }
+    if (_traceLoading) {
+      _log("Setup package map: $_packageMap");
+    }
+  }
+
+  // Resolve all pending package loads now that we know how to resolve them.
+  while (_pendingPackageLoads.length > 0) {
+    var req = _pendingPackageLoads.removeLast();
+    if (req != null) {
+      if (_traceLoading) {
+        _log("Handling deferred load request: $req");
+      }
+      _loadPackage(req._tag, req._uri, req._resourceUri, req._context);
+    } else {
+      if (_traceLoading) {
+        _log("Skipping dummy deferred request.");
+      }
+    }
+  }
+  // Reset the pending package loads to empty. So that we eventually can
+  // finish loading.
+  _pendingPackageLoads = [];
+}
+
+
+void _requestPackagesMap() {
+  assert(_packagesPort == null);
+  assert(_rootScript != null);
+  // Create a port to receive the packages map on.
+  _packagesPort = new RawReceivePort(_handlePackagesReply);
+  var sp = _packagesPort.sendPort;
+
+  var msg = new List(4);
+  msg[0] = sp;
+  msg[1] = _traceLoading;
+  msg[2] = -1;
+  msg[3] = _rootScript.toString();
+  _loadPort.send(msg);
+
+  if (_traceLoading) {
+    _log("Requested packages map for '$_rootScript'.");
+  }
+}
+
+
+// Embedder Entrypoint:
+// Request the load of a particular packages map.
+void _loadPackagesMap(String packagesParam) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
+  // First convert the packages parameter from the command line to a URI which
+  // can be handled by the loader code.
+  // TODO(iposva): Consider refactoring the common code below which is almost
+  // shared with resolution of the root script.
+  if (_traceLoading) {
+    _log("Resolving packages map: $packagesParam");
+  }
+  if (_workingDirectory == null) {
+    throw 'No current working directory set.';
+  }
+  var packagesName = _sanitizeWindowsPath(packagesParam);
+  var packagesUri = Uri.parse(packagesName);
+  if (packagesUri.scheme == '') {
+    // Script does not have a scheme, assume that it is a path,
+    // resolve it against the working directory.
+    packagesUri = _workingDirectory.resolveUri(packagesUri);
+  }
+  if (_traceLoading) {
+    _log('Resolved packages map to: $packagesUri');
+  }
+
+  // Request the loading and parsing of the packages map at the specified URI.
+  // Create a port to receive the packages map on.
+  assert(_packagesPort == null);
+  _packagesPort = new RawReceivePort(_handlePackagesReply);
+  var sp = _packagesPort.sendPort;
+
+  var msg = new List(4);
+  msg[0] = sp;
+  msg[1] = _traceLoading;
+  msg[2] = -2;
+  msg[3] = packagesUri.toString();
+  _loadPort.send(msg);
+
+  // Signal that the resolution of the packages map has started. But in this
+  // case it is not tied to a particular request.
+  _pendingPackageLoads.add(null);
+
+  if (_traceLoading) {
+    _log("Requested packages map at '$packagesUri'.");
+  }
+}
+
+
+void _asyncLoadError(_LoadRequest req, _LoadError error, StackTrace stack) {
+  if (_traceLoading) {
+    _log("_asyncLoadError(${req._uri}), error: $error\nstack: $stack");
+  }
+  if (req._tag == _Dart_kResourceLoad) {
+    Completer c = req._context;
+    c.completeError(error, stack);
+  } else {
+    String libraryUri = req._context;
+    if (req._tag == _Dart_kImportTag) {
+      // When importing a library, the libraryUri is the imported
+      // uri.
+      libraryUri = req._uri;
+    }
+    _asyncLoadErrorCallback(req._uri, libraryUri, error);
+  }
   _finishLoadRequest(req);
 }
 
 
-_loadDataFromLoadPort(int tag,
-                      String uri,
-                      String libraryUri,
-                      Uri resourceUri) {
+_loadDataFromLoadPort(int tag, String uri, Uri resourceUri, context) {
   try {
-    _startLoadRequest(tag, uri, libraryUri, resourceUri);
-  } catch (e) {
+    _startLoadRequest(tag, uri, resourceUri, context);
+  } catch (e, s) {
     if (_traceLoading) {
-      _print("Exception when communicating with service isolate: $e");
+      _log("Exception when communicating with service isolate: $e");
     }
     // Wrap inside a _LoadError unless we are already propagating a previously
     // seen _LoadError.
     var error = (e is _LoadError) ? e : new _LoadError(e.toString());
-    _asyncLoadError(tag, uri, libraryUri, error);
+    _asyncLoadError(tag, uri, context, error, s);
+  }
+}
+
+
+// Loading a package URI needs to first map the package name to a loadable
+// URI.
+_loadPackage(int tag, String uri, Uri resourceUri, context) {
+  if (_packagesReady()) {
+    _loadData(tag, uri, _resolvePackageUri(resourceUri), context);
+  } else {
+    if (_pendingPackageLoads.isEmpty) {
+      // Package resolution has not been setup yet, and this is the first
+      // request for package resolution & loading.
+      _requestPackagesMap();
+    }
+    var req = new _LoadRequest(-1, tag, uri, resourceUri, context);
+    _pendingPackageLoads.add(req);
+    if (_traceLoading) {
+      _log("Pending package load of '$uri': "
+      "${_pendingPackageLoads.length} pending");
+    }
+  }
+}
+
+
+// Load the data associated with the resourceUri.
+_loadData(int tag, String uri, Uri resourceUri, context) {
+  if (resourceUri.scheme == 'package') {
+    // package based uris need to be resolved to the correct loadable location.
+    // The logic of which is handled seperately, and then _loadData is called
+    // recursively.
+    _loadPackage(tag, uri, resourceUri, context);
+  } else {
+    _loadDataFromLoadPort(tag, uri, resourceUri, context);
   }
 }
 
@@ -371,20 +592,17 @@
 // Embedder Entrypoint:
 // Asynchronously loads script data through a http[s] or file uri.
 _loadDataAsync(int tag, String uri, String libraryUri) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   var resourceUri;
-  if (tag == Dart_kScriptTag) {
+  if (tag == _Dart_kScriptTag) {
     resourceUri = _resolveScriptUri(uri);
     uri = resourceUri.toString();
   } else {
     resourceUri = Uri.parse(uri);
   }
-
-  // package based uris need to be resolved to the correct loadable location.
-  if (resourceUri.scheme == 'package') {
-    resourceUri = _resolvePackageUri(resourceUri);
-  }
-
-  _loadDataFromLoadPort(tag, uri, libraryUri, resourceUri);
+  _loadData(tag, uri, resourceUri, libraryUri);
 }
 
 
@@ -392,8 +610,11 @@
 // Function called by standalone embedder to resolve uris when the VM requests
 // Dart_kCanonicalizeUrl from the tag handler.
 String _resolveUri(String base, String userString) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   if (_traceLoading) {
-    _print('# Resolving: $userString from $base');
+    _log('Resolving: $userString from $base');
   }
   var baseUri = Uri.parse(base);
   var result;
@@ -404,15 +625,29 @@
     result = baseUri.resolve(userString).toString();
   }
   if (_traceLoading) {
-    _print('Resolved $userString in $base to $result');
+    _log('Resolved $userString in $base to $result');
   }
   return result;
 }
 
 
+// Handling of Resource class by dispatching to the load port.
+Future<List<int>> _resourceReadAsBytes(Uri uri) {
+  var completer = new Completer<List<int>>();
+  // Request the load of the resource associating the completer as the context
+  // for the load.
+  _loadData(_Dart_kResourceLoad, uri.toString(), uri, completer);
+  // Return the future that will be triggered once the resource has been loaded.
+  return completer.future;
+}
+
+
 // Embedder Entrypoint (gen_snapshot):
 // Resolve relative paths relative to working directory.
 String _resolveInWorkingDirectory(String fileName) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   if (_workingDirectory == null) {
     throw 'No current working directory set.';
   }
@@ -425,7 +660,7 @@
   uri = _workingDirectory.resolveUri(uri);
 
   if (_traceLoading) {
-    _print('# Resolved in working directory: $fileName -> $uri');
+    _log('Resolved in working directory: $fileName -> $uri');
   }
   return uri.toString();
 }
@@ -453,7 +688,7 @@
 String _filePathFromUri(String userUri) {
   var uri = Uri.parse(userUri);
   if (_traceLoading) {
-    _print('# Getting file path from: $uri');
+    _log('Getting file path from: $uri');
   }
 
   var path;
@@ -471,7 +706,7 @@
     // Only handling file, http, and package URIs
     // in standalone binary.
     if (_traceLoading) {
-      _print('# Unknown scheme (${uri.scheme}) in $uri.');
+      _log('Unknown scheme (${uri.scheme}) in $uri.');
     }
     throw 'Not a known scheme: $uri';
   }
@@ -487,6 +722,9 @@
 // The filename part is the extension name, with the platform-dependent
 // prefixes and extensions added.
 _extensionPathFromUri(String userUri) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   if (!userUri.startsWith(_DART_EXT)) {
     throw 'Unexpected internal error: Extension URI $userUri missing dart-ext:';
   }
@@ -514,3 +752,10 @@
 
   return [path, filename, name];
 }
+
+
+// Register callbacks and hooks with the rest of the core libraries.
+_setupHooks() {
+  _setupCompleted = true;
+  VMLibraryHooks.resourceReadAsBytes = _resourceReadAsBytes;
+}
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 844e9db..ad7f6e1 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -24,47 +24,6 @@
 // Advanced I/O classes like sockets and process management are implemented
 // using functions listed in io_natives.cc.
 #define BUILTIN_NATIVE_LIST(V)                                                 \
-  V(Crypto_GetRandomBytes, 1)                                                  \
-  V(Directory_Exists, 1)                                                       \
-  V(Directory_Create, 1)                                                       \
-  V(Directory_Current, 0)                                                      \
-  V(Directory_SetCurrent, 1)                                                   \
-  V(Directory_SystemTemp, 0)                                                   \
-  V(Directory_CreateTemp, 1)                                                   \
-  V(Directory_Delete, 2)                                                       \
-  V(Directory_Rename, 2)                                                       \
-  V(Directory_List, 3)                                                         \
-  V(File_Open, 2)                                                              \
-  V(File_Exists, 1)                                                            \
-  V(File_GetFD, 1)                                                             \
-  V(File_Close, 1)                                                             \
-  V(File_ReadByte, 1)                                                          \
-  V(File_WriteByte, 2)                                                         \
-  V(File_Read, 2)                                                              \
-  V(File_ReadInto, 4)                                                          \
-  V(File_WriteFrom, 4)                                                         \
-  V(File_Position, 1)                                                          \
-  V(File_SetPosition, 2)                                                       \
-  V(File_Truncate, 2)                                                          \
-  V(File_Length, 1)                                                            \
-  V(File_LengthFromPath, 1)                                                    \
-  V(File_Stat, 1)                                                              \
-  V(File_LastModified, 1)                                                      \
-  V(File_Flush, 1)                                                             \
-  V(File_Lock, 4)                                                              \
-  V(File_Create, 1)                                                            \
-  V(File_CreateLink, 2)                                                        \
-  V(File_LinkTarget, 1)                                                        \
-  V(File_Delete, 1)                                                            \
-  V(File_DeleteLink, 1)                                                        \
-  V(File_Rename, 2)                                                            \
-  V(File_Copy, 2)                                                              \
-  V(File_RenameLink, 2)                                                        \
-  V(File_ResolveSymbolicLinks, 1)                                              \
-  V(File_OpenStdio, 1)                                                         \
-  V(File_GetStdioHandleType, 1)                                                \
-  V(File_GetType, 2)                                                           \
-  V(File_AreIdentical, 2)                                                      \
   V(Builtin_PrintString, 1)                                                    \
   V(Builtin_LoadSource, 4)                                                     \
   V(Builtin_AsyncLoadError, 3)                                                 \
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 11c5f5b4..dd63bec 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -482,12 +482,6 @@
 Dart_Handle DartUtils::LoadScript(const char* script_uri,
                                   Dart_Handle builtin_lib) {
   Dart_Handle uri = Dart_NewStringFromCString(script_uri);
-
-  Dart_Port load_port = Dart_ServiceWaitForLoadPort();
-  if (load_port == ILLEGAL_PORT) {
-    return NewDartUnsupportedError("Service did not return load port.");
-  }
-  Builtin::SetLoadPort(load_port);
   IsolateData* isolate_data =
       reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
   Dart_TimelineAsyncBegin("LoadScript", &(isolate_data->load_async_id));
@@ -632,11 +626,12 @@
 }
 
 
-void DartUtils::PrepareBuiltinLibrary(Dart_Handle builtin_lib,
-                                      Dart_Handle internal_lib,
-                                      bool is_service_isolate,
-                                      bool trace_loading,
-                                      const char* package_root) {
+Dart_Handle DartUtils::PrepareBuiltinLibrary(Dart_Handle builtin_lib,
+                                             Dart_Handle internal_lib,
+                                             bool is_service_isolate,
+                                             bool trace_loading,
+                                             const char* package_root,
+                                             const char* packages_file) {
   // Setup the internal library's 'internalPrint' function.
   Dart_Handle print = Dart_Invoke(
       builtin_lib, NewString("_getPrintClosure"), 0, NULL);
@@ -655,16 +650,20 @@
                              NewString("_traceLoading"), Dart_True());
       DART_CHECK_VALID(result);
     }
-  }
-
-  if (!is_service_isolate) {
     // Set current working directory.
     result = SetWorkingDirectory(builtin_lib);
     DART_CHECK_VALID(result);
+    // Wait for the service isolate to initialize the load port.
+    Dart_Port load_port = Dart_ServiceWaitForLoadPort();
+    if (load_port == ILLEGAL_PORT) {
+      return NewDartUnsupportedError("Service did not return load port.");
+    }
+    Builtin::SetLoadPort(load_port);
   }
 
   // Set up package root if specified.
   if (package_root != NULL) {
+    ASSERT(packages_file == NULL);
     result = NewString(package_root);
     DART_CHECK_VALID(result);
     const int kNumArgs = 1;
@@ -675,7 +674,19 @@
                          kNumArgs,
                          dart_args);
     DART_CHECK_VALID(result);
+  } else if (packages_file != NULL) {
+    result = NewString(packages_file);
+    DART_CHECK_VALID(result);
+    const int kNumArgs = 1;
+    Dart_Handle dart_args[kNumArgs];
+    dart_args[0] = result;
+    result = Dart_Invoke(builtin_lib,
+                         NewString("_loadPackagesMap"),
+                         kNumArgs,
+                         dart_args);
+    DART_CHECK_VALID(result);
   }
+  return Dart_True();
 }
 
 
@@ -718,6 +729,7 @@
 
 
 Dart_Handle DartUtils::PrepareForScriptLoading(const char* package_root,
+                                               const char* packages_file,
                                                bool is_service_isolate,
                                                bool trace_loading,
                                                Dart_Handle builtin_lib) {
@@ -746,11 +758,14 @@
   Dart_Handle result = Dart_FinalizeLoading(false);
   DART_CHECK_VALID(result);
 
-  PrepareBuiltinLibrary(builtin_lib,
-                        internal_lib,
-                        is_service_isolate,
-                        trace_loading,
-                        package_root);
+  result = PrepareBuiltinLibrary(builtin_lib,
+                                 internal_lib,
+                                 is_service_isolate,
+                                 trace_loading,
+                                 package_root,
+                                 packages_file);
+  DART_CHECK_VALID(result);
+
   PrepareAsyncLibrary(async_lib, isolate_lib);
   PrepareCoreLibrary(core_lib, builtin_lib, is_service_isolate);
   PrepareIsolateLibrary(isolate_lib);
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 0c9ac19..8a9c953 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -124,11 +124,12 @@
                                        Dart_Handle url);
   static Dart_Handle LoadScript(const char* script_uri,
                                 Dart_Handle builtin_lib);
-  static void PrepareBuiltinLibrary(Dart_Handle builtin_lib,
-                                    Dart_Handle internal_lib,
-                                    bool is_service_isolate,
-                                    bool trace_loading,
-                                    const char* package_root);
+  static Dart_Handle PrepareBuiltinLibrary(Dart_Handle builtin_lib,
+                                           Dart_Handle internal_lib,
+                                           bool is_service_isolate,
+                                           bool trace_loading,
+                                           const char* package_root,
+                                           const char* packages_file);
   static void PrepareCoreLibrary(Dart_Handle core_lib,
                                  Dart_Handle builtin_lib,
                                  bool is_service_isolate);
@@ -137,6 +138,7 @@
   static void PrepareIOLibrary(Dart_Handle io_lib);
   static void PrepareIsolateLibrary(Dart_Handle isolate_lib);
   static Dart_Handle PrepareForScriptLoading(const char* package_root,
+                                             const char* packages_file,
                                              bool is_service_isolate,
                                              bool trace_loading,
                                              Dart_Handle builtin_lib);
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 0b69d91..2f19fb2 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -592,6 +592,7 @@
     // closures and setting up 'package root' for URI resolution.
     result =
         DartUtils::PrepareForScriptLoading(package_root,
+                                           NULL,
                                            false,
                                            false,
                                            builtin_lib);
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 8bbd2cd..2be3f34 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -20,7 +20,48 @@
 // Some classes, like File and Directory, list their implementations in
 // builtin_natives.cc instead.
 #define IO_NATIVE_LIST(V)                                                      \
+  V(Crypto_GetRandomBytes, 1)                                                  \
+  V(Directory_Exists, 1)                                                       \
+  V(Directory_Create, 1)                                                       \
+  V(Directory_Current, 0)                                                      \
+  V(Directory_SetCurrent, 1)                                                   \
+  V(Directory_SystemTemp, 0)                                                   \
+  V(Directory_CreateTemp, 1)                                                   \
+  V(Directory_Delete, 2)                                                       \
+  V(Directory_Rename, 2)                                                       \
+  V(Directory_List, 3)                                                         \
   V(EventHandler_SendData, 3)                                                  \
+  V(File_Open, 2)                                                              \
+  V(File_Exists, 1)                                                            \
+  V(File_GetFD, 1)                                                             \
+  V(File_Close, 1)                                                             \
+  V(File_ReadByte, 1)                                                          \
+  V(File_WriteByte, 2)                                                         \
+  V(File_Read, 2)                                                              \
+  V(File_ReadInto, 4)                                                          \
+  V(File_WriteFrom, 4)                                                         \
+  V(File_Position, 1)                                                          \
+  V(File_SetPosition, 2)                                                       \
+  V(File_Truncate, 2)                                                          \
+  V(File_Length, 1)                                                            \
+  V(File_LengthFromPath, 1)                                                    \
+  V(File_Stat, 1)                                                              \
+  V(File_LastModified, 1)                                                      \
+  V(File_Flush, 1)                                                             \
+  V(File_Lock, 4)                                                              \
+  V(File_Create, 1)                                                            \
+  V(File_CreateLink, 2)                                                        \
+  V(File_LinkTarget, 1)                                                        \
+  V(File_Delete, 1)                                                            \
+  V(File_DeleteLink, 1)                                                        \
+  V(File_Rename, 2)                                                            \
+  V(File_Copy, 2)                                                              \
+  V(File_RenameLink, 2)                                                        \
+  V(File_ResolveSymbolicLinks, 1)                                              \
+  V(File_OpenStdio, 1)                                                         \
+  V(File_GetStdioHandleType, 1)                                                \
+  V(File_GetType, 2)                                                           \
+  V(File_AreIdentical, 2)                                                      \
   V(FileSystemWatcher_CloseWatcher, 1)                                         \
   V(FileSystemWatcher_GetSocketId, 2)                                          \
   V(FileSystemWatcher_InitWatcher, 0)                                          \
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index 179bde5..49a993f 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -6,6 +6,7 @@
 #define BIN_ISOLATE_DATA_H_
 
 #include "include/dart_api.h"
+#include "platform/assert.h"
 #include "platform/globals.h"
 
 
@@ -20,23 +21,31 @@
 // when the isolate shuts down.
 class IsolateData {
  public:
-  explicit IsolateData(const char* url, const char* package_root)
+  explicit IsolateData(const char* url,
+                       const char* package_root,
+                       const char* packages_file)
       : script_url(strdup(url)),
         package_root(NULL),
+        packages_file(NULL),
         udp_receive_buffer(NULL),
         load_async_id(-1) {
     if (package_root != NULL) {
+      ASSERT(packages_file == NULL);
       this->package_root = strdup(package_root);
+    } else if (packages_file != NULL) {
+      this->packages_file = strdup(packages_file);
     }
   }
   ~IsolateData() {
     free(script_url);
     free(package_root);
+    free(packages_file);
     free(udp_receive_buffer);
   }
 
   char* script_url;
   char* package_root;
+  char* packages_file;
   uint8_t* udp_receive_buffer;
   int64_t load_async_id;
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 5b14dff..5c36f41 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -60,11 +60,22 @@
 // free'd.)
 static const char* commandline_package_root = NULL;
 
+// Value of the --packages flag.
+// (This pointer points into an argv buffer and does not need to be
+// free'd.)
+static const char* commandline_packages_file = NULL;
+
 
 // Global flag that is used to indicate that we want to compile all the
 // dart functions and not run anything.
 static bool has_compile_all = false;
 
+
+// Global flag that is used to indicate that we want to compile all the
+// dart functions before running main and not compile anything thereafter.
+static bool has_precompile = false;
+
+
 // Global flag that is used to indicate that we want to trace resolution of
 // URIs and the loading of libraries, parts and scripts.
 static bool has_trace_loading = false;
@@ -169,6 +180,17 @@
 }
 
 
+static bool ProcessPackagesOption(const char* arg,
+                                     CommandLineOptions* vm_options) {
+  ASSERT(arg != NULL);
+  if (*arg == '\0' || *arg == '-') {
+    return false;
+  }
+  commandline_packages_file = arg;
+  return true;
+}
+
+
 static void* GetHashmapKeyFromString(char* key) {
   return reinterpret_cast<void*>(key);
 }
@@ -266,6 +288,19 @@
   return true;
 }
 
+
+static bool ProcessPrecompileOption(const char* arg,
+                                    CommandLineOptions* vm_options) {
+  ASSERT(arg != NULL);
+  if (*arg != '\0') {
+    return false;
+  }
+  has_precompile = true;
+  vm_options->AddArgument("--precompile");
+  return true;
+}
+
+
 static bool ProcessDebugOption(const char* option_value,
                                CommandLineOptions* vm_options) {
   ASSERT(option_value != NULL);
@@ -371,10 +406,12 @@
   { "--verbose", ProcessVerboseOption },
   { "-v", ProcessVerboseOption },
   { "--package-root=", ProcessPackageRootOption },
+  { "--packages=", ProcessPackagesOption },
   { "-D", ProcessEnvironmentOption },
   // VM specific options to the standalone dart program.
   { "--break-at=", ProcessBreakpointOption },
   { "--compile_all", ProcessCompileAllOption },
+  { "--precompile", ProcessPrecompileOption },
   { "--debug", ProcessDebugOption },
   { "--snapshot=", ProcessGenScriptSnapshotOption },
   { "--enable-vm-service", ProcessEnableVmServiceOption },
@@ -489,6 +526,14 @@
     i++;
   }
 
+  // Verify consistency of arguments.
+  if ((commandline_package_root != NULL) &&
+      (commandline_packages_file != NULL)) {
+    Log::PrintErr("Specifying both a packages directory and a packages "
+                  "file is invalid.");
+    return -1;
+  }
+
   return 0;
 }
 
@@ -561,11 +606,14 @@
 static Dart_Isolate CreateIsolateAndSetupHelper(const char* script_uri,
                                                 const char* main,
                                                 const char* package_root,
+                                                const char* packages_file,
                                                 Dart_IsolateFlags* flags,
                                                 char** error,
                                                 int* exit_code) {
   ASSERT(script_uri != NULL);
-  IsolateData* isolate_data = new IsolateData(script_uri, package_root);
+  IsolateData* isolate_data = new IsolateData(script_uri,
+                                              package_root,
+                                              packages_file);
   Dart_Isolate isolate = NULL;
 
   isolate = Dart_CreateIsolate(script_uri,
@@ -597,7 +645,10 @@
       *error = strdup(VmService::GetErrorMessage());
       return NULL;
     }
-    if (has_compile_all) {
+    if (has_precompile) {
+      result = Dart_Precompile();
+      CHECK_RESULT(result);
+    } else if (has_compile_all) {
       result = Dart_CompileAll();
       CHECK_RESULT(result);
     }
@@ -618,6 +669,7 @@
   // Prepare for script loading by setting up the 'print' and 'timer'
   // closures and setting up 'package root' for URI resolution.
   result = DartUtils::PrepareForScriptLoading(package_root,
+                                              packages_file,
                                               false,
                                               has_trace_loading,
                                               builtin_lib);
@@ -675,16 +727,17 @@
       return NULL;
     }
   }
+  const char* packages_file = NULL;
   if (package_root == NULL) {
     if (parent_isolate_data != NULL) {
       package_root = parent_isolate_data->package_root;
-    } else {
-      package_root = ".";
+      packages_file = parent_isolate_data->packages_file;
     }
   }
   return CreateIsolateAndSetupHelper(script_uri,
                                      main,
                                      package_root,
+                                     packages_file,
                                      flags,
                                      error,
                                      &exit_code);
@@ -712,6 +765,12 @@
 "  all VM options).\n"
 "--package-root=<path> or -p<path>\n"
 "  Where to find packages, that is, \"package:...\" imports.\n"
+"--packages=<path>\n"
+"  Where to find a package spec file.\n"
+"--observe[=<port>[/<bind-address>]]\n"
+"  Enable the VM service and cause isolates to pause on exit (default port is\n"
+"  8181, default bind address is 127.0.0.1). With the default options,\n"
+"  Observatory will be available locally at http://127.0.0.1:8181/\n"
 "--version\n"
 "  Print the VM version.\n");
   } else {
@@ -724,6 +783,12 @@
 "  all VM options).\n"
 "--package-root=<path> or -p<path>\n"
 "  Where to find packages, that is, \"package:...\" imports.\n"
+"--packages=<path>\n"
+"  Where to find a package spec file.\n"
+"--observe[=<port>[/<bind-address>]]\n"
+"  Enable the VM service and cause isolates to pause on exit (default port is\n"
+"  8181, default bind address is 127.0.0.1). With the default options,\n"
+"  Observatory will be available locally at http://127.0.0.1:8181/\n"
 "--version\n"
 "  Print the VM version.\n"
 "\n"
@@ -989,6 +1054,7 @@
   Dart_Isolate isolate = CreateIsolateAndSetupHelper(script_name,
                                                      "main",
                                                      commandline_package_root,
+                                                     commandline_packages_file,
                                                      NULL,
                                                      &error,
                                                      &exit_code);
@@ -1041,7 +1107,10 @@
     ASSERT(!Dart_IsError(builtin_lib));
     result = Dart_LibraryImportLibrary(builtin_lib, root_lib, Dart_Null());
 
-    if (has_compile_all) {
+    if (has_precompile) {
+      result = Dart_Precompile();
+      DartExitOnError(result);
+    } else if (has_compile_all) {
       result = Dart_CompileAll();
       DartExitOnError(result);
     }
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index a95df08..68f63d9 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -4,10 +4,14 @@
 
 part of vmservice_io;
 
+_log(msg) {
+  print("% $msg");
+}
+
 var _httpClient;
 
 // Send a response to the requesting isolate.
-void _sendResponse(SendPort sp, int id, dynamic data) {
+void _sendResourceResponse(SendPort sp, int id, dynamic data) {
   assert((data is List<int>) || (data is String));
   var msg = new List(2);
   msg[0] = id;
@@ -29,17 +33,17 @@
             if (response.statusCode != 200) {
               var msg = "Failure getting $uri:\n"
                         "  ${response.statusCode} ${response.reasonPhrase}";
-              _sendResponse(sp, id, msg);
+              _sendResourceResponse(sp, id, msg);
             } else {
-              _sendResponse(sp, id, builder.takeBytes());
+              _sendResourceResponse(sp, id, builder.takeBytes());
             }
           },
           onError: (e) {
-            _sendResponse(sp, d, e.toString());
+            _sendResourceResponse(sp, id, e.toString());
           });
     })
     .catchError((e) {
-      _sendResponse(sp, id, e.toString());
+      _sendResourceResponse(sp, id, e.toString());
     });
   // It's just here to push an event on the event loop so that we invoke the
   // scheduled microtasks.
@@ -50,11 +54,11 @@
   var path = uri.toFilePath();
   var sourceFile = new File(path);
   sourceFile.readAsBytes().then((data) {
-    _sendResponse(sp, id, data);
+    _sendResourceResponse(sp, id, data);
   },
   onError: (e) {
     var err = "Error loading $uri:\n  $e";
-    _sendResponse(sp, id, err);
+    _sendResourceResponse(sp, id, err);
   });
 }
 
@@ -83,24 +87,365 @@
     }
 
     var data = UTF8.encode(Uri.decodeComponent(encodedData));
-    _sendResponse(sp, id, data);
+    _sendResourceResponse(sp, id, data);
   } catch (e) {
-    _sendResponse(sp, id, "Invalid data uri ($uri):\n  $e");
+    _sendResourceResponse(sp, id, "Invalid data uri ($uri):\n  $e");
   }
 }
 
+_handleResourceRequest(SendPort sp, bool traceLoading, int id, Uri resource) {
+  if (resource.scheme == 'file') {
+    _loadFile(sp, id, resource);
+  } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
+    _loadHttp(sp, id, resource);
+  } else if ((resource.scheme == 'data')) {
+    _loadDataUri(sp, id, resource);
+  } else {
+    _sendResourceResponse(sp, id,
+                          'Unknown scheme (${resource.scheme}) for $resource');
+  }
+}
+
+
+// Handling of packages requests. Finding and parsing of .packages file or
+// packages/ directories.
+const _LF    = 0x0A;
+const _CR    = 0x0D;
+const _SPACE = 0x20;
+const _HASH  = 0x23;
+const _DOT   = 0x2E;
+const _COLON = 0x3A;
+const _DEL   = 0x7F;
+
+const _invalidPackageNameChars = const [
+  // space  !      "      #      $      %      &      '
+     true , false, true , true , false, true , false, false,
+  // (      )      *      +      ,      -      .      /
+     false, false, false, false, false, false, false, true ,
+  // 0      1      2      3      4      5      6      7
+     false, false, false, false, false, false, false, false,
+  // 8      9      :      ;      <      =      >      ?
+     false, false, true , false, true , false, true , true ,
+  // @      A      B      C      D      E      F      G
+     false, false, false, false, false, false, false, false,
+  // H      I      J      K      L      M      N      O
+     false, false, false, false, false, false, false, false,
+  // P      Q      R      S      T      U      V      W
+     false, false, false, false, false, false, false, false,
+  // X      Y      Z      [      \      ]      ^      _
+     false, false, false, true , true , true , true , false,
+  // `      a      b      c      d      e      f      g
+     true , false, false, false, false, false, false, false,
+  // h      i      j      k      l      m      n      o
+     false, false, false, false, false, false, false, false,
+  // p      q      r      s      t      u      v      w
+     false, false, false, false, false, false, false, false,
+  // x      y      z      {      |      }      ~      DEL
+     false, false, false, true , true , true , false, true
+];
+
+_parsePackagesFile(SendPort sp,
+                   bool traceLoading,
+                   Uri packagesFile,
+                   List<int> data) {
+  var result = [];
+  var index = 0;
+  var len = data.length;
+  while (index < len) {
+    var start = index;
+    var char = data[index];
+    if ((char == _CR) || (char == _LF)) {
+      // Skipping empty lines.
+      index++;
+      continue;
+    }
+
+    // Identify split within the line and end of the line.
+    var separator = -1;
+    var end = len;
+    // Verifying validity of package name while scanning the line.
+    var nonDot = false;
+    var invalidPackageName = false;
+
+    // Scan to the end of the line or data.
+    while (index < len) {
+      char = data[index++];
+      // If we have not reached the separator yet, determine whether we are
+      // scanning legal package name characters.
+      if (separator == -1) {
+        if ((char == _COLON)) {
+          // The first colon on a line is the separator between package name and
+          // related URI.
+          separator = index - 1;
+        } else {
+          // Still scanning the package name part. Check for the validity of
+          // the characters.
+          nonDot = nonDot || (char != _DOT);
+          invalidPackageName = invalidPackageName ||
+                               (char < _SPACE) || (char > _DEL) ||
+                               _invalidPackageNameChars[char - _SPACE];
+        }
+      }
+      // Identify end of line.
+      if ((char == _CR) || (char == _LF)) {
+        end = index - 1;
+        break;
+      }
+    }
+
+    // No further handling needed for comment lines.
+    if (data[start] == _HASH) {
+      if (traceLoading) {
+        _log("Skipping comment in $packagesFile:\n"
+             "${new String.fromCharCodes(data, start, end)}");
+      }
+      continue;
+    }
+
+    // Check for a badly formatted line, starting with a ':'.
+    if (separator == start) {
+      var line = new String.fromCharCodes(data, start, end);
+      if (traceLoading) {
+        _log("Line starts with ':' in $packagesFile:\n"
+             "$line");
+      }
+      sp.send("Missing package name in $packagesFile:\n"
+              "$line");
+      return;
+    }
+
+    // Ensure there is a separator on the line.
+    if (separator == -1) {
+      var line = new String.fromCharCodes(data, start, end);
+      if (traceLoading) {
+        _log("Line has no ':' in $packagesFile:\n"
+              "$line");
+      }
+      sp.send("Missing ':' separator in $packagesFile:\n"
+              "$line");
+      return;
+    }
+
+    var packageName = new String.fromCharCodes(data, start, separator);
+
+    // Check for valid package name.
+    if (invalidPackageName || !nonDot) {
+      var line = new String.fromCharCodes(data, start, end);
+      if (traceLoading) {
+        _log("Invalid package name $packageName in $packagesFile");
+      }
+      sp.send("Invalid package name '$packageName' in $packagesFile:\n"
+              "$line");
+      return;
+    }
+
+    if (traceLoading) {
+      _log("packageName: $packageName");
+    }
+    var packageUri = new String.fromCharCodes(data, separator + 1, end);
+    if (traceLoading) {
+      _log("original packageUri: $packageUri");
+    }
+    // Ensure the package uri ends with a /.
+    if (!packageUri.endsWith("/")) {
+      packageUri = "$packageUri/";
+    }
+    packageUri = packagesFile.resolve(packageUri).toString();
+    if (traceLoading) {
+      _log("mapping: $packageName -> $packageUri");
+    }
+    result.add(packageName);
+    result.add(packageUri);
+  }
+
+  if (traceLoading) {
+    _log("Parsed packages file at $packagesFile. Sending:\n$result");
+  }
+  sp.send(result);
+}
+
+_loadPackagesFile(SendPort sp, bool traceLoading, Uri packagesFile) async {
+  try {
+    var data = await new File.fromUri(packagesFile).readAsBytes();
+    if (traceLoading) {
+      _log("Loaded packages file from $packagesFile:\n"
+           "${new String.fromCharCodes(data)}");
+    }
+    _parsePackagesFile(sp, traceLoading, packagesFile, data);
+  } catch (e, s) {
+    if (traceLoading) {
+      _log("Error loading packages: $e\n$s");
+    }
+    sp.send("Uncaught error ($e) loading packags file.");
+  }
+}
+
+_findPackagesFile(SendPort sp, bool traceLoading, Uri base) async {
+  try {
+    // Walk up the directory hierarchy to check for the existence of
+    // .packages files in parent directories and for the existense of a
+    // packages/ directory on the first iteration.
+    var dir = new File.fromUri(base).parent;
+    var prev = null;
+    // Keep searching until we reach the root.
+    while ((prev == null) || (prev.path != dir.path)) {
+      // Check for the existence of a .packages file and if it exists try to
+      // load and parse it.
+      var dirUri = dir.uri;
+      var packagesFile = dirUri.resolve(".packages");
+      if (traceLoading) {
+        _log("Checking for $packagesFile file.");
+      }
+      var exists = await new File.fromUri(packagesFile).exists();
+      if (traceLoading) {
+        _log("$packagesFile exists: $exists");
+      }
+      if (exists) {
+        _loadPackagesFile(sp, traceLoading, packagesFile);
+        return;
+      }
+      // On the first loop try whether there is a packages/ directory instead.
+      if (prev == null) {
+        var packageRoot = dirUri.resolve("packages/");
+        if (traceLoading) {
+          _log("Checking for $packageRoot directory.");
+        }
+        exists = await new Directory.fromUri(packageRoot).exists();
+        if (traceLoading) {
+          _log("$packageRoot exists: $exists");
+        }
+        if (exists) {
+          if (traceLoading) {
+            _log("Found a package root at: $packageRoot");
+          }
+          sp.send([packageRoot.toString()]);
+          return;
+        }
+      }
+      // Move up one level.
+      prev = dir;
+      dir = dir.parent;
+    }
+
+    // No .packages file was found.
+    if (traceLoading) {
+      _log("Could not resolve a package location from $base");
+    }
+    sp.send("Could not resolve a package location for base at $base");
+  } catch (e, s) {
+    if (traceLoading) {
+      _log("Error loading packages: $e\n$s");
+    }
+    sp.send("Uncaught error ($e) loading packages file.");
+  }
+}
+
+
+Future<bool> _loadHttpPackagesFile(SendPort sp,
+                                   bool traceLoading,
+                                   Uri resource) async {
+  try {
+    if (_httpClient == null) {
+      _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
+    }
+    if (traceLoading) {
+      _log("Fetching packages file from '$resource'.");
+    }
+    var req = await _httpClient.getUrl(resource);
+    var rsp = await req.close();
+    var builder = new BytesBuilder(copy: false);
+    await for (var bytes in rsp) {
+      builder.add(bytes);
+    }
+    if (rsp.statusCode != 200) {
+      if (traceLoading) {
+        _log("Got status ${rsp.statusCode} fetching '$resource'.");
+      }
+      return false;
+    }
+    var data = builder.takeBytes();
+    if (traceLoading) {
+      _log("Loaded packages file from '$resource':\n"
+           "${new String.fromCharCodes(data)}");
+    }
+    _parsePackagesFile(sp, traceLoading, resource, data);
+  } catch (e, s) {
+    if (traceLoading) {
+      _log("Error loading packages file from '$resource': $e\n$s");
+    }
+    sp.send("Uncaught error ($e) loading packages file from '$resource'.");
+  }
+  return false;
+}
+
+_handlePackagesRequest(SendPort sp,
+                       bool traceLoading,
+                       int id,
+                       Uri resource) async {
+  try {
+    if (id == -1) {
+      if (resource.scheme == 'file') {
+        _findPackagesFile(sp, traceLoading, resource);
+      } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
+        // Try to load the .packages file next to the resource.
+        var packagesUri = resource.resolve(".packages");
+        var exists = await _loadHttpPackagesFile(sp, traceLoading, packagesUri);
+        if (!exists) {
+          // If the loading of the .packages file failed for http/https based
+          // scripts then setup the package root.
+          var packageRoot = resource.resolve('packages/');
+          sp.send([packageRoot.toString()]);
+        }
+      } else {
+        sp.send("Unsupported base URI to identify .packages file: "
+                "'$resource'.");
+      }
+    } else if (id == -2) {
+      if (traceLoading) {
+        _log("Handling load of packages map: '$resource'.");
+      }
+      if (resource.scheme == 'file') {
+        var exists = await new File.fromUri(resource).exists();
+        if (exists) {
+          _loadPackagesFile(sp, traceLoading, resource);
+        } else {
+          sp.send("Packages file '$resource' not found.");
+        }
+      } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
+        var exists = await _loadHttpPackagesFile(sp, traceLoading, resource);
+        if (!exists) {
+          sp.send("Packages file '$resource' not found.");
+        }
+      } else {
+        sp.send("Unknown scheme (${resource.scheme}) for package file at "
+                "'$resource'.");
+      }
+    } else {
+      sp.send("Unknown packages request id: $id for '$resource'.");
+    }
+  } catch (e, s) {
+    if (traceLoading) {
+      _log("Error handling packages request: $e\n$s");
+    }
+    sp.send("Uncaught error ($e) handling packages request.");
+  }
+}
+
+
+// External entry point for loader requests.
 _processLoadRequest(request) {
   SendPort sp = request[0];
-  int id = request[1];
-  String resource = request[2];
-  var uri = Uri.parse(request[2]);
-  if (uri.scheme == 'file') {
-    _loadFile(sp, id, uri);
-  } else if ((uri.scheme == 'http') || (uri.scheme == 'https')) {
-    _loadHttp(sp, id, uri);
-  } else if ((uri.scheme == 'data')) {
-    _loadDataUri(sp, id, uri);
+  assert(sp != null);
+  bool traceLoading = request[1];
+  assert(traceLoading != null);
+  int id = request[2];
+  assert(id != null);
+  String resource = request[3];
+  assert(resource != null);
+  var uri = Uri.parse(resource);
+  if (id >= 0) {
+    _handleResourceRequest(sp, traceLoading, id, uri);
   } else {
-    sp.send([id, 'Unknown scheme (${uri.scheme}) for $uri']);
+    _handlePackagesRequest(sp, traceLoading, id, uri);
   }
 }
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 4723ca5..1f807e7 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -8,6 +8,7 @@
   static const int PARSE_ERROR_CODE = 4000;
   static const int BINARY_MESSAGE_ERROR_CODE = 4001;
   static const int NOT_MAP_ERROR_CODE = 4002;
+  static const int ID_ERROR_CODE = 4003;
   final WebSocket socket;
 
   WebSocketClient(this.socket, VMService service) : super(service) {
@@ -29,6 +30,9 @@
         return;
       }
       var serial = map['id'];
+      if (serial != null && serial is! num && serial is! String) {
+        socket.close(ID_ERROR_CODE, '"id" must be a number, string, or null.');
+      }
       onMessage(serial, new Message.fromJsonRpc(this, map));
     } else {
       socket.close(BINARY_MESSAGE_ERROR_CODE, 'Message must be a string.');
@@ -91,21 +95,6 @@
     _displayMessages = (_ip != '127.0.0.1' || _port != 8181);
   }
 
-  bool _shouldServeObservatory(HttpRequest request) {
-    if (request.headers['Observatory-Version'] != null) {
-      // Request is already coming from Observatory.
-      return false;
-    }
-    // TODO(johnmccutchan): Test with obscure browsers.
-    if (request.headers.value(HttpHeaders.USER_AGENT).contains('Mozilla')) {
-      // Request is coming from a browser but not Observatory application.
-      // Serve Observatory and let the Observatory make the real request.
-      return true;
-    }
-    // All other user agents are assumed to be textual.
-    return false;
-  }
-
   void _requestHandler(HttpRequest request) {
     // Allow cross origin requests with 'observatory' header.
     request.response.headers.add('Access-Control-Allow-Origin', '*');
@@ -129,10 +118,6 @@
     }
 
     var resource = Resource.resources[path];
-    if (resource == null && _shouldServeObservatory(request)) {
-      resource = Resource.resources[ROOT_REDIRECT_PATH];
-      assert(resource != null);
-    }
     if (resource != null) {
       // Serving up a static resource (e.g. .css, .html, .png).
       request.response.headers.contentType =
@@ -141,6 +126,7 @@
       request.response.close();
       return;
     }
+    // HTTP based service request.
     var client = new HttpRequestClient(request, _service);
     var message = new Message.fromUri(client, request.uri);
     client.onMessage(null, message);
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 25af328..195a6ce 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -64,7 +64,8 @@
 
   // Prepare for script loading by setting up the 'print' and 'timer'
   // closures and setting up 'package root' for URI resolution.
-  result = DartUtils::PrepareForScriptLoading(NULL, true, false, builtin_lib);
+  result = DartUtils::PrepareForScriptLoading(
+      NULL, NULL, true, false, builtin_lib);
   CHECK_RESULT(result);
 
   ASSERT(Dart_IsServiceIsolate(isolate));
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index d59be63..89d802f 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -172,7 +172,8 @@
 
   // Prepare for script loading by setting up the 'print' and 'timer'
   // closures and setting up 'package root' for URI resolution.
-  result = DartUtils::PrepareForScriptLoading(NULL, true, false, builtin_lib);
+  result = DartUtils::PrepareForScriptLoading(
+      NULL, NULL, true, false, builtin_lib);
   SHUTDOWN_ON_ERROR(result);
 
   // Load main script.
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 2176aad..5a27249 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -40,6 +40,7 @@
   Dart_CObject_kTypedData,
   Dart_CObject_kExternalTypedData,
   Dart_CObject_kSendPort,
+  Dart_CObject_kCapability,
   Dart_CObject_kUnsupported,
   Dart_CObject_kNumberOfTypes
 } Dart_CObject_Type;
@@ -62,6 +63,9 @@
       Dart_Port origin_id;
     } as_send_port;
     struct {
+      int64_t id;
+    } as_capability;
+    struct {
       intptr_t length;
       struct _Dart_CObject** values;
     } as_array;
@@ -155,5 +159,6 @@
  * TODO(turnidge): Document.
  */
 DART_EXPORT Dart_Handle Dart_CompileAll();
+DART_EXPORT Dart_Handle Dart_Precompile();
 
 #endif  /* INCLUDE_DART_NATIVE_API_H_ */  /* NOLINT */
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 0358cc2..2a45ae7 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -205,27 +205,3 @@
     }
   }
 }
-
-patch class Resource {
-  /* patch */ const factory Resource(String uri) = _Resource;
-}
-
-class _Resource implements Resource {
-  final String _location;
-
-  const _Resource(String uri) : _location = uri;
-
-  Uri get uri => Uri.base.resolve(_location);
-
-  Stream<List<int>> openRead() {
-    throw new UnimplementedError("openRead");
-  }
-
-  Future<List<int>> readAsBytes() {
-    throw new UnimplementedError("readAsBytes");
-  }
-
-  Future<String> readAsString({Encoding encoding}) {
-    throw new UnimplementedError("readAsString");
-  }
-}
diff --git a/runtime/lib/core_sources.gypi b/runtime/lib/core_sources.gypi
index 8bab528..73a4e04 100644
--- a/runtime/lib/core_sources.gypi
+++ b/runtime/lib/core_sources.gypi
@@ -44,6 +44,7 @@
     'object_patch.dart',
     'regexp.cc',
     'regexp_patch.dart',
+    'resource_patch.dart',
     'stacktrace.cc',
     'stacktrace.dart',
     'stopwatch.cc',
diff --git a/runtime/lib/developer.cc b/runtime/lib/developer.cc
index 786e5de..464e89b 100644
--- a/runtime/lib/developer.cc
+++ b/runtime/lib/developer.cc
@@ -37,4 +37,26 @@
   return inspectee.raw();
 }
 
+
+DEFINE_NATIVE_ENTRY(Developer_log, 8) {
+  GET_NON_NULL_NATIVE_ARGUMENT(String, message, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, timestamp, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, sequence, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, level, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(4));
+  GET_NATIVE_ARGUMENT(Instance, dart_zone, arguments->NativeArgAt(5));
+  GET_NATIVE_ARGUMENT(Instance, error, arguments->NativeArgAt(6));
+  GET_NATIVE_ARGUMENT(Instance, stack_trace, arguments->NativeArgAt(7));
+  Service::SendLogEvent(isolate,
+                        sequence.AsInt64Value(),
+                        timestamp.AsInt64Value(),
+                        level.Value(),
+                        name,
+                        message,
+                        dart_zone,
+                        error,
+                        stack_trace);
+  return Object::null();
+}
+
 }  // namespace dart
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index 689f23e..707d591 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -2,6 +2,50 @@
 // for 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 bool debugger({bool when: true, String msg}) native "Developer_debugger";
+patch bool debugger({bool when: true,
+                     String message}) native "Developer_debugger";
 
-patch inspect(object) native "Developer_inspect";
+patch Object inspect(Object object) native "Developer_inspect";
+
+patch log(String message,
+          {DateTime time,
+           int sequenceNumber,
+           int level: 0,
+           String name: '',
+           Zone zone,
+           Object error,
+           StackTrace stackTrace}) {
+  if (message is! String) {
+    throw new ArgumentError(message, "message", "Must be a String");
+  }
+  if (time == null) {
+    time = new DateTime.now();
+  }
+  if (time is! DateTime) {
+    throw new ArgumentError(time, "time", "Must be a DateTime");
+  }
+  if (sequenceNumber == null) {
+    sequenceNumber = _nextSequenceNumber++;
+  } else {
+    _nextSequenceNumber = sequenceNumber + 1;
+  }
+  return _log(message,
+              time.millisecondsSinceEpoch,
+              sequenceNumber,
+              level,
+              name,
+              zone,
+              error,
+              stackTrace);
+}
+
+int _nextSequenceNumber = 0;
+
+_log(String message,
+     int timestamp,
+     int sequenceNumber,
+     int level,
+     String name,
+     Zone zone,
+     Object error,
+     StackTrace stackTrace) native "Developer_log";
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 63f868b..9192b28 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// TODO(srdjan): fix limitations.
-// - shift amount must be a Smi.
 class _IntegerImplementation extends _Num {
   // The Dart class _Bigint extending _IntegerImplementation requires a
   // default constructor.
diff --git a/runtime/lib/internal_patch.dart b/runtime/lib/internal_patch.dart
index ce44229..f2fe680 100644
--- a/runtime/lib/internal_patch.dart
+++ b/runtime/lib/internal_patch.dart
@@ -13,6 +13,8 @@
   static var timerFactory;
   // Example: "dart:io _EventHandler._sendData"
   static var eventHandlerSendData;
+  // Implementation of Resource.readAsBytes.
+  static var resourceReadAsBytes;
 }
 
 patch class CodeUnits {
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 7e1c496..e3dbec1 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -301,7 +301,7 @@
         readyPort.close();
       }
       return new Future<Isolate>.error(e, st);
-    };
+    }
   }
 
   /* patch */ static Future<Isolate> spawnUri(
@@ -334,7 +334,7 @@
         readyPort.close();
       }
       return new Future<Isolate>.error(e, st);
-    };
+    }
     return completer.future;
   }
 
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 45eb5ef..5942078 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -114,8 +114,6 @@
   void _nextState() native "Random_nextState";
 
   int nextInt(int max) {
-    // TODO(srdjan): Remove the 'limit' check once optimizing comparison of
-    // Smi-s with Mint constants.
     final limit = 0x3FFFFFFF;
     if (max <= 0 || ((max > limit) && (max > _POW2_32))) {
       throw new ArgumentError("max must be positive and < 2^32:"
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 33af271..24c9523 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -373,10 +373,12 @@
 
 
 static RawInstance* CreateLibraryMirror(const Library& lib) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   ASSERT(!lib.IsNull());
-  const Array& args = Array::Handle(Array::New(3));
-  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(lib)));
-  String& str = String::Handle();
+  const Array& args = Array::Handle(zone, Array::New(3));
+  args.SetAt(0, MirrorReference::Handle(zone, MirrorReference::New(lib)));
+  String& str = String::Handle(zone);
   str = lib.name();
   args.SetAt(1, str);
   str = lib.url();
@@ -384,6 +386,21 @@
     // Censored library (grumble).
     return Instance::null();
   }
+  if (str.Equals("dart:io")) {
+    // Hack around dart:io being loaded into non-service isolates in Dartium.
+    Isolate* isolate = thread->isolate();
+    const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
+      zone, isolate->object_store()->libraries());
+    Library& other_lib = Library::Handle(zone);
+    String& other_uri = String::Handle(zone);
+    for (intptr_t i = 0; i < libraries.Length(); i++) {
+      other_lib ^= libraries.At(i);
+      other_uri = other_lib.url();
+      if (other_uri.Equals("dart:html")) {
+        return Instance::null();
+      }
+    }
+  }
   args.SetAt(2, str);
   return CreateMirror(Symbols::_LocalLibraryMirror(), args);
 }
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 2e55bfd..c64be5d 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -447,11 +447,16 @@
     var result = reflect(_invokeGetter(_reflectee, unwrapped));
     // Wait until success to avoid creating closures for non-existent getters,
     // and defer the creation until the next getField invocation.
-    _getFieldClosures[unwrapped] = (receiver) {
-      var getterClosure = _createGetterClosure(unwrapped);
-      _getFieldClosures[unwrapped] = getterClosure;
-      return getterClosure(receiver);
-    };
+    // o.<operator> is not valid Dart and will cause a compilation error, so
+    // don't attempt to generate such a closure.
+    bool isOperator = _LocalMethodMirror._operators.contains(unwrapped);
+    if (!isOperator) {
+      _getFieldClosures[unwrapped] = (receiver) {
+        var getterClosure = _createGetterClosure(unwrapped);
+        _getFieldClosures[unwrapped] = getterClosure;
+        return getterClosure(receiver);
+      };
+    }
     return result;
   }
 
diff --git a/runtime/lib/resource_patch.dart b/runtime/lib/resource_patch.dart
new file mode 100644
index 0000000..0643516
--- /dev/null
+++ b/runtime/lib/resource_patch.dart
@@ -0,0 +1,68 @@
+// 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.
+
+patch class Resource {
+  /* patch */ const factory Resource(String uri) = _Resource;
+}
+
+class _Resource implements Resource {
+  final String _location;
+
+  const _Resource(this._location);
+
+  Uri get uri => Uri.base.resolve(_location);
+
+  Stream<List<int>> openRead() {
+    if (VMLibraryHooks.resourceReadAsBytes == null) {
+      throw new UnimplementedError("openRead");
+    }
+
+    var controller = new StreamController<List<int>>();
+    // We only need to implement the listener as there is no way to provide
+    // back pressure into the channel.
+    controller.onListen = () {
+      // Once there is a listener, we kick off the loading of the resource.
+      readAsBytes().then((value) {
+        // The resource loading implementation sends all of the data in a
+        // single message. So the stream will only get a single value posted.
+        controller.add(value);
+        controller.close();
+      },
+      onError: (e, s) {
+        // In case the future terminates with an error we propagate it to the
+        // stream.
+        controller.addError(e, s);
+        controller.close();
+      });
+    };
+
+    return controller.stream;
+  }
+
+  Future<List<int>> readAsBytes() {
+    if (VMLibraryHooks.resourceReadAsBytes == null) {
+      throw new UnimplementedError("readAsBytes");
+    }
+
+    return VMLibraryHooks.resourceReadAsBytes(this.uri);
+  }
+
+  Future<String> readAsString({Encoding encoding : UTF8}) {
+    if (VMLibraryHooks.resourceReadAsBytes == null) {
+      throw new UnimplementedError("readAsString");
+    }
+
+    var completer = new Completer<String>();
+
+    readAsBytes().then((bytes) {
+      var str = encoding.decode(bytes);
+      completer.complete(str);
+    },
+    onError: (e, s) {
+      completer.completeError(e,s);
+    });
+
+    return completer.future;
+  }
+}
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index 6991ead..d087550 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -55,17 +55,7 @@
   /* patch */ int get length => _partsCodeUnits + _bufferPosition;
 
   /* patch */ void write(Object obj) {
-    String str;
-    if (obj is String) {
-      str = obj;
-    } else {
-      // TODO(srdjan): The following four lines could be replaced by
-      // '$obj', but apparently this is too slow on the Dart VM.
-      str = obj.toString();
-      if (str is! String) {
-        throw new ArgumentError('toString() did not return a string');
-      }
-    }
+    String str = '$obj';
     if (str.isEmpty) return;
     _consumeBuffer();
     _addPart(str);
diff --git a/runtime/lib/symbol_patch.dart b/runtime/lib/symbol_patch.dart
index 16a3ebb..fdb6527 100644
--- a/runtime/lib/symbol_patch.dart
+++ b/runtime/lib/symbol_patch.dart
@@ -11,6 +11,11 @@
   static getUnmangledName(Symbol symbol) {
     String string = Symbol.getName(symbol);
 
+    // Remove closurization hash mark
+    // #foo -> foo
+    if (string.startsWith('#')) {
+      string = string.substring(1);
+    }
     // get:foo -> foo
     // set:foo -> foo=
     // get:_foo@xxx -> _foo
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index 5a25ea3..bcaf0ab 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -36,6 +36,7 @@
 export 'package:observatory/src/elements/json_view.dart';
 export 'package:observatory/src/elements/library_ref.dart';
 export 'package:observatory/src/elements/library_view.dart';
+export 'package:observatory/src/elements/logging.dart';
 export 'package:observatory/src/elements/metrics.dart';
 export 'package:observatory/src/elements/nav_bar.dart';
 export 'package:observatory/src/elements/object_common.dart';
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index c64656a..9888697 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -29,6 +29,7 @@
 <link rel="import" href="src/elements/json_view.html">
 <link rel="import" href="src/elements/library_ref.html">
 <link rel="import" href="src/elements/library_view.html">
+<link rel="import" href="src/elements/logging.html">
 <link rel="import" href="src/elements/metrics.html">
 <link rel="import" href="src/elements/nav_bar.html">
 <link rel="import" href="src/elements/object_common.html">
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index 0580f5c..0faa080 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -204,11 +204,11 @@
           bytes.offsetInBytes + offset,
           bytes.lengthInBytes - offset);
       var map = _parseJSON(meta);
-      if (map == null) {
+      if (map == null || map['method'] != 'streamNotify') {
         return;
       }
-      var event = map['event'];
-      var streamId = map['streamId'];
+      var event = map['params']['event'];
+      var streamId = map['params']['streamId'];
       postServiceEvent(streamId, event, data);
     });
   }
@@ -218,9 +218,10 @@
     if (map == null) {
       return;
     }
-    var event = map['event'];
-    if (event != null) {
-      var streamId = map['streamId'];
+
+    if (map['method'] == 'streamNotify') {
+      var event = map['params']['event'];
+      var streamId = map['params']['streamId'];
       postServiceEvent(streamId, event, null);
       return;
     }
diff --git a/runtime/observatory/lib/service_io.dart b/runtime/observatory/lib/service_io.dart
index 9bd5242..2a91426 100644
--- a/runtime/observatory/lib/service_io.dart
+++ b/runtime/observatory/lib/service_io.dart
@@ -16,7 +16,7 @@
 
 class _IOWebSocket implements CommonWebSocket {
   WebSocket _webSocket;
-  
+
   void connect(String address,
                void onOpen(),
                void onMessage(dynamic data),
@@ -34,20 +34,20 @@
       onError();
     });
   }
-  
+
   bool get isOpen =>
       (_webSocket != null) && (_webSocket.readyState == WebSocket.OPEN);
-  
+
   void send(dynamic data) {
     _webSocket.add(data);
   }
-  
+
   void close() {
     if (_webSocket != null) {
       _webSocket.close();
     }
   }
-  
+
   Future<ByteData> nonStringToByteData(dynamic data) {
     assert(data is Uint8List);
     Logger.root.info('Binary data size in bytes: ${data.lengthInBytes}');
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index 3dc046d..ff45043 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -138,6 +138,7 @@
     _pageRegistry.add(new ErrorViewPage(this));
     _pageRegistry.add(new MetricsPage(this));
     _pageRegistry.add(new PortsPage(this));
+    _pageRegistry.add(new LoggingPage(this));
     // Note that ErrorPage must be the last entry in the list as it is
     // the catch all.
     _pageRegistry.add(new ErrorPage(this));
@@ -225,4 +226,7 @@
     Logger.root.warning('Caught exception: ${e}\n${st}');
     notifications.add(new Notification.fromException(e, st));
   }
+
+  // This map keeps track of which curly-blocks have been expanded by the user.
+  Map<String,bool> expansions = {};
 }
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 3a96752..bc2bb43 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -294,6 +294,22 @@
   }
 }
 
+
+class LoggingPage extends SimplePage {
+  LoggingPage(app) : super('logging', 'logging-page', app);
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      if (element != null) {
+        /// Update the page.
+        LoggingPageElement page = element;
+        page.isolate = isolate;
+      }
+    });
+  }
+}
+
 class ErrorViewPage extends Page {
   ErrorViewPage(app) : super(app);
 
diff --git a/runtime/observatory/lib/src/cli/command.dart b/runtime/observatory/lib/src/cli/command.dart
index d6be00d..04ff48e 100644
--- a/runtime/observatory/lib/src/cli/command.dart
+++ b/runtime/observatory/lib/src/cli/command.dart
@@ -78,7 +78,7 @@
   List<Command> _match(List<String> args, bool preferExact) {
     if (args.isEmpty) {
       return [];
-    }    
+    }
     bool lastArg = (args.length == 1);
     var matches = _matchLocal(args[0], !lastArg || preferExact);
     if (matches.isEmpty) {
diff --git a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
index c29b30e..a67b1db 100644
--- a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
+++ b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
@@ -544,15 +544,6 @@
     }
     profileCodes.sort(_sortCodes);
 
-    if (hasOptimizedCode()) {
-      attributes.add('optimized');
-    }
-    if (hasUnoptimizedCode()) {
-      attributes.add('unoptimized');
-    }
-    if (isInlined()) {
-      attributes.add('inlined');
-    }
     _addKindBasedAttributes(attributes);
     exclusiveTicks = int.parse(data['exclusiveTicks']);
     inclusiveTicks = int.parse(data['inclusiveTicks']);
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index cca7a1c..469609b 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -283,7 +283,7 @@
     var base = match.group(1);
     var qualifier = match.group(2);
     base = (base == null ? '' : base);
-    
+
     if (qualifier == null) {
       return _lookupClass(isolate, base, allowPrefix:true).then((classes) {
         var completions = [];
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 7652a4b..bb5a626 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -432,12 +432,78 @@
   }
 }
 
-/// Displays a CpuProfile
-@CustomTag('cpu-profile')
-class CpuProfileElement extends ObservatoryElement {
-  static const MICROSECONDS_PER_SECOND = 1000000.0;
+@CustomTag('sample-buffer-control')
+class SampleBufferControlElement extends ObservatoryElement {
+  SampleBufferControlElement.created() : super.created() {
+    _stopWatch.start();
+  }
 
-  @published Isolate isolate;
+  Future<CpuProfile> reload(Isolate isolate) async {
+    profile.clear();
+    if (isolate == null) {
+      _update(profile);
+      // Notify listener.
+      onSampleBufferUpdate(profile);
+      return profile;
+    }
+    await _changeState(kFetchingState);
+    try {
+      var params = { 'tags': tagSelector };
+      var response = await isolate.invokeRpc('_getCpuProfile', params);
+      await _changeState(kLoadingState);
+      profile.load(isolate, response);
+      _update(profile);
+      await _changeState(kLoadedState);
+      // Notify listener.
+      onSampleBufferUpdate(profile);
+      return profile;
+    } catch (e, st) {
+      if (e is ServerRpcException) {
+        ServerRpcException se = e;
+        if (se.code == ServerRpcException.kFeatureDisabled) {
+          await _changeState(kDisabledState);
+          return profile;
+        }
+      }
+      await _changeState(kExceptionState, e, st);
+      rethrow;
+    }
+  }
+
+  Future _changeState(String newState, [exception, stackTrace]) {
+    if ((newState == kDisabledState) ||
+        (newState == kFetchingState) ||
+        (newState == kExceptionState)) {
+      loadTime = '';
+      fetchTime = '';
+    } else if (newState == kLoadingState) {
+      fetchTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds);
+      loadTime = '';
+    } else if (newState == kLoadedState) {
+      loadTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds);
+    }
+    state = newState;
+    this.exception = exception;
+    this.stackTrace = stackTrace;
+    _stopWatch.reset();
+    return window.animationFrame;
+  }
+
+  _update(CpuProfile sampleBuffer) {
+    sampleCount = profile.sampleCount.toString();
+    refreshTime = new DateTime.now().toString();
+    stackDepth = profile.stackDepth.toString();
+    sampleRate = profile.sampleRate.toStringAsFixed(0);
+    timeSpan = formatTime(profile.timeSpan);
+  }
+
+  void tagSelectorChanged(oldValue) {
+    reload(profile.isolate);
+  }
+
+  Function onSampleBufferUpdate;
+  @observable bool showTagSelector = true;
+
   @observable String sampleCount = '';
   @observable String refreshTime = '';
   @observable String sampleRate = '';
@@ -446,119 +512,86 @@
   @observable String fetchTime = '';
   @observable String loadTime = '';
   @observable String tagSelector = 'UserVM';
-  @observable String modeSelector = 'Function';
-  @observable String directionSelector = 'Up';
-
-  @observable String state = 'Requested';
+  @observable String state = 'kFetching';
   @observable var exception;
   @observable var stackTrace;
 
-  final Stopwatch _sw = new Stopwatch();
+  static const kDisabledState = 'kDisabled';
+  static const kExceptionState = 'Exception';
+  static const kFetchingState = 'kFetching';
+  static const kLoadedState = 'kLoaded';
+  static const kLoadingState = 'kLoading';
+
+  Isolate isolate;
 
   final CpuProfile profile = new CpuProfile();
+  final Stopwatch _stopWatch = new Stopwatch();
+}
 
-  CpuProfileElement.created() : super.created();
-
-  @override
-  void attached() {
-    super.attached();
-  }
-
-  void isolateChanged(oldValue) {
-    _getCpuProfile().catchError(app.handleException);
-  }
-
-  void tagSelectorChanged(oldValue) {
-    _getCpuProfile().catchError(app.handleException);
-  }
+@CustomTag('stack-trace-tree-config')
+class StackTraceTreeConfigElement extends ObservatoryElement {
+  StackTraceTreeConfigElement.created() : super.created();
 
   void modeSelectorChanged(oldValue) {
-    _updateView();
+    if (onTreeConfigChange == null) {
+      return;
+    }
+    onTreeConfigChange(modeSelector, directionSelector);
   }
 
   void directionSelectorChanged(oldValue) {
-    _updateView();
-  }
-
-  Future clearCpuProfile() {
-    profile.clear();
-    if (isolate == null) {
-      return new Future.value(null);
+    if (onTreeConfigChange == null) {
+      return;
     }
-    return isolate.invokeRpc('_clearCpuProfile', { })
-        .then((ServiceMap response) {
-          _updateView();
-        });
+    onTreeConfigChange(modeSelector, directionSelector);
   }
 
-  Future refresh() {
-    return _getCpuProfile();
+  Function onTreeConfigChange;
+  @observable bool showModeSelector = true;
+  @observable bool showDirectionSelector = true;
+  @observable String modeSelector = 'Function';
+  @observable String directionSelector = 'Up';
+}
+
+/// Displays a CpuProfile
+@CustomTag('cpu-profile')
+class CpuProfileElement extends ObservatoryElement {
+  CpuProfileElement.created() : super.created() {
+    _updateTask = new Task(update);
+    _renderTask = new Task(render);
   }
 
-  _onFetchStarted() {
-    _sw.reset();
-    _sw.start();
-    state = 'Requested';
+  attached() {
+    super.attached();
+    sampleBufferControlElement =
+        shadowRoot.querySelector('#sampleBufferControl');
+    assert(sampleBufferControlElement != null);
+    sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
+    stackTraceTreeConfigElement =
+        shadowRoot.querySelector('#stackTraceTreeConfig');
+    assert(stackTraceTreeConfigElement != null);
+    stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
+    cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree');
+    assert(cpuProfileTreeElement != null);
+    cpuProfileTreeElement.profile = sampleBufferControlElement.profile;
+    _updateTask.queue();
   }
 
-  _onFetchFinished() {
-    _sw.stop();
-    fetchTime = formatTimeMilliseconds(_sw.elapsedMilliseconds);
+  isolateChanged(oldValue) {
+    _updateTask.queue();
   }
 
-  Future _onLoadStarted() {
-    _sw.reset();
-    _sw.start();
-    state = 'Loading';
-    return window.animationFrame;
-  }
-
-  _onLoadFinished() {
-    _sw.stop();
-    loadTime = formatTimeMilliseconds(_sw.elapsedMilliseconds);
-    state = 'Loaded';
-  }
-
-  Future _getCpuProfile() async {
-    profile.clear();
-    if (isolate == null) {
-      return new Future.value(null);
-    }
-    _onFetchStarted();
-    try {
-      var params = { 'tags': tagSelector };
-      var response = await isolate.invokeRpc('_getCpuProfile', params);
-      _onFetchFinished();
-      await _onLoadStarted();
-      profile.load(isolate, response);
-      _onLoadFinished();
-      _updateView();
-    } catch (e, st) {
-      bool handled = false;
-      if (e is ServerRpcException) {
-        ServerRpcException se = e;
-        if (se.code == ServerRpcException.kFeatureDisabled) {
-          state = 'Disabled';
-          handled = true;
-        }
-      }
-      if (!handled) {
-        state = 'Exception';
-        exception = e;
-        stackTrace = st;
-        rethrow;
-      }
+  update() {
+    if (sampleBufferControlElement != null) {
+      sampleBufferControlElement.reload(isolate);
     }
   }
 
-  void _updateView() {
-    sampleCount = profile.sampleCount.toString();
-    refreshTime = new DateTime.now().toString();
-    stackDepth = profile.stackDepth.toString();
-    sampleRate = profile.sampleRate.toStringAsFixed(0);
-    timeSpan = formatTime(profile.timeSpan);
-    CpuProfileTreeElement cpuProfileTreeElement =
-        shadowRoot.querySelector('#cpuProfileTree');
+  onSampleBufferChange(CpuProfile sampleBuffer) {
+    _renderTask.queue();
+  }
+
+  onTreeConfigChange(String modeSelector, String directionSelector) {
     ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
     if (directionSelector != 'Up') {
       direction = ProfileTreeDirection.Inclusive;
@@ -567,11 +600,33 @@
     if (modeSelector == 'Code') {
       mode = ProfileTreeMode.Code;
     }
-    cpuProfileTreeElement.profile = profile;
     cpuProfileTreeElement.direction = direction;
     cpuProfileTreeElement.mode = mode;
+    _renderTask.queue();
+  }
+
+  Future clearCpuProfile() async {
+    await isolate.invokeRpc('_clearCpuProfile', { });
+    _updateTask.queue();
+    return new Future.value(null);
+  }
+
+  Future refresh() {
+    _updateTask.queue();
+    return new Future.value(null);
+  }
+
+  render() {
     cpuProfileTreeElement.render();
   }
+
+  @published Isolate isolate;
+
+  Task _updateTask;
+  Task _renderTask;
+  SampleBufferControlElement sampleBufferControlElement;
+  StackTraceTreeConfigElement stackTraceTreeConfigElement;
+  CpuProfileTreeElement cpuProfileTreeElement;
 }
 
 class NameSortedTable extends SortedTable {
@@ -684,28 +739,9 @@
 
 @CustomTag('cpu-profile-table')
 class CpuProfileTableElement extends ObservatoryElement {
-  final Stopwatch _sw = new Stopwatch();
-  final CpuProfile profile = new CpuProfile();
-  StreamSubscription _resizeSubscription;
-  @observable NameSortedTable profileTable;
-  @observable NameSortedTable profileCallersTable;
-  @observable NameSortedTable profileCalleesTable;
-  @observable ServiceFunction focusedFunction;
-  @observable int focusedRow;
-  @observable String fetchTime = '';
-  @observable String loadTime = '';
-  @observable String state = 'Requested';
-  @observable var exception;
-  @observable var stackTrace;
-  @observable Isolate isolate;
-  @observable String sampleCount = '';
-  @observable String refreshTime = '';
-  @observable String sampleRate = '';
-  @observable String stackDepth = '';
-  @observable String timeSpan = '';
-  @observable String directionSelector = 'Up';
-
   CpuProfileTableElement.created() : super.created() {
+    _updateTask = new Task(update);
+    _renderTask = new Task(render);
     var columns = [
         new SortedTableColumn.withFormatter('Executing (%)',
                                             Utils.formatPercentNormalized),
@@ -735,6 +771,25 @@
 
   attached() {
     super.attached();
+    sampleBufferControlElement =
+        shadowRoot.querySelector('#sampleBufferControl');
+    assert(sampleBufferControlElement != null);
+    sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
+    // Disable the tag selector- we always want no tags.
+    sampleBufferControlElement.tagSelector = 'None';
+    sampleBufferControlElement.showTagSelector = false;
+    stackTraceTreeConfigElement =
+        shadowRoot.querySelector('#stackTraceTreeConfig');
+    assert(stackTraceTreeConfigElement != null);
+    stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
+    stackTraceTreeConfigElement.modeSelector = 'Function';
+    stackTraceTreeConfigElement.showModeSelector = false;
+    stackTraceTreeConfigElement.directionSelector = 'Down';
+    stackTraceTreeConfigElement.showDirectionSelector = false;
+    cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree');
+    assert(cpuProfileTreeElement != null);
+    cpuProfileTreeElement.profile = sampleBufferControlElement.profile;
+    _updateTask.queue();
     _resizeSubscription = window.onResize.listen((_) => _updateSize());
     _updateSize();
   }
@@ -755,10 +810,48 @@
     e.style.setProperty('height', '${mainHeight}px');
   }
 
-  isolateChanged() {
-    _getCpuProfile()
-      .catchError(app.handleException)
-      .whenComplete(checkParameters);
+  isolateChanged(oldValue) {
+    _updateTask.queue();
+  }
+
+  update() {
+    _clearView();
+    if (sampleBufferControlElement != null) {
+      sampleBufferControlElement.reload(isolate).whenComplete(checkParameters);
+    }
+  }
+
+  onSampleBufferChange(CpuProfile sampleBuffer) {
+    _renderTask.queue();
+  }
+
+  onTreeConfigChange(String modeSelector, String directionSelector) {
+    ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
+    if (directionSelector != 'Up') {
+      direction = ProfileTreeDirection.Inclusive;
+    }
+    ProfileTreeMode mode = ProfileTreeMode.Function;
+    if (modeSelector == 'Code') {
+      mode = ProfileTreeMode.Code;
+    }
+    cpuProfileTreeElement.direction = direction;
+    cpuProfileTreeElement.mode = mode;
+    _renderTask.queue();
+  }
+
+  Future clearCpuProfile() async {
+    await isolate.invokeRpc('_clearCpuProfile', { });
+    _updateTask.queue();
+    return new Future.value(null);
+  }
+
+  Future refresh() {
+    _updateTask.queue();
+    return new Future.value(null);
+  }
+
+  render() {
+    _updateView();
   }
 
   checkParameters() {
@@ -773,94 +866,12 @@
     isolate.getObject(functionId).then((func) => _focusOnFunction(func));
   }
 
-  void directionSelectorChanged(oldValue) {
-    _updateFunctionTreeView();
-  }
-
-  Future refresh() {
-    return _getCpuProfile();
-  }
-
-  _onFetchStarted() {
-    _sw.reset();
-    _sw.start();
-    state = 'Requested';
-  }
-
-  _onFetchFinished() {
-    _sw.stop();
-    fetchTime = formatTimeMilliseconds(_sw.elapsedMilliseconds);
-  }
-
-  _onLoadStarted() {
-    _sw.reset();
-    _sw.start();
-    state = 'Loading';
-  }
-
-  _onLoadFinished() {
-    _sw.stop();
-    loadTime = formatTimeMilliseconds(_sw.elapsedMilliseconds);
-    state = 'Loaded';
-  }
-
-  Future clearCpuProfile() {
-    profile.clear();
-    _clearView();
-    if (isolate == null) {
-      return new Future.value(null);
-    }
-    return isolate.invokeRpc('_clearCpuProfile', { })
-    .then((ServiceMap response) {
-      _updateView();
-    });
-  }
-
-  Future _getCpuProfile() async {
-    profile.clear();
-    _clearView();
-    if (isolate == null) {
-      return new Future.value(null);
-    }
-    _onFetchStarted();
-    try {
-      var params = { 'tags': 'None' };
-      var response = await isolate.invokeRpc('_getCpuProfile', params);
-      _onFetchFinished();
-      _onLoadStarted();
-      profile.load(isolate, response);
-      profile.buildFunctionCallerAndCallees();
-      _onLoadFinished();
-      _updateView();
-    } catch (e, st) {
-      bool handled = false;
-      if (e is ServerRpcException) {
-        ServerRpcException se = e;
-        if (se.code == ServerRpcException.kFeatureDisabled) {
-          state = 'Disabled';
-          handled = true;
-        }
-      }
-      if (!handled) {
-        state = 'Exception';
-        exception = e;
-        stackTrace = st;
-        rethrow;
-      }
-    }
-  }
-
   _clearView() {
     profileTable.clearRows();
     _renderTable();
   }
 
   _updateView() {
-    sampleCount = profile.sampleCount.toString();
-    refreshTime = new DateTime.now().toString();
-    stackDepth = profile.stackDepth.toString();
-    sampleRate = profile.sampleRate.toStringAsFixed(0);
-    timeSpan = formatTime(profile.timeSpan);
     _buildFunctionTable();
     _renderTable();
     _updateFunctionTreeView();
@@ -1060,21 +1071,28 @@
   ///
   TableTree functionTree;
   _updateFunctionTreeView() {
-    CpuProfileTreeElement cpuProfileTreeElement =
-        shadowRoot.querySelector('#cpuProfileTree');
-    ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
-    if (directionSelector != 'Up') {
-      direction = ProfileTreeDirection.Inclusive;
-    }
-    ProfileTreeMode mode = ProfileTreeMode.Function;
-    cpuProfileTreeElement.profile = profile;
-    cpuProfileTreeElement.direction = direction;
-    cpuProfileTreeElement.mode = mode;
     cpuProfileTreeElement.functionFilter = (FunctionCallTreeNode node) {
       return node.profileFunction.function == focusedFunction;
     };
     cpuProfileTreeElement.render();
   }
+
+  @published Isolate isolate;
+  @observable NameSortedTable profileTable;
+  @observable NameSortedTable profileCallersTable;
+  @observable NameSortedTable profileCalleesTable;
+  @observable ServiceFunction focusedFunction;
+  @observable int focusedRow;
+
+
+  StreamSubscription _resizeSubscription;
+  Task _updateTask;
+  Task _renderTask;
+
+  CpuProfile get profile => sampleBufferControlElement.profile;
+  SampleBufferControlElement sampleBufferControlElement;
+  StackTraceTreeConfigElement stackTraceTreeConfigElement;
+  CpuProfileTreeElement cpuProfileTreeElement;
 }
 
 enum ProfileTreeDirection {
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.html b/runtime/observatory/lib/src/elements/cpu_profile.html
index 891783f..588f869 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.html
+++ b/runtime/observatory/lib/src/elements/cpu_profile.html
@@ -6,6 +6,161 @@
 <link rel="import" href="sliding_checkbox.html">
 <link rel="import" href="view_footer.html">
 
+<polymer-element name="sample-buffer-control" extends="observatory-element">
+  <template>
+    <link rel="stylesheet" href="css/shared.css">
+    <style>
+    .statusMessage {
+      font-size: 150%;
+      font-weight: bold;
+    }
+
+    .statusBox {
+      height: 100%;
+      padding: 1em;
+    }
+
+    .center {
+      align-items: center;
+      justify-content: center;
+    }
+
+    .notice {
+      background-color: #fcf8e3;
+    }
+
+    .red {
+      background-color: #f2dede;
+    }
+    </style>
+    <div class="content-centered-big">
+      <h2>Sample buffer</h2>
+      <hr>
+      <template if="{{ state == 'kFetching' }}">
+        <div class="statusBox shadow center">
+          <div class="statusMessage">Fetching profile from VM...</div>
+        </div>
+      </template>
+      <template if="{{ state == 'kLoading' }}">
+        <div class="statusBox shadow center">
+          <div class="statusMessage">Loading profile...</div>
+        </div>
+      </template>
+      <template if="{{ state == 'kDisabled' }}">
+        <div class="statusBox shadow center">
+          <div>
+            <h1>Profiling is disabled</h1>
+            <br>
+            Perhaps the <b>profile</b> flag has been disabled for this VM.
+            <br><br>
+            See all
+            <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
+          </div>
+        </div>
+      </template>
+      <template if="{{ state == 'kException' }}">
+        <div class="statusBox shadow center">
+          <div class="statusMessage">
+            <h1>Profiling is disabled due to unexpected exception:</h1>
+            <br>
+            <pre>{{ exception.toString() }}</pre>
+            <br>
+            <h1>Stack trace:</h1>
+            <br>
+            <pre>{{ stackTrace.toString() }}</pre>
+          </div>
+        </div>
+      </template>
+      <template if="{{ state == 'kLoaded' }}">
+        <div class="memberList">
+          <div class="memberItem">
+            <div class="memberName">Refreshed at </div>
+            <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime  }}) (loaded in {{ loadTime }})</div>
+          </div>
+          <div class="memberItem">
+            <div class="memberName">Profile contains</div>
+            <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
+          </div>
+          <div class="memberItem">
+            <div class="memberName">Sampling</div>
+            <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
+          </div>
+          <template if="{{ showTagSelector }}">
+            <div class="memberItem">
+              <div class="memberName">Tag Order</div>
+              <div class="memberValue">
+                <select value="{{tagSelector}}">
+                  <option value="UserVM">User &gt; VM</option>
+                  <option value="UserOnly">User</option>
+                  <option value="VMUser">VM &gt; User</option>
+                  <option value="VMOnly">VM</option>
+                  <option value="None">None</option>
+                </select>
+              </div>
+            </div>
+          </template>
+        </div>
+      </template>
+    </div>
+  </template>
+</polymer-element>
+
+<polymer-element name="stack-trace-tree-config" extends="observatory-element">
+  <template>
+    <link rel="stylesheet" href="css/shared.css">
+    <style>
+    .statusBox {
+      height: 100%;
+      padding: 1em;
+    }
+    </style>
+    <div class="content-centered-big">
+      <h2>Tree display</h2>
+      <hr>
+      <div class="memberList">
+        <template if="{{ showModeSelector }}">
+          <div class="memberItem">
+            <div class="memberName">Mode</div>
+            <div class="memberValue">
+              <select value="{{modeSelector}}">
+                <option value="Code">Code</option>
+                <option value="Function">Function</option>
+              </select>
+            </div>
+          </div>
+        </template>
+        <template if="{{ showDirectionSelector }}">
+          <div class="memberItem">
+            <div class="memberName">Call Tree Direction</div>
+            <div class="memberValue">
+              <select value="{{directionSelector}}">
+                <option value="Down">Top down</option>
+                <option value="Up">Bottom up</option>
+              </select>
+            </div>
+          </div>
+        </template>
+      </div>
+      <template if="{{ directionSelector == 'Down' }}">
+        <br>
+        <div class="statusBox shadow">
+          <div>Tree is rooted at main.</div>
+          <br>
+          <div>Child nodes are callees.</div>
+        </div>
+      </template>
+      <template if="{{ directionSelector == 'Up' }}">
+        <br>
+        <div class="statusBox shadow">
+          <div>Tree is rooted at executing function / code.</div>
+          <br>
+          <div>Child nodes are callers.</div>
+        </div>
+      </template>
+    </div>
+  </template>
+</polymer-element>
+
 <polymer-element name="cpu-profile-tree" extends="observatory-element">
   <template>
     <link rel="stylesheet" href="css/shared.css">
@@ -211,68 +366,8 @@
       }
 
     </style>
-    <div class="content-centered-big">
-      <template if="{{ state == 'Requested' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">Fetching profile from VM...</div>
-        </div>
-      </template>
-      <template if="{{ state == 'Loading' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">Loading profile...</div>
-        </div>
-      </template>
-      <template if="{{ state == 'Disabled' }}">
-        <div class="statusBox shadow center">
-          <div>
-            <h1>Profiling is disabled</h1>
-            <br>
-            Perhaps the <b>profile</b> flag has been disabled for this VM.
-            <br><br>
-            See all
-            <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
-          </div>
-        </div>
-      </template>
-      <template if="{{ state == 'Exception' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">
-            <h1>Profiling is disabled due to unexpected exception:</h1>
-            <br>
-            <pre>{{ exception.toString() }}</pre>
-            <br>
-            <h1>Stack trace:</h1>
-            <br>
-            <pre>{{ stackTrace.toString() }}</pre>
-          </div>
-        </div>
-      </template>
-      <template if="{{ state == 'Loaded' }}">
-        <div class="memberList">
-          <div class="memberItem">
-            <div class="memberName">Refreshed at </div>
-            <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime  }}) (loaded in {{ loadTime }})</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Profile contains</div>
-            <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Sampling</div>
-            <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Call Tree Direction</div>
-            <div class="memberValue">
-              <select value="{{directionSelector}}">
-                <option value="Down">Top down</option>
-                <option value="Up">Bottom up</option>
-              </select>
-            </div>
-          </div>
-        </div>
-      </template>
-    </div>
+    <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
+    <br>
     <hr>
     <div id="main" class="flex-row centered">
       <div class="flex-item-45-percent full-height outlined scroll">
@@ -329,16 +424,21 @@
       </div>
     </div>
     <br>
+    <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
     <br>
-    <div class="focused-function-label">
-      <template if="{{ focusedFunction != null }}">
-        <span>Filtered tree: </span>
-        <function-ref ref="{{ focusedFunction }}"></function-ref>
-      </template>
-      <template if="{{ focusedFunction == null }}">
-        <span>No focused function</span>
-      </template>
+    <div class="content-centered-big">
+      <div class="focused-function-label">
+        <template if="{{ focusedFunction != null }}">
+          <span>Filtered tree: </span>
+          <function-ref ref="{{ focusedFunction }}"></function-ref>
+        </template>
+        <template if="{{ focusedFunction == null }}">
+          <span>No focused function</span>
+        </template>
+      </div>
     </div>
+    <br>
+    <br>
     <div class="flex-row centered">
       <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
         <cpu-profile-tree id="cpuProfileTree"></cpu-profile-tree>
@@ -363,137 +463,12 @@
         background-color: #ECECEC;
         padding: 0.2em;
       }
-      .statusMessage {
-        font-size: 150%;
-        font-weight: bold;
-      }
-
-      .statusBox {
-        height: 100%;
-        padding: 1em;
-      }
-
-      .center {
-        align-items: center;
-        justify-content: center;
-      }
-
-      .notice {
-        background-color: #fcf8e3;
-      }
-
-      .red {
-        background-color: #f2dede;
-      }
-
     </style>
+    <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
+    <br>
+    <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
+    <br>
     <div class="content-centered-big">
-      <h1>Sampled CPU profile</h1>
-      <hr>
-      <template if="{{ state == 'Requested' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">Fetching profile from VM...</div>
-        </div>
-      </template>
-      <template if="{{ state == 'Loading' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">Loading profile...</div>
-        </div>
-      </template>
-      <template if="{{ state == 'Disabled' }}">
-        <div class="statusBox shadow center">
-          <div>
-            <h1>Profiling is disabled</h1>
-            <br>
-            Perhaps the <b>profile</b> flag has been disabled for this VM.
-            <br><br>
-            See all
-            <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
-          </div>
-        </div>
-      </template>
-      <template if="{{ state == 'Exception' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">
-            <h1>Profiling is disabled due to unexpected exception:</h1>
-            <br>
-            <pre>{{ exception.toString() }}</pre>
-            <br>
-            <h1>Stack trace:</h1>
-            <br>
-            <pre>{{ stackTrace.toString() }}</pre>
-          </div>
-        </div>
-      </template>
-      <template if="{{ state == 'Loaded' }}">
-        <div class="memberList">
-          <div class="memberItem">
-            <div class="memberName">Refreshed at </div>
-            <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime  }}) (loaded in {{ loadTime }})</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Profile contains</div>
-            <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Sampling</div>
-            <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Mode</div>
-            <div class="memberValue">
-              <select value="{{modeSelector}}">
-                <option value="Code">Code</option>
-                <option value="Function">Function</option>
-              </select>
-            </div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Tag Order</div>
-            <div class="memberValue">
-              <select value="{{tagSelector}}">
-                <option value="UserVM">User &gt; VM</option>
-                <option value="UserOnly">User</option>
-                <option value="VMUser">VM &gt; User</option>
-                <option value="VMOnly">VM</option>
-                <option value="None">None</option>
-              </select>
-            </div>
-          </div>
-          <!--- Experimental
-          <div class="memberItem">
-            <div class="memberName">Call Tree Direction</div>
-            <div class="memberValue">
-              <select value="{{directionSelector}}">
-                <option value="Down">Top down</option>
-                <option value="Up">Bottom up</option>
-              </select>
-            </div>
-          </div>
-           --->
-        </div>
-      </template>
-      <template if="{{ state == 'Loaded' && directionSelector == 'Down' }}">
-        <br>
-        <div class="statusBox shadow">
-          <div>Tree is rooted at main.</div>
-          <br>
-          <div>Child nodes are callees.</div>
-          <br>
-          <div class="notice">To get the most out of this mode you may need to launch Dart with a higher --profile-depth flag value.</div>
-          <div class="notice">Try 16, 32, ... up to 256 until [Truncated] approaches zero.</div>
-          <div class="red">NOTE: Higher values will impact performance</div>
-        </div>
-      </template>
-      <template if="{{ state == 'Loaded' && directionSelector == 'Up' }}">
-        <br>
-        <div class="statusBox shadow">
-          <div>Tree is rooted at executing function / code.</div>
-          <br>
-          <div>Child nodes are callers.</div>
-        </div>
-      </template>
-      <br><br>
       <div class="tableWell shadow">
         <cpu-profile-tree id="cpuProfileTree"></cpu-profile-tree>
       </div>
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index e7dab1c..3442d98 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -111,6 +111,16 @@
   border-bottom-left-radius:4px;
 }
 
+.full {
+  height: 100%;
+  width: 100;
+}
+
+.flex-row {
+  display: flex;
+  flex-direction: row;
+}
+
 /* Flex row container */
 .flex-row {
   display: flex;
diff --git a/runtime/observatory/lib/src/elements/curly_block.dart b/runtime/observatory/lib/src/elements/curly_block.dart
index 2632f3e..004a02e 100644
--- a/runtime/observatory/lib/src/elements/curly_block.dart
+++ b/runtime/observatory/lib/src/elements/curly_block.dart
@@ -5,36 +5,51 @@
 library curly_block_element;
 
 import 'package:polymer/polymer.dart';
+import 'observatory_element.dart';
 
 @CustomTag('curly-block')
-class CurlyBlockElement extends PolymerElement {
+class CurlyBlockElement extends ObservatoryElement {
   CurlyBlockElement.created() : super.created();
 
   @observable bool expanded = false;
   @observable bool busy = false;
   @published var callback = null;
   @published bool expand = false;
+  @published String expandKey;
 
   void expandChanged(oldValue) {
     expanded = expand;
   }
 
+  void expandKeyChanged(oldValue) {
+    if (expandKey != null) {
+      var value = app.expansions[expandKey];
+      if (value != null) {
+        if (expanded != value) {
+          toggleExpand(null, null, null);
+        }
+      }
+    }
+  }
+
   void doneCallback() {
     expanded = !expanded;
+    if (expandKey != null) {
+      app.expansions[expandKey] = expanded;
+    }
     busy = false;
   }
 
   void toggleExpand(var event, var b, var c) {
     assert(callback == null || expand == false);
-    event.stopPropagation();
     if (busy) {
       return;
     }
+    busy = true;
     if (callback != null) {
-      busy = true;
       callback(!expanded, doneCallback);
     } else {
-      expanded = !expanded;
+      doneCallback();
     }
   }
 }
diff --git a/runtime/observatory/lib/src/elements/curly_block.html b/runtime/observatory/lib/src/elements/curly_block.html
index 1576020..d1702a2 100644
--- a/runtime/observatory/lib/src/elements/curly_block.html
+++ b/runtime/observatory/lib/src/elements/curly_block.html
@@ -1,6 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
+<link rel="import" href="observatory_element.html">
 
-<polymer-element name="curly-block">
+<polymer-element name="curly-block" extends="observatory-element">
   <template>
     <style>
       .idle {
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 70a3208..ae0ab6f 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -10,6 +10,7 @@
 import 'package:observatory/cli.dart';
 import 'package:observatory/debugger.dart';
 import 'package:observatory/service.dart';
+import 'package:logging/logging.dart';
 import 'package:polymer/polymer.dart';
 
 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library.
@@ -349,6 +350,75 @@
       'Syntax: step\n';
 }
 
+class LogCommand extends DebuggerCommand {
+  LogCommand(Debugger debugger) : super(debugger, 'log', []);
+
+  Future run(List<String> args) async {
+    if (args.length == 0) {
+      debugger.console.print(
+          'Current log level: '
+          '${debugger._consolePrinter._minimumLogLevel.name}');
+      return new Future.value(null);
+    }
+    if (args.length > 1) {
+      debugger.console.print("log expects zero or one arguments");
+      return new Future.value(null);
+    }
+    var level = _findLevel(args[0]);
+    if (level == null) {
+      debugger.console.print('No such log level: ${args[0]}');
+      return new Future.value(null);
+    }
+    debugger._consolePrinter._minimumLogLevel = level;
+    debugger.console.print('Set log level to: ${level.name}');
+    return new Future.value(null);
+  }
+
+  Level _findLevel(String levelName) {
+    levelName = levelName.toUpperCase();
+    for (var level in Level.LEVELS) {
+      if (level.name == levelName) {
+        return level;
+      }
+    }
+    return null;
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length != 1) {
+      return new Future.value([args.join('')]);
+    }
+    var prefix = args[0].toUpperCase();
+    var result = <String>[];
+    for (var level in Level.LEVELS) {
+      if (level.name.startsWith(prefix)) {
+        result.add(level.name);
+      }
+    }
+    return new Future.value(result);
+  }
+
+  String helpShort =
+      'Control which log messages are displayed';
+
+  String helpLong =
+      'Get or set the minimum log level that should be displayed.\n'
+      '\n'
+      'Log levels (in ascending order): ALL, FINEST, FINER, FINE, CONFIG, '
+      'INFO, WARNING, SEVERE, SHOUT, OFF\n'
+      '\n'
+      'Default: OFF\n'
+      '\n'
+      'Syntax: log          '
+      '# Display the current minimum log level.\n'
+      '        log <level>  '
+      '# Set the minimum log level to <level>.\n'
+      '        log OFF      '
+      '# Display no log messages.\n'
+      '        log ALL      '
+      '# Display all log messages.\n';
+}
+
 class AsyncNextCommand extends DebuggerCommand {
   AsyncNextCommand(Debugger debugger) : super(debugger, 'anext', []) {
   }
@@ -358,11 +428,9 @@
       var event = debugger.isolate.pauseEvent;
       if (event.asyncContinuation == null) {
         debugger.console.print("No async continuation at this location");
-        return;
+      } else {
+        return debugger.isolate.asyncStepOver()[Isolate.kFirstResume];
       }
-      var bpt = await
-          debugger.isolate.addBreakOnActivation(event.asyncContinuation);
-      return debugger.isolate.resume();
     } else {
       debugger.console.print('The program is already running');
     }
@@ -486,25 +554,25 @@
       'Add a breakpoint by source location or function name.\n'
       '\n'
       'Syntax: break                       '
-      '- Break at the current position\n'
+      '# Break at the current position\n'
       '        break <line>                '
-      '- Break at a line in the current script\n'
+      '# Break at a line in the current script\n'
       '                                    '
       '  (e.g \'break 11\')\n'
       '        break <line>:<col>          '
-      '- Break at a line:col in the current script\n'
+      '# Break at a line:col in the current script\n'
       '                                    '
       '  (e.g \'break 11:8\')\n'
       '        break <script>:<line>       '
-      '- Break at a line:col in a specific script\n'
+      '# Break at a line:col in a specific script\n'
       '                                    '
       '  (e.g \'break test.dart:11\')\n'
       '        break <script>:<line>:<col> '
-      '- Break at a line:col in a specific script\n'
+      '# Break at a line:col in a specific script\n'
       '                                    '
       '  (e.g \'break test.dart:11:8\')\n'
       '        break <function>            '
-      '- Break at the named function\n'
+      '# Break at the named function\n'
       '                                    '
       '  (e.g \'break main\' or \'break Class.someFunction\')\n';
 }
@@ -569,25 +637,25 @@
       'Remove a breakpoint by source location or function name.\n'
       '\n'
       'Syntax: clear                       '
-      '- Clear at the current position\n'
+      '# Clear at the current position\n'
       '        clear <line>                '
-      '- Clear at a line in the current script\n'
+      '# Clear at a line in the current script\n'
       '                                    '
       '  (e.g \'clear 11\')\n'
       '        clear <line>:<col>          '
-      '- Clear at a line:col in the current script\n'
+      '# Clear at a line:col in the current script\n'
       '                                    '
       '  (e.g \'clear 11:8\')\n'
       '        clear <script>:<line>       '
-      '- Clear at a line:col in a specific script\n'
+      '# Clear at a line:col in a specific script\n'
       '                                    '
       '  (e.g \'clear test.dart:11\')\n'
       '        clear <script>:<line>:<col> '
-      '- Clear at a line:col in a specific script\n'
+      '# Clear at a line:col in a specific script\n'
       '                                    '
       '  (e.g \'clear test.dart:11:8\')\n'
       '        clear <function>            '
-      '- Clear at the named function\n'
+      '# Clear at the named function\n'
       '                                    '
       '  (e.g \'clear main\' or \'clear Class.someFunction\')\n';
 }
@@ -883,17 +951,23 @@
       'Syntax: refresh <subcommand>\n';
 }
 
-class _VMStreamPrinter {
+class _ConsoleStreamPrinter {
   ObservatoryDebugger _debugger;
 
-  _VMStreamPrinter(this._debugger);
-
+  _ConsoleStreamPrinter(this._debugger);
+  Level _minimumLogLevel = Level.OFF;
   String _savedStream;
   String _savedIsolate;
   String _savedLine;
   List<String> _buffer = [];
 
   void onEvent(String streamName, ServiceEvent event) {
+    if (event.kind == ServiceEvent.kLogging) {
+      // Check if we should print this log message.
+      if (event.logRecord['level'].value < _minimumLogLevel.value) {
+        return;
+      }
+    }
     String isolateName = event.isolate.name;
     // If we get a line from a different isolate/stream, flush
     // any pending output, even if it is not newline-terminated.
@@ -901,8 +975,15 @@
         (_savedStream != null && streamName != _savedStream)) {
        flush();
     }
-    String data = event.bytesAsString;
-    bool hasNewline = data.endsWith('\n');
+    String data;
+    bool hasNewline;
+    if (event.kind == ServiceEvent.kLogging) {
+      data = event.logRecord["message"].valueAsString;
+      hasNewline = true;
+    } else {
+      data = event.bytesAsString;
+      hasNewline = data.endsWith('\n');
+    }
     if (_savedLine != null) {
        data = _savedLine + data;
       _savedIsolate = null;
@@ -988,8 +1069,9 @@
         new InfoCommand(this),
         new IsolateCommand(this),
         new RefreshCommand(this),
+        new LogCommand(this),
     ]);
-    _stdioPrinter = new _VMStreamPrinter(this);
+    _consolePrinter = new _ConsoleStreamPrinter(this);
   }
 
   VM get vm => page.app.vm;
@@ -997,7 +1079,8 @@
   void updateIsolate(Isolate iso) {
     _isolate = iso;
     if (_isolate != null) {
-      if (exceptions != iso.exceptionsPauseInfo) {
+      if ((exceptions != iso.exceptionsPauseInfo) &&
+          (iso.exceptionsPauseInfo != null)) {
         exceptions = iso.exceptionsPauseInfo;
         console.print("Now pausing for $exceptions exceptions");
       }
@@ -1133,7 +1216,7 @@
           console.print('Paused at ${script.name}:${line}:${col}');
         }
         if (event.asyncContinuation != null) {
-          console.print("Paused in async function: 'astep' available");
+          console.print("Paused in async function: 'anext' available");
         }
       });
     }
@@ -1239,24 +1322,28 @@
       case ServiceEvent.kInspect:
         break;
 
+      case ServiceEvent.kLogging:
+        _consolePrinter.onEvent(event.logRecord['level'].name, event);
+        break;
+
       default:
         console.print('Unrecognized event: $event');
         break;
     }
   }
 
-  _VMStreamPrinter _stdioPrinter;
+  _ConsoleStreamPrinter _consolePrinter;
 
   void flushStdio() {
-    _stdioPrinter.flush();
+    _consolePrinter.flush();
   }
 
   void onStdout(ServiceEvent event) {
-    _stdioPrinter.onEvent('stdout', event);
+    _consolePrinter.onEvent('stdout', event);
   }
 
   void onStderr(ServiceEvent event) {
-    _stdioPrinter.onEvent('stderr', event);
+    _consolePrinter.onEvent('stderr', event);
   }
 
   static String _commonPrefix(String a, String b) {
@@ -1350,6 +1437,7 @@
   Future<StreamSubscription> _debugSubscriptionFuture;
   Future<StreamSubscription> _stdoutSubscriptionFuture;
   Future<StreamSubscription> _stderrSubscriptionFuture;
+  Future<StreamSubscription> _logSubscriptionFuture;
 
   @override
   void attached() {
@@ -1387,7 +1475,8 @@
         app.vm.listenEventStream(VM.kStdoutStream, debugger.onStdout);
     _stderrSubscriptionFuture =
         app.vm.listenEventStream(VM.kStderrStream, debugger.onStderr);
-
+    _logSubscriptionFuture =
+        app.vm.listenEventStream(Isolate.kLoggingStream, debugger.onEvent);
     // Turn on the periodic poll timer for this page.
     pollPeriod = const Duration(milliseconds:100);
 
@@ -1407,6 +1496,7 @@
 
   @override
   void detached() {
+    debugger.isolate = null;
     cancelFutureSubscription(_isolateSubscriptionFuture);
     _isolateSubscriptionFuture = null;
     cancelFutureSubscription(_debugSubscriptionFuture);
@@ -1415,6 +1505,8 @@
     _stdoutSubscriptionFuture = null;
     cancelFutureSubscription(_stderrSubscriptionFuture);
     _stderrSubscriptionFuture = null;
+    cancelFutureSubscription(_logSubscriptionFuture);
+    _logSubscriptionFuture = null;
     super.detached();
   }
 }
@@ -1625,6 +1717,11 @@
 
   DebuggerFrameElement.created() : super.created();
 
+
+  String makeExpandKey(String key) {
+    return '${frame.function.qualifiedName}/${key}';
+  }
+
   bool matchFrame(Frame newFrame) {
     return newFrame.function.id == frame.function.id;
   }
@@ -1761,6 +1858,38 @@
 
   DebuggerConsoleElement.created() : super.created();
 
+  /// Is [container] scrolled to the within [threshold] pixels of the bottom?
+  static bool _isScrolledToBottom(DivElement container, [int threshold = 2]) {
+    if (container == null) {
+      return false;
+    }
+    // scrollHeight -> complete height of element including scrollable area.
+    // clientHeight -> height of element on page.
+    // scrollTop -> how far is an element scrolled (from 0 to scrollHeight).
+    final distanceFromBottom =
+        container.scrollHeight - container.clientHeight - container.scrollTop;
+    const threshold = 2;  // 2 pixel slop.
+    return distanceFromBottom <= threshold;
+  }
+
+  /// Scroll [container] so the bottom content is visible.
+  static _scrollToBottom(DivElement container) {
+    if (container == null) {
+      return;
+    }
+    // Adjust scroll so that the bottom of the content is visible.
+    container.scrollTop = container.scrollHeight - container.clientHeight;
+  }
+
+  void _append(HtmlElement span) {
+    var consoleTextElement = $['consoleText'];
+    bool autoScroll = _isScrolledToBottom(parent);
+    consoleTextElement.children.add(span);
+    if (autoScroll) {
+      _scrollToBottom(parent);
+    }
+  }
+
   void print(String line, { bool newline:true }) {
     var span = new SpanElement();
     span.classes.add('normal');
@@ -1768,8 +1897,7 @@
     if (newline) {
       span.appendText('\n');
     }
-    $['consoleText'].children.add(span);
-    span.scrollIntoView();
+    _append(span);
   }
 
   void printBold(String line, { bool newline:true }) {
@@ -1779,8 +1907,7 @@
     if (newline) {
       span.appendText('\n');
     }
-    $['consoleText'].children.add(span);
-    span.scrollIntoView();
+    _append(span);
   }
 
   void printRed(String line, { bool newline:true }) {
@@ -1790,39 +1917,35 @@
     if (newline) {
       span.appendText('\n');
     }
-    $['consoleText'].children.add(span);
-    span.scrollIntoView();
+    _append(span);
   }
 
   void printStdio(List<String> lines) {
-    var lastSpan;
+    var consoleTextElement = $['consoleText'];
+    bool autoScroll = _isScrolledToBottom(parent);
     for (var line in lines) {
       var span = new SpanElement();
       span.classes.add('green');
       span.appendText(line);
       span.appendText('\n');
-      $['consoleText'].children.add(span);
-      lastSpan = span;
+      consoleTextElement.children.add(span);
     }
-    if (lastSpan != null) {
-      lastSpan.scrollIntoView();
+    if (autoScroll) {
+      _scrollToBottom(parent);
     }
   }
 
   void printRef(Instance ref, { bool newline:true }) {
     var refElement = new Element.tag('instance-ref');
     refElement.ref = ref;
-    $['consoleText'].children.add(refElement);
+    _append(refElement);
     if (newline) {
       this.newline();
     }
-    refElement.scrollIntoView();
   }
 
   void newline() {
-    var br = new BRElement();
-    $['consoleText'].children.add(br);
-    br.scrollIntoView();
+    _append(new BRElement());
   }
 }
 
@@ -1890,4 +2013,3 @@
 
   DebuggerInputElement.created() : super.created();
 }
-
diff --git a/runtime/observatory/lib/src/elements/debugger.html b/runtime/observatory/lib/src/elements/debugger.html
index b2e6bfe..e0f5dce 100644
--- a/runtime/observatory/lib/src/elements/debugger.html
+++ b/runtime/observatory/lib/src/elements/debugger.html
@@ -270,7 +270,8 @@
                   <div class="memberItem">
                     <div class="memberName">{{ v['name']}}</div>
                     <div class="memberValue">
-                      <any-service-ref ref="{{ v['value'] }}">
+                      <any-service-ref ref="{{ v['value'] }}"
+                                       expandKey="{{ makeExpandKey(v['name']) }}">
                       </any-service-ref>
                     </div>
                   </div>
diff --git a/runtime/observatory/lib/src/elements/inbound_reference.html b/runtime/observatory/lib/src/elements/inbound_reference.html
index a820224..d7b9e5d 100644
--- a/runtime/observatory/lib/src/elements/inbound_reference.html
+++ b/runtime/observatory/lib/src/elements/inbound_reference.html
@@ -8,9 +8,10 @@
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <div>
-      from <any-service-ref ref="{{ source }}"></any-service-ref>
-      <template if="{{ slotIsArrayIndex }}">via [{{ slot }}]</template>
-      <template if="{{ slotIsField }}">via <field-ref ref="{{ slot }}"></field-ref></template>
+      from
+      <template if="{{ slotIsArrayIndex }}">[{{ slot }}] of</template>
+      <template if="{{ slotIsField }}"><field-ref ref="{{ slot }}"></field-ref> of</template>
+      <any-service-ref ref="{{ source }}"></any-service-ref>
 
       <curly-block callback="{{ expander() }}">
         <div class="memberList">
diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart
index 19a87e1..86727ae 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory/lib/src/elements/instance_ref.dart
@@ -54,4 +54,8 @@
       onDone();
     }
   }
+
+  String makeExpandKey(String key) {
+    return '${expandKey}/${key}';
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/instance_ref.html b/runtime/observatory/lib/src/elements/instance_ref.html
index d8a1def..4781972 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.html
+++ b/runtime/observatory/lib/src/elements/instance_ref.html
@@ -38,17 +38,19 @@
 
       <template if="{{ ref.isClosure }}">
         <a on-click="{{ goto }}" _href="{{ url }}">
-          {{ ref.function.qualifiedName }}
+          <em>Closure</em> ({{ ref.function.qualifiedName }})
         </a>
       </template>
 
       <template if="{{ ref.isRegExp }}">
-        <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}({{ ref.pattern.valueAsString }})</em></a>
+        <a on-click="{{ goto }}" _href="{{ url }}">
+          <em>{{ ref.clazz.name }}</em> ({{ ref.pattern.valueAsString }})
+        </a>
       </template>
 
       <template if="{{ ref.isPlainInstance }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em></a>
-        <curly-block callback="{{ expander() }}">
+        <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
           <div class="memberList">
             <template repeat="{{ field in ref.fields }}">
               <div class="memberItem">
@@ -56,7 +58,9 @@
                   {{ field['decl'].name }}
                 </div>
                 <div class="memberValue">
-                  <any-service-ref ref="{{ field['value'] }}"></any-service-ref>
+                  <any-service-ref ref="{{ field['value'] }}"
+                                   expandKey="{{ makeExpandKey(field['decl'].name) }}">
+                  </any-service-ref>
                 </div>
               </div>
             </template>
@@ -66,13 +70,14 @@
 
       <template if="{{ ref.isList }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em> ({{ ref.length }})</a>
-        <curly-block callback="{{ expander() }}">
+        <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
           <div class="memberList">
             <template repeat="{{ index in ref.elements.asMap().keys }}">
               <div class="memberItem">
                 <div class="memberName">[{{ index }}]</div>
                 <div class="memberValue">
-                  <any-service-ref ref="{{ ref.elements[index] }}">
+                  <any-service-ref ref="{{ ref.elements[index] }}"
+                                   expandKey="{{ makeExpandKey(index.toString()) }}">
                   </any-service-ref>
                 </div>
               </div>
@@ -83,15 +88,19 @@
 
       <template if="{{ ref.isMap }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em> ({{ ref.length }})</a>
-        <curly-block callback="{{ expander() }}">
+        <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
           <div class="memberList">
             <template repeat="{{ association in ref.associations }}">
               <div class="memberItem">
                 <div class="memberName">
-                  [<any-service-ref ref="{{ association['key'] }}"></any-service-ref>]
+                  [<any-service-ref ref="{{ association['key'] }}"
+                                    expandKey="{{ makeExpandKey('key') }}">
+                  </any-service-ref>]
                 </div>
                 <div class="memberValue">
-                  <any-service-ref ref="{{ association['value'] }}"></any-service-ref>
+                  <any-service-ref ref="{{ association['value'] }}"
+                                   expandKey="{{ makeExpandKey('value') }}">
+                  </any-service-ref>
                 </div>
               </div>
             </template>
@@ -101,7 +110,7 @@
 
       <template if="{{ ref.isTypedData }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em> ({{ ref.length }})</a>
-        <curly-block callback="{{ expander() }}">
+        <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
           <div class="memberList">
             <template repeat="{{ index in ref.typedElements.asMap().keys }}">
               <div class="memberItem">
@@ -115,12 +124,14 @@
 
       <template if="{{ ref.isMirrorReference }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em></a>
-        <curly-block callback="{{ expander() }}">
+        <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
           <div class="memberList">
             <div class="memberItem">
               <div class="memberName">referent</div>
               <div class="memberValue">
-                <any-service-ref ref="{{ ref.referent }}"></any-service-ref>
+                <any-service-ref ref="{{ ref.referent }}"
+                                 expandKey="{{ makeExpandKey('referent') }}">
+                </any-service-ref>
               </div>
             </div>
           </div>
@@ -129,18 +140,22 @@
 
       <template if="{{ ref.isWeakProperty }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em></a>
-        <curly-block callback="{{ expander() }}">
+        <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
           <div class="memberList">
             <div class="memberItem">
               <div class="memberName">key</div>
               <div class="memberValue">
-                <any-service-ref ref="{{ ref.key }}"></any-service-ref>
+                <any-service-ref ref="{{ ref.key }}"
+                                 expandKey="{{ makeExpandKey('key') }}">
+                </any-service-ref>
               </div>
             </div>
             <div class="memberItem">
               <div class="memberName">value</div>
               <div class="memberValue">
-                <any-service-ref ref="{{ ref.value }}"></any-service-ref>
+                <any-service-ref ref="{{ ref.value }}"
+                                 expandKey="{{ makeExpandKey('value') }}">
+                </any-service-ref>
               </div>
             </div>
           </div>
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 823b581..31dc45c 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -191,6 +191,11 @@
             See <a on-click="{{ goto }}" _href="{{ gotoLink('/ports', isolate) }}">ports</a>
           </div>
         </div>
+        <div class="memberItem">
+          <div class="memberValue">
+            See <a on-click="{{ goto }}" _href="{{ gotoLink('/logging', isolate) }}">logging</a>
+          </div>
+        </div>
         <!-- Temporarily disabled until UI for dart:io is acceptable.
         <template if="{{ isolate.ioEnabled }}">
           <div class="memberItem">
diff --git a/runtime/observatory/lib/src/elements/logging.dart b/runtime/observatory/lib/src/elements/logging.dart
new file mode 100644
index 0000000..8f26305
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/logging.dart
@@ -0,0 +1,201 @@
+// 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 logging_page;
+
+import 'dart:async';
+import 'dart:html';
+import 'observatory_element.dart';
+import 'package:logging/logging.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/app.dart';
+import 'package:observatory/elements.dart';
+import 'package:observatory/utils.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('logging-page')
+class LoggingPageElement extends ObservatoryElement {
+  static const _kPageSelector = '#page';
+  static const _kLogSelector = '#log';
+  static const _kSeverityLevelSelector = '#severityLevelSelector';
+
+  LoggingPageElement.created() : super.created();
+
+  domReady() {
+    super.domReady();
+    _insertLevels();
+  }
+
+  attached() {
+    super.attached();
+    _sub();
+    _resizeSubscription = window.onResize.listen((_) => _updatePageHeight());
+    _updatePageHeight();
+    // Turn on the periodic poll timer for this page.
+    pollPeriod = const Duration(milliseconds:100);
+  }
+
+  detached() {
+    super.detached();
+    if (_resizeSubscription != null) {
+      _resizeSubscription.cancel();
+      _resizeSubscription = null;
+    }
+    _unsub();
+  }
+
+  void onPoll() {
+    _flushPendingLogs();
+  }
+
+  _updatePageHeight() {
+    HtmlElement e = shadowRoot.querySelector(_kPageSelector);
+    final totalHeight = window.innerHeight;
+    final top = e.offset.top;
+    final bottomMargin = 32;
+    final mainHeight = totalHeight - top - bottomMargin;
+    e.style.setProperty('height', '${mainHeight}px');
+  }
+
+  _insertLevels() {
+    SelectElement severityLevelSelector =
+        shadowRoot.querySelector(_kSeverityLevelSelector);
+    severityLevelSelector.children.clear();
+    _maxLevelLabelLength = 0;
+    for (var level in Level.LEVELS) {
+      var option = new OptionElement();
+      option.value = level.value.toString();
+      option.label = level.name;
+      if (level.name.length > _maxLevelLabelLength) {
+        _maxLevelLabelLength = level.name.length;
+      }
+      severityLevelSelector.children.add(option);
+    }
+    severityLevelSelector.selectedIndex = 0;
+    severityLevel = Level.ALL.value.toString();
+  }
+
+  _reset() {
+    logRecords.clear();
+    _unsub();
+    _sub();
+    _renderFull();
+  }
+
+  _unsub() {
+    cancelFutureSubscription(_loggingSubscriptionFuture);
+    _loggingSubscriptionFuture = null;
+  }
+
+  _sub() {
+    if (_loggingSubscriptionFuture != null) {
+      // Already subscribed.
+      return;
+    }
+    _loggingSubscriptionFuture =
+        app.vm.listenEventStream(Isolate.kLoggingStream, _onEvent);
+  }
+
+  _append(Map logRecord) {
+    logRecords.add(logRecord);
+    if (_shouldDisplay(logRecord)) {
+      // Queue for display.
+      pendingLogRecords.add(logRecord);
+    }
+  }
+
+  Element _renderAppend(Map logRecord) {
+    DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
+    var element = new DivElement();
+    element.classes.add('logItem');
+    element.classes.add(logRecord['level'].name);
+    element.appendText(
+        '${logRecord["level"].name.padLeft(_maxLevelLabelLength)} '
+        '${Utils.formatDateTime(logRecord["time"])} '
+        '${logRecord["message"].valueAsString}\n');
+    logContainer.children.add(element);
+    return element;
+  }
+
+  _renderFull() {
+    DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
+    logContainer.children.clear();
+    pendingLogRecords.clear();
+    for (var logRecord in logRecords) {
+      if (_shouldDisplay(logRecord)) {
+        _renderAppend(logRecord);
+      }
+    }
+    _scrollToBottom(logContainer);
+  }
+
+  /// Is [container] scrolled to the within [threshold] pixels of the bottom?
+  static bool _isScrolledToBottom(DivElement container, [int threshold = 2]) {
+    if (container == null) {
+      return false;
+    }
+    // scrollHeight -> complete height of element including scrollable area.
+    // clientHeight -> height of element on page.
+    // scrollTop -> how far is an element scrolled (from 0 to scrollHeight).
+    final distanceFromBottom =
+        container.scrollHeight - container.clientHeight - container.scrollTop;
+    const threshold = 2;  // 2 pixel slop.
+    return distanceFromBottom <= threshold;
+  }
+
+  /// Scroll [container] so the bottom content is visible.
+  static _scrollToBottom(DivElement container) {
+    if (container == null) {
+      return;
+    }
+    // Adjust scroll so that the bottom of the content is visible.
+    container.scrollTop = container.scrollHeight - container.clientHeight;
+  }
+
+  _flushPendingLogs() {
+    DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
+    bool autoScroll = _isScrolledToBottom(logContainer);
+    for (var logRecord in pendingLogRecords) {
+      _renderAppend(logRecord);
+    }
+    if (autoScroll) {
+      _scrollToBottom(logContainer);
+    }
+    pendingLogRecords.clear();
+  }
+
+  _onEvent(ServiceEvent event) {
+    assert(event.kind == Isolate.kLoggingStream);
+    _append(event.logRecord);
+  }
+
+  void isolateChanged(oldValue) {
+    _reset();
+  }
+
+  void severityLevelChanged(oldValue) {
+    _severityLevelValue = int.parse(severityLevel);
+    _renderFull();
+  }
+
+  Future clear() {
+    logRecords.clear();
+    pendingLogRecords.clear();
+    _renderFull();
+    return new Future.value(null);
+  }
+
+  bool _shouldDisplay(Map logRecord) {
+    return logRecord['level'].value >= _severityLevelValue;
+  }
+
+  @observable Isolate isolate;
+  @observable String severityLevel;
+  int _severityLevelValue = 0;
+  int _maxLevelLabelLength = 0;
+  Future<StreamSubscription> _loggingSubscriptionFuture;
+  StreamSubscription _resizeSubscription;
+  final List<Map> logRecords = new List<Map>();
+  final List<Map> pendingLogRecords = new List<Map>();
+}
diff --git a/runtime/observatory/lib/src/elements/logging.html b/runtime/observatory/lib/src/elements/logging.html
new file mode 100644
index 0000000..a3a36a1
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/logging.html
@@ -0,0 +1,77 @@
+<link rel="import" href="../../../../packages/polymer/polymer.html">
+<link rel="import" href="code_ref.html">
+<link rel="import" href="function_ref.html">
+<link rel="import" href="nav_bar.html">
+<link rel="import" href="observatory_element.html">
+<link rel="import" href="sliding_checkbox.html">
+<link rel="import" href="view_footer.html">
+
+<polymer-element name="logging-page" extends="observatory-element">
+  <template>
+    <link rel="stylesheet" href="css/shared.css">
+    <style>
+    .outlined {
+      -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+      -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+      box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+      margin: 4px;
+    }
+    .logItem {
+      font: normal 14px consolas, courier, monospace;
+      white-space: pre;
+      line-height: 125%;
+      width: 100%;
+    }
+    .FINEST {
+      background-color: #FAFAFA;
+    }
+    .FINER {
+      background-color: #ECEFF1;
+    }
+    .FINE {
+      background-color: #EFEBE9;
+    }
+    .CONFIG {
+      background-color: #FFF3E0;
+    }
+    .INFO {
+      background-color: #F1F8E9;
+    }
+    .WARNING {
+      background-color: #FFE0B2;
+    }
+    .SEVERE {
+      background-color: #FFCCBC;
+    }
+    .SHOUT {
+      background-color: #FFCDD2;
+    }
+    #log {
+      height: 100%;
+      width: 100%;
+      overflow-y: auto;
+      padding: 8px;
+    }
+    .fill {
+      height: 80%;
+      width: 100%;
+    }
+    </style>
+    <nav-bar>
+      <top-nav-menu></top-nav-menu>
+      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
+      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
+      <nav-menu link="{{ makeLink('/logging', isolate) }}" anchor="logging" last="{{ true }}"></nav-menu>
+      <nav-refresh callback="{{ clear }}" label="Clear"></nav-refresh>
+    </nav-bar>
+    <div id="page" class="content-centered-big">
+      <span>Show messages with severity <select id="severityLevelSelector" value="{{ severityLevel }}"></select> and higher</span>
+      <hr>
+      <div class="flex-row fill">
+        <div id="log" class="outlined"></div>
+      </div>
+    </div>
+  </template>
+</polymer-element>
+
+<script type="application/dart" src="logging.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/metrics.dart b/runtime/observatory/lib/src/elements/metrics.dart
index b7e4e79..73343c5 100644
--- a/runtime/observatory/lib/src/elements/metrics.dart
+++ b/runtime/observatory/lib/src/elements/metrics.dart
@@ -27,13 +27,22 @@
     if ((isolate != null) && (page != null) &&
         (page.selectedMetricId != null)) {
       selectedMetric = isolate.dartMetrics[page.selectedMetricId];
-      if (selectedMetric == null) {
-        selectedMetric = isolate.nativeMetrics[page.selectedMetricId];
+      if (selectedMetric != null) {
+        return;
       }
+      selectedMetric = isolate.nativeMetrics[page.selectedMetricId];
     }
     if ((selectedMetric == null) && (isolate != null)) {
-      var values = isolate.dartMetrics.values;
-      if (values != null) {
+      var values = isolate.dartMetrics.values.toList();
+      if ((values != null) && (values.length > 0)) {
+        // Fall back and pick the first isolate metric.
+        selectedMetric = values.first;
+      }
+      if (selectedMetric != null) {
+        return;
+      }
+      values = isolate.nativeMetrics.values.toList();
+      if ((values != null) && (values.length > 0)) {
         // Fall back and pick the first isolate metric.
         selectedMetric = values.first;
       }
diff --git a/runtime/observatory/lib/src/elements/object_common.html b/runtime/observatory/lib/src/elements/object_common.html
index 63c78a1..c4ce618 100644
--- a/runtime/observatory/lib/src/elements/object_common.html
+++ b/runtime/observatory/lib/src/elements/object_common.html
@@ -46,7 +46,7 @@
           <template if="{{ path == null }}">
             <eval-link callback="{{ retainingPath }}"
                        label="[find]"
-                       expr="10">
+                       expr="20">
             </eval-link>
           </template>
           <template if="{{ path != null }}">
@@ -54,13 +54,16 @@
             <div class="memberItem">
               <div class="memberName">[{{ element['index']}}]</div>
               <div class="memberValue">
-                <any-service-ref ref="{{ element['value'] }}"></any-service-ref>
                 <template if="{{ element['parentField'] != null }}">
-                  in <field-ref ref="{{ element['parentField'] }}"></field-ref> of
+                  from <field-ref ref="{{ element['parentField'] }}"></field-ref> of
                 </template>
                 <template if="{{ element['parentListIndex'] != null }}">
-                  in [{{ element['parentListIndex'] }}] of
+                  from [{{ element['parentListIndex'] }}] of
                 </template>
+                <template if="{{ element['_parentWordOffset'] != null }}">
+                  from word[{{ element['_parentWordOffset'] }}] of
+                </template>
+                <any-service-ref ref="{{ element['value'] }}"></any-service-ref>
               </div>
               </div>
             </template>
diff --git a/runtime/observatory/lib/src/elements/service_ref.dart b/runtime/observatory/lib/src/elements/service_ref.dart
index 7c5ff02..d823b86 100644
--- a/runtime/observatory/lib/src/elements/service_ref.dart
+++ b/runtime/observatory/lib/src/elements/service_ref.dart
@@ -14,6 +14,7 @@
 class ServiceRefElement extends ObservatoryElement {
   @published ServiceObject ref;
   @published bool internal = false;
+  @published String expandKey;
   ServiceRefElement.created() : super.created();
 
   void refChanged(oldValue) {
@@ -61,6 +62,7 @@
 @CustomTag('any-service-ref')
 class AnyServiceRefElement extends ObservatoryElement {
   @published ServiceObject ref;
+  @published String expandKey;
   AnyServiceRefElement.created() : super.created();
 
   Element _constructElementForRef() {
@@ -106,6 +108,9 @@
       case 'Sentinel':
         ServiceRefElement element = new Element.tag('instance-ref');
         element.ref = ref;
+        if (expandKey != null) {
+          element.expandKey = expandKey;
+        }
         return element;
       default:
         SpanElement element = new Element.tag('span');
diff --git a/runtime/observatory/lib/src/elements/view_footer.html b/runtime/observatory/lib/src/elements/view_footer.html
index aa82cca..59862b5 100644
--- a/runtime/observatory/lib/src/elements/view_footer.html
+++ b/runtime/observatory/lib/src/elements/view_footer.html
@@ -12,7 +12,7 @@
       </a>
     </p>
     <p>
-      <a href="https://code.google.com/p/dart/issues/entry?template=Observatory" style="font-size:90%">
+      <a href="https://github.com/dart-lang/sdk/issues/new?title=Observatory:&amp;body=Observatory%20Feedback" style="font-size:90%">
         File a bug report
       </a>
     </p>
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index fa73cf6..9124595 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -954,6 +954,7 @@
 
 /// State for a running isolate.
 class Isolate extends ServiceObjectOwner with Coverage {
+  static const kLoggingStream = '_Logging';
   @reflectable VM get vm => owner;
   @reflectable Isolate get isolate => this;
   @observable int number;
@@ -1396,6 +1397,67 @@
     return invokeRpc('resume', {'step': 'Out'});
   }
 
+
+  static const int kFirstResume = 0;
+  static const int kSecondResume = 1;
+  /// result[kFirstResume] completes after the inital resume. The UI should
+  /// wait on this future because some other breakpoint may be hit before the
+  /// async continuation.
+  /// result[kSecondResume] completes after the second resume. Tests should
+  /// wait on this future to avoid confusing the pause event at the
+  /// state-machine switch with the pause event after the state-machine switch.
+  List<Future> asyncStepOver() {
+    Completer firstResume = new Completer();
+    Completer secondResume = new Completer();
+    var subscription;
+
+    handleError(error) {
+      if (subscription != null) {
+        subscription.cancel();
+        subscription = null;
+      }
+      firstResume.completeError(error);
+      secondResume.completeError(error);
+    }
+
+    if ((pauseEvent == null) ||
+        (pauseEvent.kind != ServiceEvent.kPauseBreakpoint) ||
+        (pauseEvent.asyncContinuation == null)) {
+      handleError(new Exception("No async continuation available"));
+    } else {
+      Instance continuation = pauseEvent.asyncContinuation;
+      assert(continuation.isClosure);
+      addBreakOnActivation(continuation).then((Breakpoint continuationBpt) {
+        vm.getEventStream(VM.kDebugStream).then((stream) {
+          var onResume = firstResume;
+          subscription = stream.listen((ServiceEvent event) {
+            if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
+                (event.breakpoint == continuationBpt)) {
+              // We are stopped before state-machine dispatch; step-over to
+              // reach user code.
+              removeBreakpoint(continuationBpt).then((_) {
+                onResume = secondResume;
+                stepOver().catchError(handleError);
+              });
+            } else if (event.kind == ServiceEvent.kResume) {
+              if (onResume == secondResume) {
+                subscription.cancel();
+                subscription = null;
+              }
+              if (onResume != null) {
+                onResume.complete(this);
+                onResume = null;
+              }
+            }
+          });
+          resume().catchError(handleError);
+        }).catchError(handleError);
+      }).catchError(handleError);
+    }
+
+    return [firstResume.future, secondResume.future];
+  }
+
   Future setName(String newName) {
     return invokeRpc('setName', {'name': newName});
   }
@@ -1591,6 +1653,15 @@
   String toString() => 'DartError($message)';
 }
 
+Level _findLogLevel(int value) {
+  for (var level in Level.LEVELS) {
+    if (level.value == value) {
+      return level;
+    }
+  }
+  return new Level('$value', value);
+}
+
 /// A [ServiceEvent] is an asynchronous event notification from the vm.
 class ServiceEvent extends ServiceObject {
   /// The possible 'kind' values.
@@ -1611,6 +1682,7 @@
   static const kInspect                = 'Inspect';
   static const kDebuggerSettingsUpdate = '_DebuggerSettingsUpdate';
   static const kConnectionClosed       = 'ConnectionClosed';
+  static const kLogging                = '_Logging';
 
   ServiceEvent._empty(ServiceObjectOwner owner) : super._empty(owner);
 
@@ -1629,6 +1701,7 @@
   @observable String reason;
   @observable String exceptions;
   @observable String bytesAsString;
+  @observable Map logRecord;
   int chunkIndex, chunkCount, nodeCount;
 
   @observable bool get isPauseEvent {
@@ -1691,6 +1764,12 @@
       var bytes = decodeBase64(map['bytes']);
       bytesAsString = UTF8.decode(bytes);
     }
+    if (map['logRecord'] != null) {
+      logRecord = map['logRecord'];
+      logRecord['time'] =
+          new DateTime.fromMillisecondsSinceEpoch(logRecord['time'].toInt());
+      logRecord['level'] = _findLogLevel(logRecord['level']);
+    }
   }
 
   String toString() {
diff --git a/runtime/observatory/lib/tracer.dart b/runtime/observatory/lib/tracer.dart
index 1453c3c..ffe0892 100644
--- a/runtime/observatory/lib/tracer.dart
+++ b/runtime/observatory/lib/tracer.dart
@@ -60,7 +60,7 @@
       _current = null;
     }
   }
-  
+
   // The tracer subscribes to all logging events.
   StreamSubscription loggerSub = null;
 
@@ -93,5 +93,5 @@
     var event = new TraceEvent.msg(_time.elapsedMicroseconds, message, map);
     events.add(event);
     return event;
-  } 
+  }
 }
diff --git a/runtime/observatory/lib/utils.dart b/runtime/observatory/lib/utils.dart
index c696529..cfc447c 100644
--- a/runtime/observatory/lib/utils.dart
+++ b/runtime/observatory/lib/utils.dart
@@ -135,6 +135,13 @@
     return '${seconds}s';
   }
 
+  static String formatDateTime(DateTime now) {
+    return '${now.year}-${now.month}-${now.day} '
+           '${now.hour.toString().padLeft(2)}:'
+           '${now.minute.toString().padLeft(2)}:'
+           '${now.second.toString().padLeft(2)}';
+  }
+
   static String formatSeconds(double x) {
     return x.toStringAsFixed(2);
   }
diff --git a/runtime/observatory/observatory.gypi b/runtime/observatory/observatory.gypi
index 156caad..50cd334 100644
--- a/runtime/observatory/observatory.gypi
+++ b/runtime/observatory/observatory.gypi
@@ -43,10 +43,7 @@
       'target_name': 'build_observatory',
       'type': 'none',
       'dependencies': [
-        'dart_bootstrap#host',
         'fetch_observatory_deps#host',
-        # We use packages for building
-        '../pkg/pkg.gyp:pkg_packages#target',
       ],
       'toolsets': ['host'],
       'includes': [
@@ -57,13 +54,11 @@
           'action_name': 'pub_build_observatory',
           'inputs': [
             '../../tools/observatory_tool.py',
-            '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
             'pubspec.lock',
             '<@(_sources)',
           ],
           'outputs': [
             '<(PRODUCT_DIR)/observatory/build/web/index.html',
-            '<(PRODUCT_DIR)/observatory/build/web/index.html.polymer.bootstrap.dart.js',
           ],
           'action': [
             'python',
@@ -81,11 +76,9 @@
           'inputs': [
             '../../tools/observatory_tool.py',
             '<(PRODUCT_DIR)/observatory/build/web/index.html',
-            '<(PRODUCT_DIR)/observatory/build/web/index.html.polymer.bootstrap.dart.js',
           ],
           'outputs': [
             '<(PRODUCT_DIR)/observatory/deployed/web/index.html',
-            '<(PRODUCT_DIR)/observatory/deployed/web/index.html.polymer.bootstrap.dart.js',
           ],
           'action': [
             'python',
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index 9445912..e02a5e7 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -103,6 +103,8 @@
     'lib/src/elements/library_ref.html',
     'lib/src/elements/library_view.dart',
     'lib/src/elements/library_view.html',
+    'lib/src/elements/logging.dart',
+    'lib/src/elements/logging.html',
     'lib/src/elements/metrics.dart',
     'lib/src/elements/metrics.html',
     'lib/src/elements/nav_bar.dart',
diff --git a/runtime/observatory/tests/service/allocations_test.dart b/runtime/observatory/tests/service/allocations_test.dart
index 4708811..6cd953f 100644
--- a/runtime/observatory/tests/service/allocations_test.dart
+++ b/runtime/observatory/tests/service/allocations_test.dart
@@ -25,8 +25,8 @@
     expect(lib.classes.length, equals(1));
     return lib.classes.first.load().then((Class fooClass) {
       expect(fooClass.name, equals('Foo'));
-      expect(fooClass.newSpace.accumulated.instances +
-             fooClass.oldSpace.accumulated.instances, equals(3));
+      expect(fooClass.newSpace.current.instances +
+             fooClass.oldSpace.current.instances, equals(3));
     });
 }),
 
diff --git a/runtime/observatory/tests/service/async_continuation_test.dart b/runtime/observatory/tests/service/async_continuation_test.dart
index 5b65bf8..781f7ca 100644
--- a/runtime/observatory/tests/service/async_continuation_test.dart
+++ b/runtime/observatory/tests/service/async_continuation_test.dart
@@ -66,7 +66,7 @@
       if (bp == bp1) {
         await stoppedAtLine(15)(isolate);
         print(event.asyncContinuation);
-        expect(event.asyncContinuation.isNull, isTrue);
+        expect(event.asyncContinuation, equals(null));
         isolate.resume();
         bp1_hit.complete(null);
       }
diff --git a/runtime/observatory/tests/service/async_next_test.dart b/runtime/observatory/tests/service/async_next_test.dart
new file mode 100644
index 0000000..2e9a0f2
--- /dev/null
+++ b/runtime/observatory/tests/service/async_next_test.dart
@@ -0,0 +1,43 @@
+// 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.
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override  --verbose_debug
+
+import 'package:observatory/service_io.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+foo() async { }
+
+doAsync(stop) async {
+  if (stop) debugger();
+  await foo(); // Line 14.
+  await foo(); // Line 15.
+  await foo(); // Line 16.
+  return null;
+}
+
+testMain() {
+  // With two runs of doAsync floating around, async step should only cause
+  // us to stop in the run we started in.
+  doAsync(false);
+  doAsync(true);
+}
+
+asyncNext(Isolate isolate) async {
+  return isolate.asyncStepOver()[Isolate.kSecondResume];
+}
+
+var tests = [
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(14),
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(15),
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(16),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/async_scope_test.dart b/runtime/observatory/tests/service/async_scope_test.dart
index 3150b50..981ea26 100644
--- a/runtime/observatory/tests/service/async_scope_test.dart
+++ b/runtime/observatory/tests/service/async_scope_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
-import 'dart:async';
 import 'dart:developer';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -13,14 +12,14 @@
 
 doAsync(param1) async {
   var local1 = param1 + 1;
-  foo(); // Line 16
-  await null;
+  foo(); // Line 15
+  await local1;
 }
 
 doAsyncStar(param2) async* {
   var local2 = param2 + 1;
-  foo(); // Line 22
-  yield null;
+  foo(); // Line 21
+  yield local2;
 }
 
 testeeDo() {
@@ -54,17 +53,17 @@
 
 var tests = [
   hasStoppedAtBreakpoint, // debugger()
-  setBreakpointAtLine(16),
-  setBreakpointAtLine(22),
+  setBreakpointAtLine(15),
+  setBreakpointAtLine(21),
   resumeIsolate,
 
   hasStoppedAtBreakpoint,
-  stoppedAtLine(16),
+  stoppedAtLine(15),
   checkAsyncVarDescriptors,
   resumeIsolate,
 
   hasStoppedAtBreakpoint,
-  stoppedAtLine(22),
+  stoppedAtLine(21),
   checkAsyncStarVarDescriptors,
   resumeIsolate,
 ];
diff --git a/runtime/observatory/tests/service/async_step_test.dart b/runtime/observatory/tests/service/async_step_test.dart
deleted file mode 100644
index fb0fafd..0000000
--- a/runtime/observatory/tests/service/async_step_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override  --verbose_debug
-
-import 'package:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
-import 'test_helper.dart';
-import 'dart:developer';
-
-foo() async { }
-
-doAsync(stop) async {
-  if (stop) debugger();
-  await foo(); // Line 15.
-  await foo(); // Line 16.
-  await foo(); // Line 17.
-  return null;
-}
-
-testMain() {
-  // With two runs of doAsync floating around, async step should only cause
-  // us to stop in the run we started in.
-  doAsync(false);
-  doAsync(true);
-}
-
-asyncStep(Isolate isolate) async {
-  await isolate.reload(); // isolate.pauseEvent may be stale
-  ServiceEvent event = isolate.pauseEvent;
-  print("Pause event is $event");
-  expect(event, isNotNull);
-  expect(event.kind, equals(ServiceEvent.kPauseBreakpoint));
-
-  // 1. Set breakpoint for the continuation and resume the isolate.
-  Instance continuation = event.asyncContinuation;
-  print("Async continuation is $continuation");
-  if (continuation == null) {
-    print(await isolate.getStack());
-  }
-  expect(continuation.isClosure, isTrue);
-
-  var bpt = await isolate.addBreakOnActivation(continuation);
-  print("Async step to $bpt");
-  expect(bpt is Breakpoint, isTrue);
-
-  await isolate.resume();
-  await hasStoppedAtBreakpoint(isolate);
-  print("Big step to: ${isolate.pauseEvent}");
-
-  // 2. Step past the state-machine dispatch.
-  await isolate.stepOver();
-  await hasStoppedAtBreakpoint(isolate);
-  print("Small step to: ${isolate.pauseEvent}");
-}
-
-var tests = [
-  hasStoppedAtBreakpoint,
-  stoppedAtLine(15),
-  asyncStep,
-  stoppedAtLine(16),
-  asyncStep,
-  stoppedAtLine(17),
-  resumeIsolate,
-];
-
-main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/capture_stdio_test.dart b/runtime/observatory/tests/service/capture_stdio_test.dart
index b9673cf..56a1451 100644
--- a/runtime/observatory/tests/service/capture_stdio_test.dart
+++ b/runtime/observatory/tests/service/capture_stdio_test.dart
@@ -85,5 +85,5 @@
   },
 ];
 
-  
+
 main(args) => runIsolateTests(args, tests, testeeConcurrent: test);
diff --git a/runtime/observatory/tests/service/crash_dump_test.dart b/runtime/observatory/tests/service/crash_dump_test.dart
new file mode 100644
index 0000000..8b60567
--- /dev/null
+++ b/runtime/observatory/tests/service/crash_dump_test.dart
@@ -0,0 +1,34 @@
+// 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 crash_dump_test;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory/service_io.dart';
+
+import 'test_helper.dart';
+
+Future warmup() async {
+  print('hi');
+}
+
+var tests = [
+  (VM vm) async {
+    HttpClient client = new HttpClient();
+    var request =
+        await client.getUrl(Uri.parse('$serviceHttpAddress/_getCrashDump'));
+    var response = await request.close();
+    Completer completer = new Completer();
+    StringBuffer sb = new StringBuffer();
+    response.transform(UTF8.decoder).listen((chunk) {
+      sb.write(chunk);
+    }, onDone: () => completer.complete(sb.toString()));
+    var responseString = await completer.future;
+    JSON.decode(responseString);
+  }
+];
+
+main(args) async => runVMTests(args, tests, testeeBefore:warmup);
diff --git a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
index dbb43c7..f773dae 100644
--- a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
@@ -78,7 +78,7 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('_getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['elements'][0]['parentField']['name'], equals('x'));
+    expect(result['elements'][1]['parentField']['name'], equals('x'));
     expect(result['elements'][2]['value']['name'], equals('globalObject'));
   },
 
@@ -91,7 +91,7 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('_getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['elements'][0]['parentField']['name'], equals('y'));
+    expect(result['elements'][1]['parentField']['name'], equals('y'));
     expect(result['elements'][2]['value']['name'], equals('globalObject'));
   },
 
@@ -104,7 +104,7 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('_getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['elements'][0]['parentListIndex'], equals(12));
+    expect(result['elements'][1]['parentListIndex'], equals(12));
     expect(result['elements'][2]['value']['name'], equals('globalList'));
   },
 ];
diff --git a/runtime/observatory/tests/service/get_stack_rpc_test.dart b/runtime/observatory/tests/service/get_stack_rpc_test.dart
index f3736e6..7210794 100644
--- a/runtime/observatory/tests/service/get_stack_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_stack_rpc_test.dart
@@ -19,7 +19,7 @@
 
 void periodicTask(_) {
   port.sendPort.send(34);
-  developer.debugger(msg: "foo", when: true); // We will be at the next line.
+  developer.debugger(message: "fo", when: true); // We will be at the next line.
   counter++;
   if (counter % 300 == 0) {
     print('counter = $counter');
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index cb03444..636eb71 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
   (VM vm) async {
     var result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
-    expect(result['major'], equals(1));
+    expect(result['major'], equals(2));
     expect(result['minor'], equals(0));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
diff --git a/runtime/observatory/tests/service/logging_test.dart b/runtime/observatory/tests/service/logging_test.dart
new file mode 100644
index 0000000..cefa67b
--- /dev/null
+++ b/runtime/observatory/tests/service/logging_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer' as developer;
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'package:logging/logging.dart';
+
+import 'test_helper.dart';
+
+void init() {
+  Logger.root.level = Level.ALL;
+  Logger.root.onRecord.listen((logRecord) {
+    developer.log(
+        logRecord.message,
+        time: logRecord.time,
+        sequenceNumber: logRecord.sequenceNumber,
+        level: logRecord.level.value,
+        name: logRecord.loggerName,
+        zone: null,
+        error: logRecord.error,
+        stackTrace: logRecord.stackTrace);
+  });
+}
+
+void run() {
+  developer.debugger();
+  Logger.root.fine('Hey Buddy!');
+  developer.debugger();
+  Logger.root.info('YES');
+}
+
+var tests = [
+  hasStoppedAtBreakpoint,
+  resumeIsolateAndAwaitEvent(Isolate.kLoggingStream, (ServiceEvent event) {
+    expect(event.kind, equals(ServiceEvent.kLogging));
+    expect(event.logRecord['sequenceNumber'], equals(0));
+    expect(event.logRecord['message'].valueAsString, equals('Hey Buddy!'));
+    expect(event.logRecord['level'], equals(Level.FINE));
+    expect(event.logRecord['time'], new isInstanceOf<DateTime>());
+  }),
+  resumeIsolateAndAwaitEvent(Isolate.kLoggingStream, (ServiceEvent event) {
+    expect(event.kind, equals(ServiceEvent.kLogging));
+    expect(event.logRecord['sequenceNumber'], equals(1));
+    expect(event.logRecord['level'], equals(Level.INFO));
+    expect(event.logRecord['message'].valueAsString, equals('YES'));
+    expect(event.logRecord['time'], new isInstanceOf<DateTime>());
+  }),
+];
+
+main(args) => runIsolateTests(args,
+                              tests,
+                              testeeBefore: init,
+                              testeeConcurrent: run);
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 53520c4..4c492ed 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override --checked
 
 library test_helper;
 
@@ -87,6 +86,10 @@
 typedef Future IsolateTest(Isolate isolate);
 typedef Future VMTest(VM vm);
 
+/// Will be set to the http address of the VM's service protocol before
+/// any tests are invoked.
+String serviceHttpAddress;
+
 /// Runs [tests] in sequence, each of which should take an [Isolate] and
 /// return a [Future]. Code for setting up state can run before and/or
 /// concurrently with the tests. Uses [mainArgs] to determine whether
@@ -113,6 +116,7 @@
         port = 8181;
       }
       String addr = 'ws://localhost:$port/ws';
+      serviceHttpAddress = 'http://localhost:$port';
       var testIndex = 1;
       var totalTests = tests.length;
       var name = Platform.script.pathSegments.last;
@@ -167,7 +171,8 @@
           print('Breakpoint reached');
           subscription.cancel();
           if (completer != null) {
-            completer.complete(isolate);
+            // Reload to update isolate.pauseEvent.
+            completer.complete(isolate.reload());
             completer = null;
           }
         }
@@ -237,6 +242,30 @@
 }
 
 
+Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async {
+  Completer completer = new Completer();
+  var sub;
+  sub = await isolate.vm.listenEventStream(
+    stream,
+    (ServiceEvent event) {
+      var r = onEvent(event);
+      if (r is! Future) {
+        r = new Future.value(r);
+      }
+      r.then((x) => sub.cancel().then((_) {
+        completer.complete();
+      }));
+    });
+  await isolate.resume();
+  return completer.future;
+}
+
+IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) {
+  return (Isolate isolate) async =>
+      resumeAndAwaitEvent(isolate, stream, onEvent);
+}
+
+
 Future<Class> getClassFromRootLib(Isolate isolate, String className) async {
   Library rootLib = await isolate.rootLibrary.load();
   for (var i = 0; i < rootLib.classes.length; i++) {
@@ -275,6 +304,7 @@
         port = 8181;
       }
       String addr = 'ws://localhost:$port/ws';
+      serviceHttpAddress = 'http://localhost:$port';
       var testIndex = 1;
       var totalTests = tests.length;
       var name = Platform.script.pathSegments.last;
diff --git a/runtime/observatory/tests/ui/log.dart b/runtime/observatory/tests/ui/log.dart
new file mode 100644
index 0000000..8bd1940
--- /dev/null
+++ b/runtime/observatory/tests/ui/log.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer' as developer;
+import 'package:logging/logging.dart';
+
+main() {
+  Logger.root.level = Level.ALL;
+  Logger.root.onRecord.listen((logRecord) {
+    developer.log(
+        logRecord.message,
+        time: logRecord.time,
+        sequenceNumber: logRecord.sequenceNumber,
+        level: logRecord.level.value,
+        name: logRecord.loggerName,
+        zone: null,
+        error: logRecord.error,
+        stackTrace: logRecord.stackTrace);
+  });
+  new Timer.periodic(new Duration(seconds: 1), (t) {
+    Logger.root.info('INFO MESSAGE');
+  });
+  new Timer.periodic(new Duration(seconds: 1), (t) {
+    Logger.root.fine('FINE MESSAGE');
+  });
+}
diff --git a/runtime/observatory/tests/ui/log.txt b/runtime/observatory/tests/ui/log.txt
new file mode 100644
index 0000000..0f64917
--- /dev/null
+++ b/runtime/observatory/tests/ui/log.txt
@@ -0,0 +1,6 @@
+0. Run dart --observe log.dart
+1. Visit main isolate's logging page.
+2. You should see 'INFO MESSAGE' and 'FINE MESSAGE'.
+3. Adjust the level to be 'INFO' and see that 'FINE' messages are hidden.
+4. Adjust the level to be 'FINE' and see that all messages are displayed.
+5. Adjust the level to be 'SHOUT' and see that no messages are displayed.
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 8bf2fb4..d0ffb46 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -4,7 +4,7 @@
 
 # These tests are expected to crash on all platforms.
 cc/ArrayNew_Overflow_Crash: Crash
-cc/AllocGeneric_Overflow: Crash
+cc/AllocGeneric_Overflow: Crash, Timeout
 cc/CodeImmutability: Crash
 
 cc/SNPrint_BadArgs: Skip
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index b6ca73e..92e2885 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -30,11 +30,11 @@
 }
 
 
-void StackResource::UnwindAbove(Isolate* isolate, StackResource* new_top) {
-  StackResource* current_resource = isolate->top_resource();
+void StackResource::UnwindAbove(Thread* thread, StackResource* new_top) {
+  StackResource* current_resource = thread->top_resource();
   while (current_resource != new_top) {
     current_resource->~StackResource();
-    current_resource = isolate->top_resource();
+    current_resource = thread->top_resource();
   }
 }
 
diff --git a/runtime/vm/allocation.h b/runtime/vm/allocation.h
index f6b74b8..3947f0e 100644
--- a/runtime/vm/allocation.h
+++ b/runtime/vm/allocation.h
@@ -70,12 +70,10 @@
   // The thread that owns this resource.
   Thread* thread() const { return thread_; }
 
-  // Destroy stack resources of isolate until top exit frame.
-  // TODO(koda): Migrate to Thread.
-  static void Unwind(Isolate* isolate) { UnwindAbove(isolate, NULL); }
-  // TODO(koda): Migrate to Thread.
-  // Destroy stack resources of isolate above new_top, exclusive.
-  static void UnwindAbove(Isolate* isolate, StackResource* new_top);
+  // Destroy stack resources of thread until top exit frame.
+  static void Unwind(Thread* thread) { UnwindAbove(thread, NULL); }
+  // Destroy stack resources of thread above new_top, exclusive.
+  static void UnwindAbove(Thread* thread, StackResource* new_top);
 
  private:
   void Init(Thread* thread) {
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index 3f3e61a..9d17b1b 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -312,9 +312,10 @@
     return Object::empty_object_pool().raw();
   }
   const ObjectPool& result = ObjectPool::Handle(ObjectPool::New(len));
+  const TypedData& info_array = TypedData::Handle(result.info_array());
   for (intptr_t i = 0; i < len; ++i) {
     ObjectPool::EntryType info = object_pool_[i].type_;
-    result.SetInfoAt(i, info);
+    info_array.SetInt8(i, static_cast<int8_t>(info));
     if (info == ObjectPool::kTaggedObject) {
       result.SetObjectAt(i, *object_pool_[i].obj_);
     } else {
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 0e3fb7e..bd2a6e7 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1525,11 +1525,16 @@
 }
 
 
+intptr_t Assembler::FindImmediate(int32_t imm) {
+  return object_pool_wrapper_.FindImmediate(imm);
+}
+
+
 // Uses a code sequence that can easily be decoded.
 void Assembler::LoadWordFromPoolOffset(Register rd,
                                        int32_t offset,
                                        Condition cond) {
-  ASSERT(allow_constant_pool());
+  ASSERT(constant_pool_allowed());
   ASSERT(rd != PP);
   int32_t offset_mask = 0;
   if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) {
@@ -1555,6 +1560,7 @@
      Instructions::HeaderSize() - Instructions::object_pool_offset() +
      CodeSize() + Instr::kPCReadOffset;
   LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist);
+  set_constant_pool_allowed(true);
 }
 
 
@@ -1576,7 +1582,7 @@
   // Smis and VM heap objects are never relocated; do not use object pool.
   if (object.IsSmi()) {
     LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond);
-  } else if (object.InVMHeap() || !allow_constant_pool()) {
+  } else if (object.InVMHeap() || !constant_pool_allowed()) {
     // Make sure that class CallPattern is able to decode this load immediate.
     const int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
     LoadImmediate(rd, object_raw, cond);
@@ -2678,6 +2684,12 @@
 }
 
 
+void Assembler::Branch(const StubEntry& stub_entry, Condition cond) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  Branch(&label, cond);
+}
+
+
 void Assembler::BranchPatchable(const ExternalLabel* label) {
   // Use a fixed size code sequence, since a function prologue may be patched
   // with this branch sequence.
@@ -2688,12 +2700,24 @@
 }
 
 
+void Assembler::BranchPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchPatchable(&label);
+}
+
+
 void Assembler::BranchLink(const ExternalLabel* label) {
   LoadImmediate(LR, label->address());  // Target address is never patched.
   blx(LR);  // Use blx instruction so that the return branch prediction works.
 }
 
 
+void Assembler::BranchLink(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLink(&label);
+}
+
+
 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) {
   // Make sure that class CallPattern is able to patch the label referred
   // to by this code sequence.
@@ -2706,11 +2730,24 @@
 }
 
 
+void Assembler::BranchLink(const StubEntry& stub_entry,
+                           Patchability patchable) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLink(&label, patchable);
+}
+
+
 void Assembler::BranchLinkPatchable(const ExternalLabel* label) {
   BranchLink(label, kPatchable);
 }
 
 
+void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLinkPatchable(&label);
+}
+
+
 void Assembler::BranchLinkOffset(Register base, int32_t offset) {
   ASSERT(base != PC);
   ASSERT(base != IP);
@@ -2746,7 +2783,12 @@
     Register rd, int32_t value, Condition cond) {
   const ARMVersion version = TargetCPUFeatures::arm_version();
   if ((version == ARMv5TE) || (version == ARMv6)) {
-    LoadPatchableImmediate(rd, value, cond);
+    if (constant_pool_allowed()) {
+      const int32_t offset = Array::element_offset(FindImmediate(value));
+      LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
+    } else {
+      LoadPatchableImmediate(rd, value, cond);
+    }
   } else {
     ASSERT(version == ARMv7);
     movw(rd, Utils::Low16Bits(value), cond);
@@ -3273,6 +3315,7 @@
 
 
 void Assembler::EnterDartFrame(intptr_t frame_size) {
+  ASSERT(!constant_pool_allowed());
   const intptr_t offset = CodeSize();
 
   // Save PC in frame for fast identification of corresponding code.
@@ -3301,6 +3344,7 @@
 // optimized function and there may be extra space for spill slots to
 // allocate. We must also set up the pool pointer for the function.
 void Assembler::EnterOsrFrame(intptr_t extra_size) {
+  ASSERT(!constant_pool_allowed());
   // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be
   // different from EntryPointToPcMarkerOffset().
   const intptr_t offset =
@@ -3320,6 +3364,10 @@
 
 
 void Assembler::LeaveDartFrame() {
+  // LeaveDartFrame is called from stubs (pp disallowed) and from Dart code (pp
+  // allowed), so there is no point in checking the current value of
+  // constant_pool_allowed().
+  set_constant_pool_allowed(false);
   LeaveFrame((1 << PP) | (1 << FP) | (1 << LR));
   // Adjust SP for PC pushed in EnterDartFrame.
   AddImmediate(SP, kWordSize);
@@ -3327,6 +3375,7 @@
 
 
 void Assembler::EnterStubFrame() {
+  set_constant_pool_allowed(false);
   // Push 0 as saved PC for stub frames.
   mov(IP, Operand(LR));
   mov(LR, Operand(0));
@@ -3339,6 +3388,7 @@
 
 void Assembler::LeaveStubFrame() {
   LeaveFrame((1 << PP) | (1 << FP) | (1 << LR));
+  set_constant_pool_allowed(false);
   // Adjust SP for null PC pushed in EnterStubFrame.
   AddImmediate(SP, kWordSize);
 }
@@ -3373,8 +3423,9 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
-                                     Label* trace) {
-  LoadAllocationStatsAddress(temp_reg, cid);
+                                     Label* trace,
+                                     bool inline_isolate) {
+  LoadAllocationStatsAddress(temp_reg, cid, inline_isolate);
   const uword state_offset = ClassHeapStats::state_offset();
   ldr(temp_reg, Address(temp_reg, state_offset));
   tst(temp_reg, Operand(ClassHeapStats::TraceAllocationMask()));
@@ -3433,29 +3484,26 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure);
-    Heap* heap = Isolate::Current()->heap();
-    Heap::Space space = heap->SpaceForAllocation(cls.id());
-    const uword top_address = heap->TopAddress(space);
-    LoadImmediate(temp_reg, top_address);
-    ldr(instance_reg, Address(temp_reg));
+    MaybeTraceAllocation(cls.id(), temp_reg, failure,
+                         /* inline_isolate = */ false);
+    Heap::Space space = Heap::SpaceForAllocation(cls.id());
+    ldr(temp_reg, Address(THR, Thread::heap_offset()));
+    ldr(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
     // TODO(koda): Protect against unsigned overflow here.
     AddImmediateSetFlags(instance_reg, instance_reg, instance_size);
 
     // instance_reg: potential next object start.
-    const uword end_address = heap->EndAddress(space);
-    ASSERT(top_address < end_address);
-    // Could use ldm to load (top, end), but no benefit seen experimentally.
-    ldr(IP, Address(temp_reg, end_address - top_address));
+    ldr(IP, Address(temp_reg, Heap::EndOffset(space)));
     cmp(IP, Operand(instance_reg));
     // fail if heap end unsigned less than or equal to instance_reg.
     b(failure, LS);
 
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
-    str(instance_reg, Address(temp_reg));
+    str(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
 
-    LoadAllocationStatsAddress(temp_reg, cls.id());
+    LoadAllocationStatsAddress(temp_reg, cls.id(),
+                               /* inline_isolate = */ false);
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
@@ -3485,28 +3533,26 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, temp1, failure);
-    Isolate* isolate = Isolate::Current();
-    Heap* heap = isolate->heap();
-    Heap::Space space = heap->SpaceForAllocation(cid);
-    LoadImmediate(temp1, heap->TopAddress(space));
-    ldr(instance, Address(temp1, 0));  // Potential new object start.
+    MaybeTraceAllocation(cid, temp1, failure, /* inline_isolate = */ false);
+    Heap::Space space = Heap::SpaceForAllocation(cid);
+    ldr(temp1, Address(THR, Thread::heap_offset()));
+    // Potential new object start.
+    ldr(instance, Address(temp1, Heap::TopOffset(space)));
     AddImmediateSetFlags(end_address, instance, instance_size);
     b(failure, CS);  // Branch if unsigned overflow.
 
     // Check if the allocation fits into the remaining space.
     // instance: potential new object start.
     // end_address: potential next object start.
-    LoadImmediate(temp2, heap->EndAddress(space));
-    ldr(temp2, Address(temp2, 0));
+    ldr(temp2, Address(temp1, Heap::EndOffset(space)));
     cmp(end_address, Operand(temp2));
     b(failure, CS);
 
-    LoadAllocationStatsAddress(temp2, cid);
+    LoadAllocationStatsAddress(temp2, cid, /* inline_isolate = */ false);
 
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
-    str(end_address, Address(temp1, 0));
+    str(end_address, Address(temp1, Heap::TopOffset(space)));
     add(instance, instance, Operand(kHeapObjectTag));
 
     // Initialize the tags.
@@ -3527,11 +3573,10 @@
 
 void Assembler::Stop(const char* message) {
   if (FLAG_print_stop_message) {
-    StubCode* stub_code = Isolate::Current()->stub_code();
     PushList((1 << R0) | (1 << IP) | (1 << LR));  // Preserve R0, IP, LR.
     LoadImmediate(R0, reinterpret_cast<int32_t>(message));
     // PrintStopMessage() preserves all registers.
-    BranchLink(&stub_code->PrintStopMessageLabel());  // Passing message in R0.
+    BranchLink(&StubCode::PrintStopMessage_entry()->label());
     PopList((1 << R0) | (1 << IP) | (1 << LR));  // Restore R0, IP, LR.
   }
   // Emit the message address before the svc instruction, so that we can
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 70dd9ad..8218bb9 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -21,6 +21,7 @@
 
 // Forward declarations.
 class RuntimeEntry;
+class StubEntry;
 
 class Label : public ValueObject {
  public:
@@ -319,7 +320,7 @@
         prologue_offset_(-1),
         use_far_branches_(use_far_branches),
         comments_(),
-        allow_constant_pool_(true) { }
+        constant_pool_allowed_(false) { }
 
   ~Assembler() { }
 
@@ -608,17 +609,22 @@
   // Macros.
   // Branch to an entry address. Call sequence is never patched.
   void Branch(const ExternalLabel* label, Condition cond = AL);
+  void Branch(const StubEntry& stub_entry, Condition cond = AL);
 
   // Branch to an entry address. Call sequence can be patched or even replaced.
   void BranchPatchable(const ExternalLabel* label);
+  void BranchPatchable(const StubEntry& stub_entry);
 
   // Branch and link to an entry address. Call sequence is never patched.
   void BranchLink(const ExternalLabel* label);
+  void BranchLink(const StubEntry& stub_entry);
 
   void BranchLink(const ExternalLabel* label, Patchability patchable);
+  void BranchLink(const StubEntry& stub_entry, Patchability patchable);
 
   // Branch and link to an entry address. Call sequence can be patched.
   void BranchLinkPatchable(const ExternalLabel* label);
+  void BranchLinkPatchable(const StubEntry& stub_entry);
 
   // Branch and link to [base + offset]. Call sequence is never patched.
   void BranchLinkOffset(Register base, int32_t offset);
@@ -755,6 +761,7 @@
                            Register scratch2,
                            Label* miss);
 
+  intptr_t FindImmediate(int32_t imm);
   void LoadWordFromPoolOffset(Register rd, int32_t offset, Condition cond = AL);
   void LoadFromOffset(OperandSize type,
                       Register reg,
@@ -938,7 +945,8 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
-                            Label* trace);
+                            Label* trace,
+                            bool inline_isolate = true);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
@@ -965,11 +973,11 @@
   static bool IsSafe(const Object& object) { return true; }
   static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
 
-  bool allow_constant_pool() const {
-    return allow_constant_pool_;
+  bool constant_pool_allowed() const {
+    return constant_pool_allowed_;
   }
-  void set_allow_constant_pool(bool b) {
-    allow_constant_pool_ = b;
+  void set_constant_pool_allowed(bool b) {
+    constant_pool_allowed_ = b;
   }
 
  private:
@@ -1005,7 +1013,7 @@
 
   GrowableArray<CodeComment*> comments_;
 
-  bool allow_constant_pool_;
+  bool constant_pool_allowed_;
 
   void LoadObjectHelper(Register rd,
                         const Object& object,
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 290890e..11fbdb2 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -30,7 +30,7 @@
       prologue_offset_(-1),
       use_far_branches_(use_far_branches),
       comments_(),
-      allow_constant_pool_(true) {
+      constant_pool_allowed_(false) {
 }
 
 
@@ -316,21 +316,22 @@
   // because the offset wouldn't be aligned, it would be only one instruction
   // for the first 64 entries.
   sub(pp, pp, Operand(kHeapObjectTag));
+  set_constant_pool_allowed(pp == PP);
 }
 
 
-void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
-                                       uint32_t offset) {
-  ASSERT(dst != pp);
+void Assembler::LoadWordFromPoolOffset(Register dst, uint32_t offset) {
+  ASSERT(constant_pool_allowed());
+  ASSERT(dst != PP);
   Operand op;
   const uint32_t upper20 = offset & 0xfffff000;
   if (Address::CanHoldOffset(offset)) {
-    ldr(dst, Address(pp, offset));
+    ldr(dst, Address(PP, offset));
   } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) ==
              Operand::Immediate) {
     const uint32_t lower12 = offset & 0x00000fff;
     ASSERT(Address::CanHoldOffset(lower12));
-    add(dst, pp, op);
+    add(dst, PP, op);
     ldr(dst, Address(dst, lower12));
   } else {
     const uint16_t offset_low = Utils::Low16Bits(offset);
@@ -339,14 +340,14 @@
     if (offset_high != 0) {
       movk(dst, Immediate(offset_high), 1);
     }
-    ldr(dst, Address(pp, dst));
+    ldr(dst, Address(PP, dst));
   }
 }
 
 
-void Assembler::LoadWordFromPoolOffsetFixed(Register dst, Register pp,
-                                            uint32_t offset) {
-  ASSERT(dst != pp);
+void Assembler::LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset) {
+  ASSERT(constant_pool_allowed());
+  ASSERT(dst != PP);
   Operand op;
   const uint32_t upper20 = offset & 0xfffff000;
   const uint32_t lower12 = offset & 0x00000fff;
@@ -354,7 +355,7 @@
       Operand::CanHold(upper20, kXRegSizeInBits, &op);
   ASSERT(ot == Operand::Immediate);
   ASSERT(Address::CanHoldOffset(lower12));
-  add(dst, pp, op);
+  add(dst, PP, op);
   ldr(dst, Address(dst, lower12));
 }
 
@@ -366,7 +367,7 @@
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
   ASSERT(!Thread::CanLoadFromThread(object));
-  if (!allow_constant_pool()) {
+  if (!constant_pool_allowed()) {
     return false;
   }
 
@@ -383,36 +384,24 @@
 }
 
 
-bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) {
-  if (!allow_constant_pool()) {
-    return false;
-  }
-  return !Utils::IsInt(32, imm) && (pp != kNoPP);
-}
-
-
-void Assembler::LoadExternalLabel(Register dst,
-                                  const ExternalLabel* label,
-                                  Patchability patchable,
-                                  Register pp) {
-  const int64_t target = static_cast<int64_t>(label->address());
-  if (CanLoadImmediateFromPool(target, pp)) {
+void Assembler::LoadExternalLabel(Register dst, const ExternalLabel* label) {
+  if (constant_pool_allowed()) {
     const int32_t offset = ObjectPool::element_offset(
-        object_pool_wrapper_.FindExternalLabel(label, patchable));
-    LoadWordFromPoolOffset(dst, pp, offset);
+        object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
+    LoadWordFromPoolOffset(dst, offset);
   } else {
-    LoadImmediate(dst, target, kNoPP);
+    const int64_t target = static_cast<int64_t>(label->address());
+    LoadImmediate(dst, target);
   }
 }
 
 
 void Assembler::LoadExternalLabelFixed(Register dst,
                                        const ExternalLabel* label,
-                                       Patchability patchable,
-                                       Register pp) {
+                                       Patchability patchable) {
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper_.FindExternalLabel(label, patchable));
-  LoadWordFromPoolOffsetFixed(dst, pp, offset);
+  LoadWordFromPoolOffsetFixed(dst, offset);
 }
 
 
@@ -423,7 +412,6 @@
 
 void Assembler::LoadObjectHelper(Register dst,
                                  const Object& object,
-                                 Register pp,
                                  bool is_unique) {
   if (Thread::CanLoadFromThread(object)) {
     ldr(dst, Address(THR, Thread::OffsetFromThread(object)));
@@ -431,43 +419,53 @@
     const int32_t offset = ObjectPool::element_offset(
         is_unique ? object_pool_wrapper_.AddObject(object)
                   : object_pool_wrapper_.FindObject(object));
-    LoadWordFromPoolOffset(dst, pp, offset);
+    LoadWordFromPoolOffset(dst, offset);
   } else {
     ASSERT(object.IsSmi() || object.InVMHeap());
-    LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
+    LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()));
   }
 }
 
 
-void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
-  LoadObjectHelper(dst, object, pp, false);
+void Assembler::LoadFunctionFromCalleePool(Register dst,
+                                           const Function& function,
+                                           Register new_pp) {
+  ASSERT(!constant_pool_allowed());
+  ASSERT(new_pp != PP);
+  const int32_t offset =
+      ObjectPool::element_offset(object_pool_wrapper_.FindObject(function));
+  ASSERT(Address::CanHoldOffset(offset));
+  ldr(dst, Address(new_pp, offset));
 }
 
 
-void Assembler::LoadUniqueObject(Register dst,
-                                 const Object& object,
-                                 Register pp) {
-  LoadObjectHelper(dst, object, pp, true);
+void Assembler::LoadObject(Register dst, const Object& object) {
+  LoadObjectHelper(dst, object, false);
 }
 
 
-void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
+void Assembler::LoadUniqueObject(Register dst, const Object& object) {
+  LoadObjectHelper(dst, object, true);
+}
+
+
+void Assembler::CompareObject(Register reg, const Object& object) {
   if (Thread::CanLoadFromThread(object)) {
     ldr(TMP, Address(THR, Thread::OffsetFromThread(object)));
     CompareRegisters(reg, TMP);
   } else if (CanLoadFromObjectPool(object)) {
-    LoadObject(TMP, object, pp);
+    LoadObject(TMP, object);
     CompareRegisters(reg, TMP);
   } else {
-    CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()), pp);
+    CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()));
   }
 }
 
 
-void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) {
-  if ((pp != kNoPP) && allow_constant_pool()) {
+void Assembler::LoadDecodableImmediate(Register reg, int64_t imm) {
+  if (constant_pool_allowed()) {
     const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
-    LoadWordFromPoolOffset(reg, pp, offset);
+    LoadWordFromPoolOffset(reg, offset);
   } else {
     // TODO(zra): Since this sequence only needs to be decodable, it can be
     // of variable length.
@@ -490,111 +488,127 @@
 }
 
 
-void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) {
+void Assembler::LoadImmediate(Register reg, int64_t imm) {
   Comment("LoadImmediate");
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    // It's a 64-bit constant and we're not in the VM isolate, so load from
-    // object pool.
-    // Save the bits that must be masked-off for the SmiTag
-    int64_t val_smi_tag = imm & kSmiTagMask;
-    imm &= ~kSmiTagMask;  // Mask off the tag bits.
+  // Is it 0?
+  if (imm == 0) {
+    movz(reg, Immediate(0), 0);
+    return;
+  }
+
+  // Can we use one orri operation?
+  Operand op;
+  Operand::OperandType ot;
+  ot = Operand::CanHold(imm, kXRegSizeInBits, &op);
+  if (ot == Operand::BitfieldImm) {
+    orri(reg, ZR, Immediate(imm));
+    return;
+  }
+
+  // We may fall back on movz, movk, movn.
+  const uint32_t w0 = Utils::Low32Bits(imm);
+  const uint32_t w1 = Utils::High32Bits(imm);
+  const uint16_t h0 = Utils::Low16Bits(w0);
+  const uint16_t h1 = Utils::High16Bits(w0);
+  const uint16_t h2 = Utils::Low16Bits(w1);
+  const uint16_t h3 = Utils::High16Bits(w1);
+
+  // Special case for w1 == 0xffffffff
+  if (w1 == 0xffffffff) {
+    if (h1 == 0xffff) {
+      movn(reg, Immediate(~h0), 0);
+    } else {
+      movn(reg, Immediate(~h1), 1);
+      movk(reg, Immediate(h0), 0);
+    }
+    return;
+  }
+
+  // Special case for h3 == 0xffff
+  if (h3 == 0xffff) {
+    // We know h2 != 0xffff.
+    movn(reg, Immediate(~h2), 2);
+    if (h1 != 0xffff) {
+      movk(reg, Immediate(h1), 1);
+    }
+    if (h0 != 0xffff) {
+      movk(reg, Immediate(h0), 0);
+    }
+    return;
+  }
+
+  // Use constant pool if allowed, unless we can load imm with 2 instructions.
+  if ((w1 != 0) && constant_pool_allowed()) {
     const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
-    LoadWordFromPoolOffset(reg, pp, offset);
-    if (val_smi_tag != 0) {
-      // Add back the tag bits.
-      orri(reg, reg, Immediate(val_smi_tag));
-    }
-  } else {
-    // 0. Is it 0?
-    if (imm == 0) {
-      movz(reg, Immediate(0), 0);
-      return;
-    }
+    LoadWordFromPoolOffset(reg, offset);
+    return;
+  }
 
-    // 1. Can we use one orri operation?
-    Operand op;
-    Operand::OperandType ot;
-    ot = Operand::CanHold(imm, kXRegSizeInBits, &op);
-    if (ot == Operand::BitfieldImm) {
-      orri(reg, ZR, Immediate(imm));
-      return;
-    }
-
-    // 2. Fall back on movz, movk, movn.
-    const uint32_t w0 = Utils::Low32Bits(imm);
-    const uint32_t w1 = Utils::High32Bits(imm);
-    const uint16_t h0 = Utils::Low16Bits(w0);
-    const uint16_t h1 = Utils::High16Bits(w0);
-    const uint16_t h2 = Utils::Low16Bits(w1);
-    const uint16_t h3 = Utils::High16Bits(w1);
-
-    // Special case for w1 == 0xffffffff
-    if (w1 == 0xffffffff) {
-      if (h1 == 0xffff) {
-        movn(reg, Immediate(~h0), 0);
-      } else {
-        movn(reg, Immediate(~h1), 1);
-        movk(reg, Immediate(h0), 0);
-      }
-      return;
-    }
-
-    // Special case for h3 == 0xffff
-    if (h3 == 0xffff) {
-      // We know h2 != 0xffff.
-      movn(reg, Immediate(~h2), 2);
-      if (h1 != 0xffff) {
-        movk(reg, Immediate(h1), 1);
-      }
-      if (h0 != 0xffff) {
-        movk(reg, Immediate(h0), 0);
-      }
-      return;
-    }
-
-    bool initialized = false;
-    if (h0 != 0) {
-      movz(reg, Immediate(h0), 0);
+  bool initialized = false;
+  if (h0 != 0) {
+    movz(reg, Immediate(h0), 0);
+    initialized = true;
+  }
+  if (h1 != 0) {
+    if (initialized) {
+      movk(reg, Immediate(h1), 1);
+    } else {
+      movz(reg, Immediate(h1), 1);
       initialized = true;
     }
-    if (h1 != 0) {
-      if (initialized) {
-        movk(reg, Immediate(h1), 1);
-      } else {
-        movz(reg, Immediate(h1), 1);
-        initialized = true;
-      }
+  }
+  if (h2 != 0) {
+    if (initialized) {
+      movk(reg, Immediate(h2), 2);
+    } else {
+      movz(reg, Immediate(h2), 2);
+      initialized = true;
     }
-    if (h2 != 0) {
-      if (initialized) {
-        movk(reg, Immediate(h2), 2);
-      } else {
-        movz(reg, Immediate(h2), 2);
-        initialized = true;
-      }
-    }
-    if (h3 != 0) {
-      if (initialized) {
-        movk(reg, Immediate(h3), 3);
-      } else {
-        movz(reg, Immediate(h3), 3);
-      }
+  }
+  if (h3 != 0) {
+    if (initialized) {
+      movk(reg, Immediate(h3), 3);
+    } else {
+      movz(reg, Immediate(h3), 3);
     }
   }
 }
 
 
-void Assembler::LoadDImmediate(VRegister vd, double immd, Register pp) {
+void Assembler::LoadDImmediate(VRegister vd, double immd) {
   if (!fmovdi(vd, immd)) {
     int64_t imm = bit_cast<int64_t, double>(immd);
-    LoadImmediate(TMP, imm, pp);
+    LoadImmediate(TMP, imm);
     fmovdr(vd, TMP);
   }
 }
 
 
-void Assembler::AddImmediate(
-    Register dest, Register rn, int64_t imm, Register pp) {
+void Assembler::Branch(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  Branch(&label);
+}
+
+
+void Assembler::BranchPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchPatchable(&label);
+}
+
+
+void Assembler::BranchLink(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLink(&label);
+}
+
+
+void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLinkPatchable(&label);
+}
+
+
+void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
   Operand op;
   if (imm == 0) {
     if (dest != rn) {
@@ -610,14 +624,13 @@
   } else {
     // TODO(zra): Try adding top 12 bits, then bottom 12 bits.
     ASSERT(rn != TMP2);
-    LoadImmediate(TMP2, imm, pp);
+    LoadImmediate(TMP2, imm);
     add(dest, rn, Operand(TMP2));
   }
 }
 
 
-void Assembler::AddImmediateSetFlags(
-    Register dest, Register rn, int64_t imm, Register pp) {
+void Assembler::AddImmediateSetFlags(Register dest, Register rn, int64_t imm) {
   Operand op;
   if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
     // Handles imm == kMinInt64.
@@ -629,14 +642,13 @@
   } else {
     // TODO(zra): Try adding top 12 bits, then bottom 12 bits.
     ASSERT(rn != TMP2);
-    LoadImmediate(TMP2, imm, pp);
+    LoadImmediate(TMP2, imm);
     adds(dest, rn, Operand(TMP2));
   }
 }
 
 
-void Assembler::SubImmediateSetFlags(
-    Register dest, Register rn, int64_t imm, Register pp) {
+void Assembler::SubImmediateSetFlags(Register dest, Register rn, int64_t imm) {
   Operand op;
   if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
     // Handles imm == kMinInt64.
@@ -648,60 +660,57 @@
   } else {
     // TODO(zra): Try subtracting top 12 bits, then bottom 12 bits.
     ASSERT(rn != TMP2);
-    LoadImmediate(TMP2, imm, pp);
+    LoadImmediate(TMP2, imm);
     subs(dest, rn, Operand(TMP2));
   }
 }
 
 
-void Assembler::AndImmediate(
-    Register rd, Register rn, int64_t imm, Register pp) {
+void Assembler::AndImmediate(Register rd, Register rn, int64_t imm) {
   Operand imm_op;
   if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
     andi(rd, rn, Immediate(imm));
   } else {
-    LoadImmediate(TMP, imm, pp);
+    LoadImmediate(TMP, imm);
     and_(rd, rn, Operand(TMP));
   }
 }
 
 
-void Assembler::OrImmediate(
-    Register rd, Register rn, int64_t imm, Register pp) {
+void Assembler::OrImmediate(Register rd, Register rn, int64_t imm) {
   Operand imm_op;
   if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
     orri(rd, rn, Immediate(imm));
   } else {
-    LoadImmediate(TMP, imm, pp);
+    LoadImmediate(TMP, imm);
     orr(rd, rn, Operand(TMP));
   }
 }
 
 
-void Assembler::XorImmediate(
-    Register rd, Register rn, int64_t imm, Register pp) {
+void Assembler::XorImmediate(Register rd, Register rn, int64_t imm) {
   Operand imm_op;
   if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
     eori(rd, rn, Immediate(imm));
   } else {
-    LoadImmediate(TMP, imm, pp);
+    LoadImmediate(TMP, imm);
     eor(rd, rn, Operand(TMP));
   }
 }
 
 
-void Assembler::TestImmediate(Register rn, int64_t imm, Register pp) {
+void Assembler::TestImmediate(Register rn, int64_t imm) {
   Operand imm_op;
   if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
     tsti(rn, Immediate(imm));
   } else {
-    LoadImmediate(TMP, imm, pp);
+    LoadImmediate(TMP, imm);
     tst(rn, Operand(TMP));
   }
 }
 
 
-void Assembler::CompareImmediate(Register rn, int64_t imm, Register pp) {
+void Assembler::CompareImmediate(Register rn, int64_t imm) {
   Operand op;
   if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
     cmp(rn, op);
@@ -710,80 +719,76 @@
     cmn(rn, op);
   } else {
     ASSERT(rn != TMP2);
-    LoadImmediate(TMP2, imm, pp);
+    LoadImmediate(TMP2, imm);
     cmp(rn, Operand(TMP2));
   }
 }
 
 
 void Assembler::LoadFromOffset(
-    Register dest, Register base, int32_t offset, Register pp, OperandSize sz) {
+    Register dest, Register base, int32_t offset, OperandSize sz) {
   if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
     ldr(dest, Address(base, offset, Address::Offset, sz), sz);
   } else {
     ASSERT(base != TMP2);
-    AddImmediate(TMP2, base, offset, pp);
+    AddImmediate(TMP2, base, offset);
     ldr(dest, Address(TMP2), sz);
   }
 }
 
 
-void Assembler::LoadDFromOffset(
-    VRegister dest, Register base, int32_t offset, Register pp) {
+void Assembler::LoadDFromOffset(VRegister dest, Register base, int32_t offset) {
   if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
     fldrd(dest, Address(base, offset, Address::Offset, kDWord));
   } else {
     ASSERT(base != TMP2);
-    AddImmediate(TMP2, base, offset, pp);
+    AddImmediate(TMP2, base, offset);
     fldrd(dest, Address(TMP2));
   }
 }
 
 
-void Assembler::LoadQFromOffset(
-    VRegister dest, Register base, int32_t offset, Register pp) {
+void Assembler::LoadQFromOffset(VRegister dest, Register base, int32_t offset) {
   if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
     fldrq(dest, Address(base, offset, Address::Offset, kQWord));
   } else {
     ASSERT(base != TMP2);
-    AddImmediate(TMP2, base, offset, pp);
+    AddImmediate(TMP2, base, offset);
     fldrq(dest, Address(TMP2));
   }
 }
 
 
 void Assembler::StoreToOffset(
-    Register src, Register base, int32_t offset, Register pp, OperandSize sz) {
+    Register src, Register base, int32_t offset, OperandSize sz) {
   ASSERT(base != TMP2);
   if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
     str(src, Address(base, offset, Address::Offset, sz), sz);
   } else {
     ASSERT(src != TMP2);
-    AddImmediate(TMP2, base, offset, pp);
+    AddImmediate(TMP2, base, offset);
     str(src, Address(TMP2), sz);
   }
 }
 
 
-void Assembler::StoreDToOffset(
-    VRegister src, Register base, int32_t offset, Register pp) {
+void Assembler::StoreDToOffset(VRegister src, Register base, int32_t offset) {
   if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
     fstrd(src, Address(base, offset, Address::Offset, kDWord));
   } else {
     ASSERT(base != TMP2);
-    AddImmediate(TMP2, base, offset, pp);
+    AddImmediate(TMP2, base, offset);
     fstrd(src, Address(TMP2));
   }
 }
 
 
-void Assembler::StoreQToOffset(
-    VRegister src, Register base, int32_t offset, Register pp) {
+void Assembler::StoreQToOffset(VRegister src, Register base, int32_t offset) {
   if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
     fstrq(src, Address(base, offset, Address::Offset, kQWord));
   } else {
     ASSERT(base != TMP2);
-    AddImmediate(TMP2, base, offset, pp);
+    AddImmediate(TMP2, base, offset);
     fstrq(src, Address(TMP2));
   }
 }
@@ -857,13 +862,12 @@
 void Assembler::StoreIntoObjectOffset(Register object,
                                       int32_t offset,
                                       Register value,
-                                      Register pp,
                                       bool can_value_be_smi) {
   if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
     StoreIntoObject(
         object, FieldAddress(object, offset), value, can_value_be_smi);
   } else {
-    AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
+    AddImmediate(TMP, object, offset - kHeapObjectTag);
     StoreIntoObject(object, Address(TMP), value, can_value_be_smi);
   }
 }
@@ -917,12 +921,11 @@
 
 void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
                                                int32_t offset,
-                                               Register value,
-                                               Register pp) {
+                                               Register value) {
   if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
     StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
   } else {
-    AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
+    AddImmediate(TMP, object, offset - kHeapObjectTag);
     StoreIntoObjectNoBarrier(object, Address(TMP), value);
   }
 }
@@ -934,71 +937,69 @@
   ASSERT(value.IsSmi() || value.InVMHeap() ||
          (value.IsOld() && value.IsNotTemporaryScopedHandle()));
   // No store buffer update.
-  LoadObject(TMP2, value, PP);
+  LoadObject(TMP2, value);
   str(TMP2, dest);
 }
 
 
 void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
                                                int32_t offset,
-                                               const Object& value,
-                                               Register pp) {
+                                               const Object& value) {
   if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
     StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
   } else {
-    AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
+    AddImmediate(TMP, object, offset - kHeapObjectTag);
     StoreIntoObjectNoBarrier(object, Address(TMP), value);
   }
 }
 
 
-void Assembler::LoadClassId(Register result, Register object, Register pp) {
+void Assembler::LoadClassId(Register result, Register object) {
   ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32);
   ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32);
   const intptr_t class_id_offset = Object::tags_offset() +
       RawObject::kClassIdTagPos / kBitsPerByte;
-  LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, pp,
+  LoadFromOffset(result, object, class_id_offset - kHeapObjectTag,
                  kUnsignedWord);
 }
 
 
-void Assembler::LoadClassById(Register result, Register class_id, Register pp) {
+void Assembler::LoadClassById(Register result, Register class_id) {
   ASSERT(result != class_id);
   LoadIsolate(result);
   const intptr_t offset =
       Isolate::class_table_offset() + ClassTable::table_offset();
-  LoadFromOffset(result, result, offset, pp);
+  LoadFromOffset(result, result, offset);
   ldr(result, Address(result, class_id, UXTX, Address::Scaled));
 }
 
 
-void Assembler::LoadClass(Register result, Register object, Register pp) {
+void Assembler::LoadClass(Register result, Register object) {
   ASSERT(object != TMP);
-  LoadClassId(TMP, object, pp);
-  LoadClassById(result, TMP, pp);
+  LoadClassId(TMP, object);
+  LoadClassById(result, TMP);
 }
 
 
-void Assembler::CompareClassId(
-    Register object, intptr_t class_id, Register pp) {
-  LoadClassId(TMP, object, pp);
-  CompareImmediate(TMP, class_id, pp);
+void Assembler::CompareClassId(Register object, intptr_t class_id) {
+  LoadClassId(TMP, object);
+  CompareImmediate(TMP, class_id);
 }
 
 
 void Assembler::LoadClassIdMayBeSmi(Register result, Register object) {
   // Load up a null object. We only need it so we can use LoadClassId on it in
   // the case that object is a Smi..
-  LoadObject(TMP, Object::null_object(), PP);
+  LoadObject(TMP, Object::null_object());
   // Check if the object is a Smi.
   tsti(object, Immediate(kSmiTagMask));
   // If the object *is* a Smi, use the null object instead. o/w leave alone.
   csel(TMP, TMP, object, EQ);
   // Loads either the cid of the object if it isn't a Smi, or the cid of null
   // if it is a Smi, which will be ignored.
-  LoadClassId(result, TMP, PP);
+  LoadClassId(result, TMP);
 
-  LoadImmediate(TMP, kSmiCid, PP);
+  LoadImmediate(TMP, kSmiCid);
   // If object is a Smi, move the Smi cid into result. o/w leave alone.
   csel(result, TMP, result, EQ);
 }
@@ -1020,22 +1021,22 @@
   b(&not_smi, NE);
 
   AsrImmediate(scratch, value, 32);
-  LoadImmediate(result, ICData::kUint32RangeBit, PP);
+  LoadImmediate(result, ICData::kUint32RangeBit);
   cmp(scratch, Operand(1));
   b(&done, EQ);
 
   neg(scratch, scratch);
   add(result, scratch, Operand(ICData::kInt32RangeBit));
   cmp(scratch, Operand(1));
-  LoadImmediate(TMP, ICData::kSignedRangeBit, PP);
+  LoadImmediate(TMP, ICData::kSignedRangeBit);
   csel(result, result, TMP, LS);
   b(&done);
 
   Bind(&not_smi);
-  CompareClassId(value, kMintCid, PP);
+  CompareClassId(value, kMintCid);
   b(not_mint, NE);
 
-  LoadImmediate(result, ICData::kInt64RangeBit, PP);
+  LoadImmediate(result, ICData::kInt64RangeBit);
   Bind(&done);
 }
 
@@ -1061,7 +1062,7 @@
   // Reserve space for arguments and align frame before entering
   // the C++ world.
   if (frame_space != 0) {
-    AddImmediate(SP, SP, -frame_space, kNoPP);
+    AddImmediate(SP, SP, -frame_space);
   }
   if (OS::ActivationFrameAlignment() > 1) {
     andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
@@ -1086,37 +1087,40 @@
 
 
 void Assembler::EnterDartFrame(intptr_t frame_size) {
+  ASSERT(!constant_pool_allowed());
   // Setup the frame.
   adr(TMP, Immediate(-CodeSize()));  // TMP gets PC marker.
   EnterFrame(0);
   TagAndPushPPAndPcMarker(TMP);  // Save PP and PC marker.
 
   // Load the pool pointer.
-  LoadPoolPointer(PP);
+  LoadPoolPointer();
 
   // Reserve space.
   if (frame_size > 0) {
-    AddImmediate(SP, SP, -frame_size, PP);
+    AddImmediate(SP, SP, -frame_size);
   }
 }
 
 
 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) {
+  ASSERT(!constant_pool_allowed());
   // Setup the frame.
   adr(TMP, Immediate(-CodeSize()));  // TMP gets PC marker.
   EnterFrame(0);
   TagAndPushPPAndPcMarker(TMP);  // Save PP and PC marker.
 
   // Load the pool pointer.
-  if (new_pp == kNoPP) {
-    LoadPoolPointer(PP);
+  if (new_pp == kNoRegister) {
+    LoadPoolPointer();
   } else {
     mov(PP, new_pp);
+    set_constant_pool_allowed(true);
   }
 
   // Reserve space.
   if (frame_size > 0) {
-    AddImmediate(SP, SP, -frame_size, PP);
+    AddImmediate(SP, SP, -frame_size);
   }
 }
 
@@ -1127,27 +1131,33 @@
 // optimized function and there may be extra space for spill slots to
 // allocate. We must also set up the pool pointer for the function.
 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) {
+  ASSERT(!constant_pool_allowed());
   Comment("EnterOsrFrame");
   adr(TMP, Immediate(-CodeSize()));
 
-  StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize, kNoPP);
+  StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize);
 
   // Setup pool pointer for this dart function.
-  if (new_pp == kNoPP) {
-    LoadPoolPointer(PP);
+  if (new_pp == kNoRegister) {
+    LoadPoolPointer();
   } else {
     mov(PP, new_pp);
+    set_constant_pool_allowed(true);
   }
 
   if (extra_size > 0) {
-    AddImmediate(SP, SP, -extra_size, PP);
+    AddImmediate(SP, SP, -extra_size);
   }
 }
 
 
 void Assembler::LeaveDartFrame() {
+  // LeaveDartFrame is called from stubs (pp disallowed) and from Dart code (pp
+  // allowed), so there is no point in checking the current value of
+  // constant_pool_allowed().
+  set_constant_pool_allowed(false);
   // Restore and untag PP.
-  LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize, kNoPP);
+  LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize);
   sub(PP, PP, Operand(kHeapObjectTag));
   LeaveFrame();
 }
@@ -1185,7 +1195,7 @@
   const intptr_t kPushedRegistersSize =
       kDartVolatileCpuRegCount * kWordSize +
       kDartVolatileFpuRegCount * kWordSize;
-  AddImmediate(SP, FP, -kPushedRegistersSize, PP);
+  AddImmediate(SP, FP, -kPushedRegistersSize);
   for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) {
     const Register reg = static_cast<Register>(i);
     Pop(reg);
@@ -1213,23 +1223,24 @@
 
 
 void Assembler::EnterStubFrame() {
+  set_constant_pool_allowed(false);
   EnterFrame(0);
   // Save caller's pool pointer. Push 0 in the saved PC area for stub frames.
   TagAndPushPPAndPcMarker(ZR);
-  LoadPoolPointer(PP);
+  LoadPoolPointer();
 }
 
 
 void Assembler::LeaveStubFrame() {
+  set_constant_pool_allowed(false);
   // Restore and untag PP.
-  LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize, kNoPP);
+  LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize);
   sub(PP, PP, Operand(kHeapObjectTag));
   LeaveFrame();
 }
 
 
 void Assembler::UpdateAllocationStats(intptr_t cid,
-                                      Register pp,
                                       Heap::Space space,
                                       bool inline_isolate) {
   ASSERT(cid > 0);
@@ -1240,28 +1251,27 @@
     ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
     if (cid < kNumPredefinedCids) {
       LoadImmediate(
-          TMP2, reinterpret_cast<uword>(*table_ptr) + counter_offset, pp);
+          TMP2, reinterpret_cast<uword>(*table_ptr) + counter_offset);
     } else {
-      LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr), pp);
+      LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr));
       ldr(TMP, Address(TMP2));
-      AddImmediate(TMP2, TMP, counter_offset, pp);
+      AddImmediate(TMP2, TMP, counter_offset);
     }
   } else {
     LoadIsolate(TMP2);
     intptr_t table_offset =
         Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
     ldr(TMP, Address(TMP2, table_offset));
-    AddImmediate(TMP2, TMP, counter_offset, pp);
+    AddImmediate(TMP2, TMP, counter_offset);
   }
   ldr(TMP, Address(TMP2, 0));
-  AddImmediate(TMP, TMP, 1, pp);
+  AddImmediate(TMP, TMP, 1);
   str(TMP, Address(TMP2, 0));
 }
 
 
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               Register size_reg,
-                                              Register pp,
                                               Heap::Space space,
                                               bool inline_isolate) {
   ASSERT(cid > 0);
@@ -1277,21 +1287,21 @@
     ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
     if (cid < kNumPredefinedCids) {
       LoadImmediate(TMP2,
-                    reinterpret_cast<uword>(*table_ptr) + class_offset, pp);
+                    reinterpret_cast<uword>(*table_ptr) + class_offset);
     } else {
-      LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr), pp);
+      LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr));
       ldr(TMP, Address(TMP2));
-      AddImmediate(TMP2, TMP, class_offset, pp);
+      AddImmediate(TMP2, TMP, class_offset);
     }
   } else {
     LoadIsolate(TMP2);
     intptr_t table_offset =
         Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
     ldr(TMP, Address(TMP2, table_offset));
-    AddImmediate(TMP2, TMP, class_offset, pp);
+    AddImmediate(TMP2, TMP, class_offset);
   }
   ldr(TMP, Address(TMP2, count_field_offset));
-  AddImmediate(TMP, TMP, 1, pp);
+  AddImmediate(TMP, TMP, 1);
   str(TMP, Address(TMP2, count_field_offset));
   ldr(TMP, Address(TMP2, size_field_offset));
   add(TMP, TMP, Operand(size_reg));
@@ -1301,21 +1311,27 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
-                                     Register pp,
-                                     Label* trace) {
+                                     Label* trace,
+                                     bool inline_isolate) {
   ASSERT(cid > 0);
-  intptr_t state_offset;
-  ClassTable* class_table = Isolate::Current()->class_table();
-  ClassHeapStats** table_ptr =
-      class_table->StateAddressFor(cid, &state_offset);
-
-  if (cid < kNumPredefinedCids) {
-    LoadImmediate(
-        temp_reg, reinterpret_cast<uword>(*table_ptr) + state_offset, pp);
+  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
+  if (inline_isolate) {
+    ClassTable* class_table = Isolate::Current()->class_table();
+    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
+    if (cid < kNumPredefinedCids) {
+      LoadImmediate(
+          temp_reg, reinterpret_cast<uword>(*table_ptr) + state_offset);
+    } else {
+      LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
+      ldr(temp_reg, Address(temp_reg, 0));
+      AddImmediate(temp_reg, temp_reg, state_offset);
+    }
   } else {
-    LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr), pp);
-    ldr(temp_reg, Address(temp_reg, 0));
-    AddImmediate(temp_reg, temp_reg, state_offset, pp);
+    LoadIsolate(temp_reg);
+    intptr_t table_offset =
+        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+    ldr(temp_reg, Address(temp_reg, table_offset));
+    AddImmediate(temp_reg, temp_reg, state_offset);
   }
   ldr(temp_reg, Address(temp_reg, 0));
   tsti(temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
@@ -1326,47 +1342,42 @@
 void Assembler::TryAllocate(const Class& cls,
                             Label* failure,
                             Register instance_reg,
-                            Register temp_reg,
-                            Register pp) {
+                            Register temp_reg) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, pp, failure);
+    MaybeTraceAllocation(cls.id(), temp_reg, failure,
+                         /* inline_isolate = */ false);
     const intptr_t instance_size = cls.instance_size();
-    Heap* heap = Isolate::Current()->heap();
-    Heap::Space space = heap->SpaceForAllocation(cls.id());
-    const uword top_address = heap->TopAddress(space);
-    LoadImmediate(temp_reg, top_address, pp);
-    ldr(instance_reg, Address(temp_reg));
+    Heap::Space space = Heap::SpaceForAllocation(cls.id());
+    ldr(temp_reg, Address(THR, Thread::heap_offset()));
+    ldr(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
     // TODO(koda): Protect against unsigned overflow here.
-    AddImmediateSetFlags(instance_reg, instance_reg, instance_size, pp);
+    AddImmediateSetFlags(instance_reg, instance_reg, instance_size);
 
     // instance_reg: potential next object start.
-    const uword end_address = heap->EndAddress(space);
-    ASSERT(top_address < end_address);
-    // Could use ldm to load (top, end), but no benefit seen experimentally.
-    ldr(TMP, Address(temp_reg, end_address - top_address));
+    ldr(TMP, Address(temp_reg, Heap::EndOffset(space)));
     CompareRegisters(TMP, instance_reg);
     // fail if heap end unsigned less than or equal to instance_reg.
     b(failure, LS);
 
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
-    str(instance_reg, Address(temp_reg));
+    str(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(
-        instance_reg, instance_reg, -instance_size + kHeapObjectTag, pp);
-    UpdateAllocationStats(cls.id(), pp, space);
+        instance_reg, instance_reg, -instance_size + kHeapObjectTag);
+    UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
 
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
     ASSERT(cls.id() != kIllegalCid);
     tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    LoadImmediate(TMP, tags, pp);
-    StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp);
+    LoadImmediate(TMP, tags);
+    StoreFieldToOffset(TMP, instance_reg, Object::tags_offset());
   } else {
     b(failure);
   }
@@ -1384,36 +1395,35 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, temp1, PP, failure);
-    Isolate* isolate = Isolate::Current();
-    Heap* heap = isolate->heap();
-    Heap::Space space = heap->SpaceForAllocation(cid);
-    LoadImmediate(temp1, heap->TopAddress(space), PP);
-    ldr(instance, Address(temp1, 0));  // Potential new object start.
-    AddImmediateSetFlags(end_address, instance, instance_size, PP);
+    MaybeTraceAllocation(cid, temp1, failure, /* inline_isolate = */ false);
+    Heap::Space space = Heap::SpaceForAllocation(cid);
+    ldr(temp1, Address(THR, Thread::heap_offset()));
+    // Potential new object start.
+    ldr(instance, Address(temp1, Heap::TopOffset(space)));
+    AddImmediateSetFlags(end_address, instance, instance_size);
     b(failure, CS);  // Fail on unsigned overflow.
 
     // Check if the allocation fits into the remaining space.
     // instance: potential new object start.
     // end_address: potential next object start.
-    LoadImmediate(temp2, heap->EndAddress(space), PP);
-    ldr(temp2, Address(temp2, 0));
+    ldr(temp2, Address(temp1, Heap::EndOffset(space)));
     cmp(end_address, Operand(temp2));
     b(failure, CS);
 
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
-    str(end_address, Address(temp1, 0));
+    str(end_address, Address(temp1, Heap::TopOffset(space)));
     add(instance, instance, Operand(kHeapObjectTag));
-    LoadImmediate(temp2, instance_size, PP);
-    UpdateAllocationStatsWithSize(cid, temp2, PP, space);
+    LoadImmediate(temp2, instance_size);
+    UpdateAllocationStatsWithSize(cid, temp2, space,
+                                  /* inline_isolate = */ false);
 
     // Initialize the tags.
     // instance: new object start as a tagged pointer.
     uword tags = 0;
     tags = RawObject::ClassIdTag::update(cid, tags);
     tags = RawObject::SizeTag::update(instance_size, tags);
-    LoadImmediate(temp2, tags, PP);
+    LoadImmediate(temp2, tags);
     str(temp2, FieldAddress(instance, Array::tags_offset()));  // Store tags.
   } else {
     b(failure);
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index 32da483..936e105 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -21,6 +21,7 @@
 
 // Forward declarations.
 class RuntimeEntry;
+class StubEntry;
 
 class Immediate : public ValueObject {
  public:
@@ -119,7 +120,7 @@
   // is unscaled.
   Address(Register rn, int32_t offset = 0, AddressType at = Offset,
           OperandSize sz = kDoubleWord) {
-    ASSERT((rn != R31) && (rn != ZR));
+    ASSERT((rn != kNoRegister) && (rn != R31) && (rn != ZR));
     ASSERT(CanHoldOffset(offset, at, sz));
     const Register crn = ConcreteRegister(rn);
     const int32_t scale = Log2OperandSizeBytes(sz);
@@ -1161,6 +1162,8 @@
   void PopAndUntagPP() {
     ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex));
     sub(PP, PP, Operand(kHeapObjectTag));
+    // The caller of PopAndUntagPP() must explicitly allow use of popped PP.
+    set_constant_pool_allowed(false);
   }
   void tst(Register rn, Operand o) {
     ands(ZR, rn, o);
@@ -1196,11 +1199,13 @@
   }
 
   // Branching to ExternalLabels.
-  void Branch(const ExternalLabel* label, Register pp) {
-    LoadExternalLabel(TMP, label, kNotPatchable, pp);
+  void Branch(const ExternalLabel* label) {
+    LoadExternalLabel(TMP, label);
     br(TMP);
   }
 
+  void Branch(const StubEntry& stub_entry);
+
   // Fixed length branch to label.
   void BranchPatchable(const ExternalLabel* label) {
     // TODO(zra): Use LoadExternalLabelFixed if possible.
@@ -1208,69 +1213,65 @@
     br(TMP);
   }
 
-  void BranchLink(const ExternalLabel* label, Register pp) {
-    LoadExternalLabel(TMP, label, kNotPatchable, pp);
+  void BranchPatchable(const StubEntry& stub_entry);
+
+  void BranchLink(const ExternalLabel* label) {
+    LoadExternalLabel(TMP, label);
     blr(TMP);
   }
 
+  void BranchLink(const StubEntry& stub_entry);
+
   // BranchLinkPatchable must be a fixed-length sequence so we can patch it
   // with the debugger.
   void BranchLinkPatchable(const ExternalLabel* label) {
-    LoadExternalLabelFixed(TMP, label, kPatchable, PP);
+    LoadExternalLabelFixed(TMP, label, kPatchable);
     blr(TMP);
   }
 
+  void BranchLinkPatchable(const StubEntry& stub_entry);
+
   // Macros accepting a pp Register argument may attempt to load values from
   // the object pool when possible. Unless you are sure that the untagged object
   // pool pointer is in another register, or that it is not available at all,
   // PP should be passed for pp.
-  void AddImmediate(Register dest, Register rn, int64_t imm, Register pp);
-  void AddImmediateSetFlags(
-      Register dest, Register rn, int64_t imm, Register pp);
-  void SubImmediateSetFlags(
-      Register dest, Register rn, int64_t imm, Register pp);
-  void AndImmediate(Register rd, Register rn, int64_t imm, Register pp);
-  void OrImmediate(Register rd, Register rn, int64_t imm, Register pp);
-  void XorImmediate(Register rd, Register rn, int64_t imm, Register pp);
-  void TestImmediate(Register rn, int64_t imm, Register pp);
-  void CompareImmediate(Register rn, int64_t imm, Register pp);
+  void AddImmediate(Register dest, Register rn, int64_t imm);
+  void AddImmediateSetFlags(Register dest, Register rn, int64_t imm);
+  void SubImmediateSetFlags(Register dest, Register rn, int64_t imm);
+  void AndImmediate(Register rd, Register rn, int64_t imm);
+  void OrImmediate(Register rd, Register rn, int64_t imm);
+  void XorImmediate(Register rd, Register rn, int64_t imm);
+  void TestImmediate(Register rn, int64_t imm);
+  void CompareImmediate(Register rn, int64_t imm);
 
   void LoadFromOffset(Register dest, Register base, int32_t offset,
-                      Register pp, OperandSize sz = kDoubleWord);
+                      OperandSize sz = kDoubleWord);
   void LoadFieldFromOffset(Register dest, Register base, int32_t offset,
-                           Register pp, OperandSize sz = kDoubleWord) {
-    LoadFromOffset(dest, base, offset - kHeapObjectTag, pp, sz);
+                           OperandSize sz = kDoubleWord) {
+    LoadFromOffset(dest, base, offset - kHeapObjectTag, sz);
   }
-  void LoadDFromOffset(
-      VRegister dest, Register base, int32_t offset, Register pp);
-  void LoadDFieldFromOffset(
-      VRegister dest, Register base, int32_t offset, Register pp) {
-    LoadDFromOffset(dest, base, offset - kHeapObjectTag, pp);
+  void LoadDFromOffset(VRegister dest, Register base, int32_t offset);
+  void LoadDFieldFromOffset(VRegister dest, Register base, int32_t offset) {
+    LoadDFromOffset(dest, base, offset - kHeapObjectTag);
   }
-  void LoadQFromOffset(
-      VRegister dest, Register base, int32_t offset, Register pp);
-  void LoadQFieldFromOffset(
-      VRegister dest, Register base, int32_t offset, Register pp) {
-    LoadQFromOffset(dest, base, offset - kHeapObjectTag, pp);
+  void LoadQFromOffset(VRegister dest, Register base, int32_t offset);
+  void LoadQFieldFromOffset(VRegister dest, Register base, int32_t offset) {
+    LoadQFromOffset(dest, base, offset - kHeapObjectTag);
   }
 
   void StoreToOffset(Register src, Register base, int32_t offset,
-                     Register pp, OperandSize sz = kDoubleWord);
+                     OperandSize sz = kDoubleWord);
   void StoreFieldToOffset(Register src, Register base, int32_t offset,
-                          Register pp, OperandSize sz = kDoubleWord) {
-    StoreToOffset(src, base, offset - kHeapObjectTag, pp, sz);
+                          OperandSize sz = kDoubleWord) {
+    StoreToOffset(src, base, offset - kHeapObjectTag, sz);
   }
-  void StoreDToOffset(
-      VRegister src, Register base, int32_t offset, Register pp);
-  void StoreDFieldToOffset(
-      VRegister src, Register base, int32_t offset, Register pp) {
-    StoreDToOffset(src, base, offset - kHeapObjectTag, pp);
+  void StoreDToOffset(VRegister src, Register base, int32_t offset);
+  void StoreDFieldToOffset(VRegister src, Register base, int32_t offset) {
+    StoreDToOffset(src, base, offset - kHeapObjectTag);
   }
-  void StoreQToOffset(
-      VRegister src, Register base, int32_t offset, Register pp);
-  void StoreQFieldToOffset(
-      VRegister src, Register base, int32_t offset, Register pp) {
-    StoreQToOffset(src, base, offset - kHeapObjectTag, pp);
+  void StoreQToOffset(VRegister src, Register base, int32_t offset);
+  void StoreQFieldToOffset(VRegister src, Register base, int32_t offset) {
+    StoreQToOffset(src, base, offset - kHeapObjectTag);
   }
 
   // Storing into an object.
@@ -1281,62 +1282,59 @@
   void StoreIntoObjectOffset(Register object,
                              int32_t offset,
                              Register value,
-                             Register pp,
                              bool can_value_be_smi = true);
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 Register value);
   void StoreIntoObjectOffsetNoBarrier(Register object,
                                       int32_t offset,
-                                      Register value,
-                                      Register pp);
+                                      Register value);
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 const Object& value);
   void StoreIntoObjectOffsetNoBarrier(Register object,
                                       int32_t offset,
-                                      const Object& value,
-                                      Register pp);
+                                      const Object& value);
 
   // Object pool, loading from pool, etc.
-  void LoadPoolPointer(Register pp);
+  void LoadPoolPointer(Register pp = PP);
 
-  bool allow_constant_pool() const {
-    return allow_constant_pool_;
+  bool constant_pool_allowed() const {
+    return constant_pool_allowed_;
   }
-  void set_allow_constant_pool(bool b) {
-    allow_constant_pool_ = b;
+  void set_constant_pool_allowed(bool b) {
+    constant_pool_allowed_ = b;
   }
 
-  void LoadWordFromPoolOffset(Register dst, Register pp, uint32_t offset);
-  void LoadWordFromPoolOffsetFixed(Register dst, Register pp, uint32_t offset);
+  void LoadWordFromPoolOffset(Register dst, uint32_t offset);
+  void LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset);
   intptr_t FindImmediate(int64_t imm);
   bool CanLoadFromObjectPool(const Object& object) const;
-  bool CanLoadImmediateFromPool(int64_t imm, Register pp);
-  void LoadExternalLabel(Register dst, const ExternalLabel* label,
-                         Patchability patchable, Register pp);
+  void LoadExternalLabel(Register dst, const ExternalLabel* label);
   void LoadExternalLabelFixed(Register dst,
                               const ExternalLabel* label,
-                              Patchability patchable,
-                              Register pp);
+                              Patchability patchable);
+  void LoadFunctionFromCalleePool(Register dst,
+                                  const Function& function,
+                                  Register new_pp);
   void LoadIsolate(Register dst);
-  void LoadObject(Register dst, const Object& obj, Register pp);
-  void LoadUniqueObject(Register dst, const Object& obj, Register pp);
-  void LoadDecodableImmediate(Register reg, int64_t imm, Register pp);
+  void LoadObject(Register dst, const Object& obj);
+  void LoadUniqueObject(Register dst, const Object& obj);
+  void LoadDecodableImmediate(Register reg, int64_t imm);
   void LoadImmediateFixed(Register reg, int64_t imm);
-  void LoadImmediate(Register reg, int64_t imm, Register pp);
-  void LoadDImmediate(VRegister reg, double immd, Register pp);
+  void LoadImmediate(Register reg, int64_t imm);
+  void LoadDImmediate(VRegister reg, double immd);
 
-  void PushObject(const Object& object, Register pp) {
-    LoadObject(TMP, object, pp);
+  void PushObject(const Object& object) {
+    LoadObject(TMP, object);
     Push(TMP);
   }
-  void CompareObject(Register reg, const Object& object, Register pp);
+  void CompareObject(Register reg, const Object& object);
 
-  void LoadClassId(Register result, Register object, Register pp);
-  void LoadClassById(Register result, Register class_id, Register pp);
-  void LoadClass(Register result, Register object, Register pp);
-  void CompareClassId(Register object, intptr_t class_id, Register pp);
+  void LoadClassId(Register result, Register object);
+  void LoadClassById(Register result, Register class_id);
+  void LoadClass(Register result, Register object);
+  void CompareClassId(Register object, intptr_t class_id);
   void LoadClassIdMayBeSmi(Register result, Register object);
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
 
@@ -1379,13 +1377,11 @@
   void LeaveStubFrame();
 
   void UpdateAllocationStats(intptr_t cid,
-                             Register pp,
                              Heap::Space space,
                              bool inline_isolate = true);
 
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      Register size_reg,
-                                     Register pp,
                                      Heap::Space space,
                                      bool inline_isolate = true);
 
@@ -1393,8 +1389,8 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
-                            Register pp,
-                            Label* trace);
+                            Label* trace,
+                            bool inline_isolate = true);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
@@ -1403,8 +1399,7 @@
   void TryAllocate(const Class& cls,
                    Label* failure,
                    Register instance_reg,
-                   Register temp_reg,
-                   Register pp);
+                   Register temp_reg);
 
   void TryAllocateArray(intptr_t cid,
                         intptr_t instance_size,
@@ -1452,12 +1447,9 @@
 
   GrowableArray<CodeComment*> comments_;
 
-  bool allow_constant_pool_;
+  bool constant_pool_allowed_;
 
-  void LoadObjectHelper(Register dst,
-                        const Object& obj,
-                        Register pp,
-                        bool is_unique);
+  void LoadObjectHelper(Register dst, const Object& obj, bool is_unique);
 
   void AddSubHelper(OperandSize os, bool set_flags, bool subtract,
                     Register rd, Register rn, Operand o) {
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index 28749b3..6fb9822 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -287,9 +287,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(AddCarryInOut, assembler) {
-  __ LoadImmediate(R2, -1, kNoPP);
-  __ LoadImmediate(R1, 1, kNoPP);
-  __ LoadImmediate(R0, 0, kNoPP);
+  __ LoadImmediate(R2, -1);
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R0, 0);
   __ adds(IP0, R2, Operand(R1));  // c_out = 1.
   __ adcs(IP0, R2, R0);  // c_in = 1, c_out = 1.
   __ adc(R0, R0, R0);  // c_in = 1.
@@ -304,8 +304,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(SubCarryInOut, assembler) {
-  __ LoadImmediate(R1, 1, kNoPP);
-  __ LoadImmediate(R0, 0, kNoPP);
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R0, 0);
   __ subs(IP0, R0, Operand(R1));  // c_out = 1.
   __ sbcs(IP0, R0, R0);  // c_in = 1, c_out = 1.
   __ sbc(R0, R0, R0);  // c_in = 1.
@@ -320,10 +320,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(Overflow, assembler) {
-  __ LoadImmediate(R0, 0, kNoPP);
-  __ LoadImmediate(R1, 1, kNoPP);
-  __ LoadImmediate(R2, 0xFFFFFFFFFFFFFFFF, kNoPP);
-  __ LoadImmediate(R3, 0x7FFFFFFFFFFFFFFF, kNoPP);
+  __ LoadImmediate(R0, 0);
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R2, 0xFFFFFFFFFFFFFFFF);
+  __ LoadImmediate(R3, 0x7FFFFFFFFFFFFFFF);
   __ adds(IP0, R2, Operand(R1));  // c_out = 1.
   __ adcs(IP0, R3, R0);  // c_in = 1, c_out = 1, v = 1.
   __ csinc(R0, R0, R0, VS);  // R0 = v ? R0 : R0 + 1.
@@ -338,9 +338,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(WordAddCarryInOut, assembler) {
-  __ LoadImmediate(R2, -1, kNoPP);
-  __ LoadImmediate(R1, 1, kNoPP);
-  __ LoadImmediate(R0, 0, kNoPP);
+  __ LoadImmediate(R2, -1);
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R0, 0);
   __ addsw(IP0, R2, Operand(R1));  // c_out = 1.
   __ adcsw(IP0, R2, R0);  // c_in = 1, c_out = 1.
   __ adcw(R0, R0, R0);  // c_in = 1.
@@ -355,8 +355,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(WordSubCarryInOut, assembler) {
-  __ LoadImmediate(R1, 1, kNoPP);
-  __ LoadImmediate(R0, 0, kNoPP);
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R0, 0);
   __ subsw(IP0, R0, Operand(R1));  // c_out = 1.
   __ sbcsw(IP0, R0, R0);  // c_in = 1, c_out = 1.
   __ sbcw(R0, R0, R0);  // c_in = 1.
@@ -371,10 +371,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(WordOverflow, assembler) {
-  __ LoadImmediate(R0, 0, kNoPP);
-  __ LoadImmediate(R1, 1, kNoPP);
-  __ LoadImmediate(R2, 0xFFFFFFFF, kNoPP);
-  __ LoadImmediate(R3, 0x7FFFFFFF, kNoPP);
+  __ LoadImmediate(R0, 0);
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R2, 0xFFFFFFFF);
+  __ LoadImmediate(R3, 0x7FFFFFFF);
   __ addsw(IP0, R2, Operand(R1));  // c_out = 1.
   __ adcsw(IP0, R3, R0);  // c_in = 1, c_out = 1, v = 1.
   __ csinc(R0, R0, R0, VS);  // R0 = v ? R0 : R0 + 1.
@@ -510,7 +510,7 @@
 
 ASSEMBLER_TEST_GENERATE(LoadSigned32Bit, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadImmediate(R1, 0xffffffff, kNoPP);
+  __ LoadImmediate(R1, 0xffffffff);
   __ str(R1, Address(SP, -4, Address::PreIndex, kWord), kWord);
   __ ldr(R0, Address(SP), kWord);
   __ ldr(R1, Address(SP, 4, Address::PostIndex, kWord), kWord);
@@ -527,8 +527,8 @@
 
 ASSEMBLER_TEST_GENERATE(SimpleLoadStorePair, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadImmediate(R2, 43, kNoPP);
-  __ LoadImmediate(R3, 42, kNoPP);
+  __ LoadImmediate(R2, 43);
+  __ LoadImmediate(R3, 42);
   __ stp(R2, R3, Address(SP, -2*kWordSize, Address::PairPreIndex));
   __ ldp(R0, R1, Address(SP, 2*kWordSize, Address::PairPostIndex));
   __ sub(R0, R0, Operand(R1));
@@ -545,8 +545,8 @@
 
 ASSEMBLER_TEST_GENERATE(LoadStorePairOffset, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadImmediate(R2, 43, kNoPP);
-  __ LoadImmediate(R3, 42, kNoPP);
+  __ LoadImmediate(R2, 43);
+  __ LoadImmediate(R3, 42);
   __ sub(SP, SP, Operand(4 * kWordSize));
   __ stp(R2, R3, Address::Pair(SP, 2 * kWordSize));
   __ ldp(R0, R1, Address::Pair(SP, 2 * kWordSize));
@@ -729,11 +729,11 @@
   __ clz(R1, ZR);
   __ cmp(R1, Operand(64));
   __ b(&error, NE);
-  __ LoadImmediate(R2, 42, kNoPP);
+  __ LoadImmediate(R2, 42);
   __ clz(R2, R2);
   __ cmp(R2, Operand(58));
   __ b(&error, NE);
-  __ LoadImmediate(R0, -1, kNoPP);
+  __ LoadImmediate(R0, -1);
   __ clz(R1, R0);
   __ cmp(R1, Operand(0));
   __ b(&error, NE);
@@ -744,7 +744,7 @@
   __ mov(R0, ZR);
   __ ret();
   __ Bind(&error);
-  __ LoadImmediate(R0, 1, kNoPP);
+  __ LoadImmediate(R0, 1);
   __ ret();
 }
 
@@ -998,13 +998,13 @@
 ASSEMBLER_TEST_GENERATE(FcmpEqBranch, assembler) {
   Label l;
 
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, 234.0, kNoPP);
-  __ LoadDImmediate(V2, 234.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, 234.0);
+  __ LoadDImmediate(V2, 234.0);
 
   __ fcmpd(V1, V2);
   __ b(&l, EQ);
-  __ LoadDImmediate(V0, 0.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
   __ Bind(&l);
   __ ret();
 }
@@ -1019,13 +1019,13 @@
 ASSEMBLER_TEST_GENERATE(FcmpEqBranchNotTaken, assembler) {
   Label l;
 
-  __ LoadDImmediate(V0, 0.0, kNoPP);
-  __ LoadDImmediate(V1, 233.0, kNoPP);
-  __ LoadDImmediate(V2, 234.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
+  __ LoadDImmediate(V1, 233.0);
+  __ LoadDImmediate(V2, 234.0);
 
   __ fcmpd(V1, V2);
   __ b(&l, EQ);
-  __ LoadDImmediate(V0, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
   __ Bind(&l);
   __ ret();
 }
@@ -1040,13 +1040,13 @@
 ASSEMBLER_TEST_GENERATE(FcmpLtBranch, assembler) {
   Label l;
 
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, 233.0, kNoPP);
-  __ LoadDImmediate(V2, 234.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, 233.0);
+  __ LoadDImmediate(V2, 234.0);
 
   __ fcmpd(V1, V2);
   __ b(&l, LT);
-  __ LoadDImmediate(V0, 0.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
   __ Bind(&l);
   __ ret();
 }
@@ -1061,13 +1061,13 @@
 ASSEMBLER_TEST_GENERATE(FcmpLtBranchNotTaken, assembler) {
   Label l;
 
-  __ LoadDImmediate(V0, 0.0, kNoPP);
-  __ LoadDImmediate(V1, 235.0, kNoPP);
-  __ LoadDImmediate(V2, 234.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
+  __ LoadDImmediate(V1, 235.0);
+  __ LoadDImmediate(V2, 234.0);
 
   __ fcmpd(V1, V2);
   __ b(&l, LT);
-  __ LoadDImmediate(V0, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
   __ Bind(&l);
   __ ret();
 }
@@ -1082,15 +1082,15 @@
 ASSEMBLER_TEST_GENERATE(FcmpzGtBranch, assembler) {
   Label l;
 
-  __ LoadDImmediate(V0, 235.0, kNoPP);
-  __ LoadDImmediate(V1, 233.0, kNoPP);
+  __ LoadDImmediate(V0, 235.0);
+  __ LoadDImmediate(V1, 233.0);
 
   __ fcmpdz(V1);
   __ b(&l, GT);
-  __ LoadDImmediate(V0, 0.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
   __ ret();
   __ Bind(&l);
-  __ LoadDImmediate(V0, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
   __ ret();
 }
 
@@ -1513,7 +1513,7 @@
 
 // Loading immediate values without the object pool.
 ASSEMBLER_TEST_GENERATE(LoadImmediateSmall, assembler) {
-  __ LoadImmediate(R0, 42, kNoRegister);
+  __ LoadImmediate(R0, 42);
   __ ret();
 }
 
@@ -1525,7 +1525,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateMed, assembler) {
-  __ LoadImmediate(R0, 0xf1234123, kNoRegister);
+  __ LoadImmediate(R0, 0xf1234123);
   __ ret();
 }
 
@@ -1537,7 +1537,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateMed2, assembler) {
-  __ LoadImmediate(R0, 0x4321f1234123, kNoRegister);
+  __ LoadImmediate(R0, 0x4321f1234123);
   __ ret();
 }
 
@@ -1550,7 +1550,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateLarge, assembler) {
-  __ LoadImmediate(R0, 0x9287436598237465, kNoRegister);
+  __ LoadImmediate(R0, 0x9287436598237465);
   __ ret();
 }
 
@@ -1563,7 +1563,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateSmallNeg, assembler) {
-  __ LoadImmediate(R0, -42, kNoRegister);
+  __ LoadImmediate(R0, -42);
   __ ret();
 }
 
@@ -1575,7 +1575,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg, assembler) {
-  __ LoadImmediate(R0, -0x1212341234, kNoRegister);
+  __ LoadImmediate(R0, -0x1212341234);
   __ ret();
 }
 
@@ -1587,7 +1587,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg2, assembler) {
-  __ LoadImmediate(R0, -0x1212340000, kNoRegister);
+  __ LoadImmediate(R0, -0x1212340000);
   __ ret();
 }
 
@@ -1599,7 +1599,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg3, assembler) {
-  __ LoadImmediate(R0, -0x1200001234, kNoRegister);
+  __ LoadImmediate(R0, -0x1200001234);
   __ ret();
 }
 
@@ -1611,7 +1611,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediateMedNeg4, assembler) {
-  __ LoadImmediate(R0, -0x12341234, kNoRegister);
+  __ LoadImmediate(R0, -0x12341234);
   __ ret();
 }
 
@@ -1626,8 +1626,8 @@
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPSmall, assembler) {
   __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadImmediate(R0, 42, PP);
+  __ LoadPoolPointer();
+  __ LoadImmediate(R0, 42);
   __ PopAndUntagPP();
   __ mov(CSP, SP);
   __ ret();
@@ -1643,8 +1643,8 @@
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPMed, assembler) {
   __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadImmediate(R0, 0xf1234123, PP);
+  __ LoadPoolPointer();
+  __ LoadImmediate(R0, 0xf1234123);
   __ PopAndUntagPP();
   __ mov(CSP, SP);
   __ ret();
@@ -1660,8 +1660,8 @@
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPMed2, assembler) {
   __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadImmediate(R0, 0x4321f1234124, PP);
+  __ LoadPoolPointer();
+  __ LoadImmediate(R0, 0x4321f1234124);
   __ PopAndUntagPP();
   __ mov(CSP, SP);
   __ ret();
@@ -1678,8 +1678,8 @@
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPLarge, assembler) {
   __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadImmediate(R0, 0x9287436598237465, PP);
+  __ LoadPoolPointer();
+  __ LoadImmediate(R0, 0x9287436598237465);
   __ PopAndUntagPP();
   __ mov(CSP, SP);
   __ ret();
@@ -1713,8 +1713,8 @@
   __ Push(THR);
   __ mov(THR, R0);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadObject(R0, Object::null_object(), PP);
+  __ LoadPoolPointer();
+  __ LoadObject(R0, Object::null_object());
   __ PopAndUntagPP();
   __ Pop(THR);
   __ mov(CSP, SP);
@@ -1733,8 +1733,8 @@
   __ Push(THR);
   __ mov(THR, R0);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadObject(R0, Bool::True(), PP);
+  __ LoadPoolPointer();
+  __ LoadObject(R0, Bool::True());
   __ PopAndUntagPP();
   __ Pop(THR);
   __ mov(CSP, SP);
@@ -1753,8 +1753,8 @@
   __ Push(THR);
   __ mov(THR, R0);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadObject(R0, Bool::False(), PP);
+  __ LoadPoolPointer();
+  __ LoadObject(R0, Bool::False());
   __ PopAndUntagPP();
   __ Pop(THR);
   __ mov(CSP, SP);
@@ -1769,8 +1769,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(CSelTrue, assembler) {
-  __ LoadImmediate(R1, 42, kNoRegister);
-  __ LoadImmediate(R2, 1234, kNoRegister);
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 1234);
   __ CompareRegisters(R1, R2);
   __ csel(R0, R1, R2, LT);
   __ ret();
@@ -1784,8 +1784,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(CSelFalse, assembler) {
-  __ LoadImmediate(R1, 42, kNoRegister);
-  __ LoadImmediate(R2, 1234, kNoRegister);
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 1234);
   __ CompareRegisters(R1, R2);
   __ csel(R0, R1, R2, GE);
   __ ret();
@@ -1799,8 +1799,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(CsincFalse, assembler) {
-  __ LoadImmediate(R1, 42, kNoRegister);
-  __ LoadImmediate(R2, 1234, kNoRegister);
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 1234);
   __ CompareRegisters(R1, R2);
   __ csinc(R0, R2, R1, GE);
   __ ret();
@@ -1814,8 +1814,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(CsincTrue, assembler) {
-  __ LoadImmediate(R1, 42, kNoRegister);
-  __ LoadImmediate(R2, 1234, kNoRegister);
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 1234);
   __ CompareRegisters(R1, R2);
   __ csinc(R0, R2, R1, LT);
   __ ret();
@@ -1829,8 +1829,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(CsinvFalse, assembler) {
-  __ LoadImmediate(R1, 42, kNoRegister);
-  __ LoadImmediate(R2, 1234, kNoRegister);
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 1234);
   __ CompareRegisters(R1, R2);
   __ csinv(R0, R2, R1, GE);
   __ ret();
@@ -1844,8 +1844,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(CsinvTrue, assembler) {
-  __ LoadImmediate(R1, 42, kNoRegister);
-  __ LoadImmediate(R2, 1234, kNoRegister);
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 1234);
   __ CompareRegisters(R1, R2);
   __ csinv(R0, R2, R1, LT);
   __ ret();
@@ -1860,7 +1860,7 @@
 
 // Floating point move immediate, to/from integer register.
 ASSEMBLER_TEST_GENERATE(Fmovdi, assembler) {
-  __ LoadDImmediate(V0, 1.0, kNoPP);
+  __ LoadDImmediate(V0, 1.0);
   __ ret();
 }
 
@@ -1872,7 +1872,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fmovdi2, assembler) {
-  __ LoadDImmediate(V0, 123412983.1324524315, kNoPP);
+  __ LoadDImmediate(V0, 123412983.1324524315);
   __ ret();
 }
 
@@ -1885,7 +1885,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fmovrd, assembler) {
-  __ LoadDImmediate(V1, 1.0, kNoPP);
+  __ LoadDImmediate(V1, 1.0);
   __ fmovrd(R0, V1);
   __ ret();
 }
@@ -1899,7 +1899,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fmovdr, assembler) {
-  __ LoadDImmediate(V1, 1.0, kNoPP);
+  __ LoadDImmediate(V1, 1.0);
   __ fmovrd(R1, V1);
   __ fmovdr(V0, R1);
   __ ret();
@@ -1914,7 +1914,7 @@
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdPrePostIndex, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V1, 42.0);
   __ fstrd(V1, Address(SP, -1*kWordSize, Address::PreIndex));
   __ fldrd(V0, Address(SP, 1*kWordSize, Address::PostIndex));
   __ mov(CSP, SP);
@@ -1930,7 +1930,7 @@
 
 ASSEMBLER_TEST_GENERATE(FldrsFstrsPrePostIndex, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V1, 42.0);
   __ fcvtsd(V2, V1);
   __ fstrs(V2, Address(SP, -1*kWordSize, Address::PreIndex));
   __ fldrs(V3, Address(SP, 1*kWordSize, Address::PostIndex));
@@ -1948,9 +1948,9 @@
 
 ASSEMBLER_TEST_GENERATE(FldrqFstrqPrePostIndex, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V1, 21.0, kNoPP);
-  __ LoadDImmediate(V2, 21.0, kNoPP);
-  __ LoadImmediate(R1, 42, kNoPP);
+  __ LoadDImmediate(V1, 21.0);
+  __ LoadDImmediate(V2, 21.0);
+  __ LoadImmediate(R1, 42);
   __ Push(R1);
   __ PushDouble(V1);
   __ PushDouble(V2);
@@ -1972,7 +1972,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fcvtzds, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
   __ fcvtzds(R0, V0);
   __ ret();
 }
@@ -1985,7 +1985,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Scvtfdx, assembler) {
-  __ LoadImmediate(R0, 42, kNoPP);
+  __ LoadImmediate(R0, 42);
   __ scvtfdx(V0, R0);
   __ ret();
 }
@@ -1999,7 +1999,7 @@
 
 ASSEMBLER_TEST_GENERATE(Scvtfdw, assembler) {
   // Fill upper 32-bits with garbage.
-  __ LoadImmediate(R0, 0x111111110000002A, kNoPP);
+  __ LoadImmediate(R0, 0x111111110000002A);
   __ scvtfdw(V0, R0);
   __ ret();
 }
@@ -2012,7 +2012,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(FabsdPos, assembler) {
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V1, 42.0);
   __ fabsd(V0, V1);
   __ ret();
 }
@@ -2025,7 +2025,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(FabsdNeg, assembler) {
-  __ LoadDImmediate(V1, -42.0, kNoPP);
+  __ LoadDImmediate(V1, -42.0);
   __ fabsd(V0, V1);
   __ ret();
 }
@@ -2038,7 +2038,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(FnegdPos, assembler) {
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V1, 42.0);
   __ fnegd(V0, V1);
   __ ret();
 }
@@ -2051,7 +2051,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(FnegdNeg, assembler) {
-  __ LoadDImmediate(V1, -42.0, kNoPP);
+  __ LoadDImmediate(V1, -42.0);
   __ fnegd(V0, V1);
   __ ret();
 }
@@ -2064,7 +2064,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fsqrtd, assembler) {
-  __ LoadDImmediate(V1, 64.0, kNoPP);
+  __ LoadDImmediate(V1, 64.0);
   __ fsqrtd(V0, V1);
   __ ret();
 }
@@ -2077,8 +2077,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fmuld, assembler) {
-  __ LoadDImmediate(V1, 84.0, kNoPP);
-  __ LoadDImmediate(V2, 0.5, kNoPP);
+  __ LoadDImmediate(V1, 84.0);
+  __ LoadDImmediate(V2, 0.5);
   __ fmuld(V0, V1, V2);
   __ ret();
 }
@@ -2091,8 +2091,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fdivd, assembler) {
-  __ LoadDImmediate(V1, 84.0, kNoPP);
-  __ LoadDImmediate(V2, 2.0, kNoPP);
+  __ LoadDImmediate(V1, 84.0);
+  __ LoadDImmediate(V2, 2.0);
   __ fdivd(V0, V1, V2);
   __ ret();
 }
@@ -2105,8 +2105,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Faddd, assembler) {
-  __ LoadDImmediate(V1, 41.5, kNoPP);
-  __ LoadDImmediate(V2, 0.5, kNoPP);
+  __ LoadDImmediate(V1, 41.5);
+  __ LoadDImmediate(V2, 0.5);
   __ faddd(V0, V1, V2);
   __ ret();
 }
@@ -2119,8 +2119,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Fsubd, assembler) {
-  __ LoadDImmediate(V1, 42.5, kNoPP);
-  __ LoadDImmediate(V2, 0.5, kNoPP);
+  __ LoadDImmediate(V1, 42.5);
+  __ LoadDImmediate(V2, 0.5);
   __ fsubd(V0, V1, V2);
   __ ret();
 }
@@ -2134,13 +2134,13 @@
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdHeapTag, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 43.0, kNoPP);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
-  __ AddImmediate(SP, SP, -1 * kWordSize, kNoPP);
+  __ LoadDImmediate(V0, 43.0);
+  __ LoadDImmediate(V1, 42.0);
+  __ AddImmediate(SP, SP, -1 * kWordSize);
   __ add(R2, SP, Operand(1));
   __ fstrd(V1, Address(R2, -1));
   __ fldrd(V0, Address(R2, -1));
-  __ AddImmediate(SP, SP, 1 * kWordSize, kNoPP);
+  __ AddImmediate(SP, SP, 1 * kWordSize);
   __ mov(CSP, SP);
   __ ret();
 }
@@ -2154,8 +2154,8 @@
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdLargeIndex, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 43.0, kNoPP);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 43.0);
+  __ LoadDImmediate(V1, 42.0);
   // Largest negative offset that can fit in the signed 9-bit immediate field.
   __ fstrd(V1, Address(SP, -32*kWordSize, Address::PreIndex));
   // Largest positive kWordSize aligned offset that we can fit.
@@ -2175,8 +2175,8 @@
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdLargeOffset, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 43.0, kNoPP);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 43.0);
+  __ LoadDImmediate(V1, 42.0);
   __ sub(SP, SP, Operand(512*kWordSize));
   __ fstrd(V1, Address(SP, 512*kWordSize, Address::Offset));
   __ add(SP, SP, Operand(512*kWordSize));
@@ -2194,8 +2194,8 @@
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdExtReg, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 43.0, kNoPP);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 43.0);
+  __ LoadDImmediate(V1, 42.0);
   __ movz(R2, Immediate(0xfff8), 0);
   __ movk(R2, Immediate(0xffff), 1);  // R2 <- -8 (int32_t).
   // This should sign extend R2, and add to SP to get address,
@@ -2217,8 +2217,8 @@
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdScaledReg, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 43.0, kNoPP);
-  __ LoadDImmediate(V1, 42.0, kNoPP);
+  __ LoadDImmediate(V0, 43.0);
+  __ LoadDImmediate(V1, 42.0);
   __ movz(R2, Immediate(10), 0);
   __ sub(SP, SP, Operand(10*kWordSize));
   // Store V1 into SP + R2 * kWordSize.
@@ -2237,10 +2237,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(VinswVmovrs, assembler) {
-  __ LoadImmediate(R0, 42, kNoPP);
-  __ LoadImmediate(R1, 43, kNoPP);
-  __ LoadImmediate(R2, 44, kNoPP);
-  __ LoadImmediate(R3, 45, kNoPP);
+  __ LoadImmediate(R0, 42);
+  __ LoadImmediate(R1, 43);
+  __ LoadImmediate(R2, 44);
+  __ LoadImmediate(R3, 45);
 
   __ vinsw(V0, 0, R0);
   __ vinsw(V0, 1, R1);
@@ -2267,8 +2267,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(VinsxVmovrd, assembler) {
-  __ LoadImmediate(R0, 42, kNoPP);
-  __ LoadImmediate(R1, 43, kNoPP);
+  __ LoadImmediate(R0, 42);
+  __ LoadImmediate(R1, 43);
 
   __ vinsx(V0, 0, R0);
   __ vinsx(V0, 1, R1);
@@ -2289,8 +2289,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vnot, assembler) {
-  __ LoadImmediate(R0, 0xfffffffe, kNoPP);
-  __ LoadImmediate(R1, 0xffffffff, kNoPP);
+  __ LoadImmediate(R0, 0xfffffffe);
+  __ LoadImmediate(R1, 0xffffffff);
   __ vinsw(V1, 0, R1);
   __ vinsw(V1, 1, R0);
   __ vinsw(V1, 2, R1);
@@ -2317,8 +2317,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vabss, assembler) {
-  __ LoadDImmediate(V1, 21.0, kNoPP);
-  __ LoadDImmediate(V2, -21.0, kNoPP);
+  __ LoadDImmediate(V1, 21.0);
+  __ LoadDImmediate(V2, -21.0);
 
   __ fcvtsd(V1, V1);
   __ fcvtsd(V2, V2);
@@ -2347,8 +2347,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vabsd, assembler) {
-  __ LoadDImmediate(V1, 21.0, kNoPP);
-  __ LoadDImmediate(V2, -21.0, kNoPP);
+  __ LoadDImmediate(V1, 21.0);
+  __ LoadDImmediate(V2, -21.0);
 
   __ vinsd(V3, 0, V1, 0);
   __ vinsd(V3, 1, V2, 0);
@@ -2370,8 +2370,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vnegs, assembler) {
-  __ LoadDImmediate(V1, 42.0, kNoPP);
-  __ LoadDImmediate(V2, -84.0, kNoPP);
+  __ LoadDImmediate(V1, 42.0);
+  __ LoadDImmediate(V2, -84.0);
 
   __ fcvtsd(V1, V1);
   __ fcvtsd(V2, V2);
@@ -2399,8 +2399,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vnegd, assembler) {
-  __ LoadDImmediate(V1, 42.0, kNoPP);
-  __ LoadDImmediate(V2, -84.0, kNoPP);
+  __ LoadDImmediate(V1, 42.0);
+  __ LoadDImmediate(V2, -84.0);
 
   __ vinsd(V3, 0, V1, 0);
   __ vinsd(V3, 1, V2, 0);
@@ -2422,10 +2422,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vadds, assembler) {
-  __ LoadDImmediate(V0, 0.0, kNoPP);
-  __ LoadDImmediate(V1, 1.0, kNoPP);
-  __ LoadDImmediate(V2, 2.0, kNoPP);
-  __ LoadDImmediate(V3, 3.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
+  __ LoadDImmediate(V1, 1.0);
+  __ LoadDImmediate(V2, 2.0);
+  __ LoadDImmediate(V3, 3.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -2463,11 +2463,11 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vsubs, assembler) {
-  __ LoadDImmediate(V0, 0.0, kNoPP);
-  __ LoadDImmediate(V1, 1.0, kNoPP);
-  __ LoadDImmediate(V2, 2.0, kNoPP);
-  __ LoadDImmediate(V3, 3.0, kNoPP);
-  __ LoadDImmediate(V5, 0.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
+  __ LoadDImmediate(V1, 1.0);
+  __ LoadDImmediate(V2, 2.0);
+  __ LoadDImmediate(V3, 3.0);
+  __ LoadDImmediate(V5, 0.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -2505,10 +2505,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vmuls, assembler) {
-  __ LoadDImmediate(V0, 0.0, kNoPP);
-  __ LoadDImmediate(V1, 1.0, kNoPP);
-  __ LoadDImmediate(V2, 2.0, kNoPP);
-  __ LoadDImmediate(V3, 3.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
+  __ LoadDImmediate(V1, 1.0);
+  __ LoadDImmediate(V2, 2.0);
+  __ LoadDImmediate(V3, 3.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -2546,10 +2546,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vdivs, assembler) {
-  __ LoadDImmediate(V0, 0.0, kNoPP);
-  __ LoadDImmediate(V1, 1.0, kNoPP);
-  __ LoadDImmediate(V2, 2.0, kNoPP);
-  __ LoadDImmediate(V3, 3.0, kNoPP);
+  __ LoadDImmediate(V0, 0.0);
+  __ LoadDImmediate(V1, 1.0);
+  __ LoadDImmediate(V2, 2.0);
+  __ LoadDImmediate(V3, 3.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -2587,8 +2587,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vaddd, assembler) {
-  __ LoadDImmediate(V0, 2.0, kNoPP);
-  __ LoadDImmediate(V1, 3.0, kNoPP);
+  __ LoadDImmediate(V0, 2.0);
+  __ LoadDImmediate(V1, 3.0);
 
   __ vinsd(V4, 0, V0, 0);
   __ vinsd(V4, 1, V1, 0);
@@ -2610,9 +2610,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vsubd, assembler) {
-  __ LoadDImmediate(V0, 2.0, kNoPP);
-  __ LoadDImmediate(V1, 3.0, kNoPP);
-  __ LoadDImmediate(V5, 0.0, kNoPP);
+  __ LoadDImmediate(V0, 2.0);
+  __ LoadDImmediate(V1, 3.0);
+  __ LoadDImmediate(V5, 0.0);
 
   __ vinsd(V4, 0, V0, 0);
   __ vinsd(V4, 1, V1, 0);
@@ -2634,8 +2634,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vmuld, assembler) {
-  __ LoadDImmediate(V0, 2.0, kNoPP);
-  __ LoadDImmediate(V1, 3.0, kNoPP);
+  __ LoadDImmediate(V0, 2.0);
+  __ LoadDImmediate(V1, 3.0);
 
   __ vinsd(V4, 0, V0, 0);
   __ vinsd(V4, 1, V1, 0);
@@ -2657,8 +2657,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vdivd, assembler) {
-  __ LoadDImmediate(V0, 2.0, kNoPP);
-  __ LoadDImmediate(V1, 3.0, kNoPP);
+  __ LoadDImmediate(V0, 2.0);
+  __ LoadDImmediate(V1, 3.0);
 
   __ vinsd(V4, 0, V0, 0);
   __ vinsd(V4, 1, V1, 0);
@@ -2681,7 +2681,7 @@
 
 ASSEMBLER_TEST_GENERATE(Vdupd, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 21.0, kNoPP);
+  __ LoadDImmediate(V0, 21.0);
   __ vdupd(V1, V0, 0);
 
   const int dword_bytes = 1 << Log2OperandSizeBytes(kDWord);
@@ -2705,7 +2705,7 @@
 
 ASSEMBLER_TEST_GENERATE(Vdups, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 21.0, kNoPP);
+  __ LoadDImmediate(V0, 21.0);
   __ fcvtsd(V0, V0);
   __ vdups(V1, V0, 0);
 
@@ -2739,7 +2739,7 @@
 
 ASSEMBLER_TEST_GENERATE(Vinsd, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V5, 42.0, kNoPP);
+  __ LoadDImmediate(V5, 42.0);
   __ vinsd(V1, 1, V5, 0);  // V1[1] <- V0[0].
 
   const int dword_bytes = 1 << Log2OperandSizeBytes(kDWord);
@@ -2763,7 +2763,7 @@
 
 ASSEMBLER_TEST_GENERATE(Vinss, assembler) {
   __ SetupDartSP(kTestStackSpace);
-  __ LoadDImmediate(V0, 21.0, kNoPP);
+  __ LoadDImmediate(V0, 21.0);
   __ fcvtsd(V0, V0);
   __ vinss(V1, 3, V0, 0);
   __ vinss(V1, 1, V0, 0);
@@ -2797,8 +2797,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vand, assembler) {
-  __ LoadDImmediate(V1, 21.0, kNoPP);
-  __ LoadImmediate(R0, 0xffffffff, kNoPP);
+  __ LoadDImmediate(V1, 21.0);
+  __ LoadImmediate(R0, 0xffffffff);
 
   // V0 <- (0, 0xffffffff, 0, 0xffffffff)
   __ fmovdr(V0, R0);
@@ -2834,7 +2834,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vorr, assembler) {
-  __ LoadDImmediate(V1, 10.5, kNoPP);
+  __ LoadDImmediate(V1, 10.5);
   __ fcvtsd(V1, V1);
 
   // V0 <- (0, 10.5, 0, 10.5)
@@ -2872,8 +2872,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Veor, assembler) {
-  __ LoadImmediate(R1, 0xffffffff, kNoPP);
-  __ LoadImmediate(R2, ~21, kNoPP);
+  __ LoadImmediate(R1, 0xffffffff);
+  __ LoadImmediate(R2, ~21);
 
   __ vinsw(V1, 0, R1);
   __ vinsw(V1, 1, R2);
@@ -2906,7 +2906,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vaddw, assembler) {
-  __ LoadImmediate(R4, 21, kNoPP);
+  __ LoadImmediate(R4, 21);
 
   __ vdupw(V1, R4);
   __ vdupw(V2, R4);
@@ -2931,8 +2931,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vsubw, assembler) {
-  __ LoadImmediate(R4, 31, kNoPP);
-  __ LoadImmediate(R5, 10, kNoPP);
+  __ LoadImmediate(R4, 31);
+  __ LoadImmediate(R5, 10);
 
   __ vdupw(V1, R4);
   __ vdupw(V2, R5);
@@ -2957,7 +2957,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vaddx, assembler) {
-  __ LoadImmediate(R4, 21, kNoPP);
+  __ LoadImmediate(R4, 21);
 
   __ vdupx(V1, R4);
   __ vdupx(V2, R4);
@@ -2978,8 +2978,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vsubx, assembler) {
-  __ LoadImmediate(R4, 31, kNoPP);
-  __ LoadImmediate(R5, 10, kNoPP);
+  __ LoadImmediate(R4, 31);
+  __ LoadImmediate(R5, 10);
 
   __ vdupx(V1, R4);
   __ vdupx(V2, R5);
@@ -3000,8 +3000,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vceqs, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, -42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, -42.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -3033,8 +3033,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vceqd, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, -42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, -42.0);
 
   __ vdupd(V2, V0, 0);
   __ vinsd(V3, 0, V0, 0);
@@ -3057,8 +3057,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vcgts, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, -42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, -42.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -3090,8 +3090,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vcgtd, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, -42.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, -42.0);
 
   __ vdupd(V2, V0, 0);
   __ vinsd(V3, 0, V0, 0);
@@ -3114,8 +3114,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vcges, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, 43.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, 43.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -3147,8 +3147,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vcged, assembler) {
-  __ LoadDImmediate(V0, 42.0, kNoPP);
-  __ LoadDImmediate(V1, 43.0, kNoPP);
+  __ LoadDImmediate(V0, 42.0);
+  __ LoadDImmediate(V1, 43.0);
 
   __ vdupd(V2, V0, 0);
   __ vinsd(V3, 0, V0, 0);
@@ -3171,8 +3171,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vmaxs, assembler) {
-  __ LoadDImmediate(V0, 10.5, kNoPP);
-  __ LoadDImmediate(V1, 10.0, kNoPP);
+  __ LoadDImmediate(V0, 10.5);
+  __ LoadDImmediate(V1, 10.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -3209,8 +3209,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vmaxd, assembler) {
-  __ LoadDImmediate(V0, 21.0, kNoPP);
-  __ LoadDImmediate(V1, 20.5, kNoPP);
+  __ LoadDImmediate(V0, 21.0);
+  __ LoadDImmediate(V1, 20.5);
 
   __ vdupd(V2, V0, 0);
   __ vinsd(V3, 0, V0, 0);
@@ -3233,8 +3233,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vmins, assembler) {
-  __ LoadDImmediate(V0, 10.5, kNoPP);
-  __ LoadDImmediate(V1, 11.0, kNoPP);
+  __ LoadDImmediate(V0, 10.5);
+  __ LoadDImmediate(V1, 11.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -3271,8 +3271,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vmind, assembler) {
-  __ LoadDImmediate(V0, 21.0, kNoPP);
-  __ LoadDImmediate(V1, 21.5, kNoPP);
+  __ LoadDImmediate(V0, 21.0);
+  __ LoadDImmediate(V1, 21.5);
 
   __ vdupd(V2, V0, 0);
   __ vinsd(V3, 0, V0, 0);
@@ -3295,8 +3295,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vsqrts, assembler) {
-  __ LoadDImmediate(V0, 64.0, kNoPP);
-  __ LoadDImmediate(V1, 49.0, kNoPP);
+  __ LoadDImmediate(V0, 64.0);
+  __ LoadDImmediate(V1, 49.0);
 
   __ fcvtsd(V0, V0);
   __ fcvtsd(V1, V1);
@@ -3325,8 +3325,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vsqrtd, assembler) {
-  __ LoadDImmediate(V0, 64.0, kNoPP);
-  __ LoadDImmediate(V1, 49.0, kNoPP);
+  __ LoadDImmediate(V0, 64.0);
+  __ LoadDImmediate(V1, 49.0);
 
   __ vinsd(V3, 0, V0, 0);
   __ vinsd(V3, 1, V1, 0);
@@ -3383,7 +3383,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vrecpes, assembler) {
-  __ LoadDImmediate(V1, 147.0, kNoPP);
+  __ LoadDImmediate(V1, 147.0);
   __ fcvtsd(V1, V1);
   __ vinss(V2, 0, V1, 0);
   __ vinss(V2, 1, V1, 0);
@@ -3404,8 +3404,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vrecpss, assembler) {
-  __ LoadDImmediate(V1, 5.0, kNoPP);
-  __ LoadDImmediate(V2, 10.0, kNoPP);
+  __ LoadDImmediate(V1, 5.0);
+  __ LoadDImmediate(V2, 10.0);
 
   __ fcvtsd(V1, V1);
   __ fcvtsd(V2, V2);
@@ -3426,7 +3426,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(VRecps, assembler) {
-  __ LoadDImmediate(V0, 1.0 / 10.5, kNoPP);
+  __ LoadDImmediate(V0, 1.0 / 10.5);
   __ fcvtsd(V0, V0);
 
   __ vdups(V1, V0, 0);
@@ -3509,7 +3509,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vrsqrtes, assembler) {
-  __ LoadDImmediate(V1, 147.0, kNoPP);
+  __ LoadDImmediate(V1, 147.0);
   __ fcvtsd(V1, V1);
 
   __ vrsqrtes(V0, V1);
@@ -3528,8 +3528,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Vrsqrtss, assembler) {
-    __ LoadDImmediate(V1, 5.0, kNoPP);
-    __ LoadDImmediate(V2, 10.0, kNoPP);
+    __ LoadDImmediate(V1, 5.0);
+    __ LoadDImmediate(V2, 10.0);
 
     __ fcvtsd(V1, V1);
     __ fcvtsd(V2, V2);
@@ -3550,7 +3550,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(ReciprocalSqrt, assembler) {
-    __ LoadDImmediate(V1, 147000.0, kNoPP);
+    __ LoadDImmediate(V1, 147000.0);
     __ fcvtsd(V1, V1);
 
     __ VRSqrts(V0, V1);
@@ -3577,7 +3577,7 @@
 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
   __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ Push(THR);
   __ Push(CTX);
   __ Push(LR);
@@ -3598,14 +3598,14 @@
 ASSEMBLER_TEST_GENERATE(ComputeRange, assembler) {
   __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   Label miss, done;
   __ mov(R1, R0);
   __ ComputeRange(R0, R1, R2, &miss);
   __ b(&done);
 
   __ Bind(&miss);
-  __ LoadImmediate(R0, -1, kNoPP);
+  __ LoadImmediate(R0, -1);
 
   __ Bind(&done);
   __ PopAndUntagPP();
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 8de5223..c6c8da8 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -2366,8 +2366,7 @@
   if (object != EDX) {
     movl(EDX, object);
   }
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  call(&stub_code->UpdateStoreBufferLabel());
+  Call(*StubCode::UpdateStoreBuffer_entry());
   if (value != EDX) {
     popl(EDX);  // Restore EDX.
   }
@@ -2622,6 +2621,24 @@
 }
 
 
+void Assembler::Call(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  call(&label);
+}
+
+
+void Assembler::Jmp(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  jmp(&label);
+}
+
+
+void Assembler::J(Condition condition, const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  j(condition, &label);
+}
+
+
 void Assembler::Align(intptr_t alignment, intptr_t offset) {
   ASSERT(Utils::IsPowerOfTwo(alignment));
   intptr_t pos = offset + buffer_.GetPosition();
@@ -2663,21 +2680,30 @@
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
                                      Label* trace,
-                                     bool near_jump) {
+                                     bool near_jump,
+                                     bool inline_isolate) {
   ASSERT(cid > 0);
   Address state_address(kNoRegister, 0);
-  intptr_t state_offset;
-  ClassTable* class_table = Isolate::Current()->class_table();
-  ClassHeapStats** table_ptr =
-      class_table->StateAddressFor(cid, &state_offset);
-  if (cid < kNumPredefinedCids) {
-    state_address = Address::Absolute(
-        reinterpret_cast<uword>(*table_ptr) + state_offset);
+  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
+  if (inline_isolate) {
+    ClassTable* class_table = Isolate::Current()->class_table();
+    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
+    if (cid < kNumPredefinedCids) {
+      state_address = Address::Absolute(
+          reinterpret_cast<uword>(*table_ptr) + state_offset);
+    } else {
+      ASSERT(temp_reg != kNoRegister);
+      // temp_reg gets address of class table pointer.
+      movl(temp_reg,
+           Address::Absolute(reinterpret_cast<uword>(table_ptr)));
+      state_address = Address(temp_reg, state_offset);
+    }
   } else {
     ASSERT(temp_reg != kNoRegister);
-    // temp_reg gets address of class table pointer.
-    movl(temp_reg,
-         Address::Absolute(reinterpret_cast<uword>(table_ptr)));
+    LoadIsolate(temp_reg);
+    intptr_t table_offset =
+        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+    movl(temp_reg, Address(temp_reg, table_offset));
     state_address = Address(temp_reg, state_offset);
   }
   testb(state_address, Immediate(ClassHeapStats::TraceAllocationMask()));
@@ -2763,23 +2789,26 @@
                             Register instance_reg,
                             Register temp_reg) {
   ASSERT(failure != NULL);
+  ASSERT(temp_reg != kNoRegister);
   if (FLAG_inline_alloc) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump);
-    Heap* heap = Isolate::Current()->heap();
+    MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump,
+                         /* inline_isolate = */ false);
     const intptr_t instance_size = cls.instance_size();
-    Heap::Space space = heap->SpaceForAllocation(cls.id());
-    movl(instance_reg, Address::Absolute(heap->TopAddress(space)));
+    Heap::Space space = Heap::SpaceForAllocation(cls.id());
+    movl(temp_reg, Address(THR, Thread::heap_offset()));
+    movl(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
     addl(instance_reg, Immediate(instance_size));
     // instance_reg: potential next object start.
-    cmpl(instance_reg, Address::Absolute(heap->EndAddress(space)));
+    cmpl(instance_reg, Address(temp_reg, Heap::EndOffset(space)));
     j(ABOVE_EQUAL, failure, near_jump);
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
-    movl(Address::Absolute(heap->TopAddress(space)), instance_reg);
-    UpdateAllocationStats(cls.id(), temp_reg, space);
+    movl(Address(temp_reg, Heap::TopOffset(space)), instance_reg);
+    UpdateAllocationStats(cls.id(), temp_reg, space,
+                          /* inline_isolate = */ false);
     ASSERT(instance_size >= kHeapObjectTag);
     subl(instance_reg, Immediate(instance_size - kHeapObjectTag));
     uword tags = 0;
@@ -2798,17 +2827,19 @@
                                  Label* failure,
                                  bool near_jump,
                                  Register instance,
-                                 Register end_address) {
+                                 Register end_address,
+                                 Register temp_reg) {
   ASSERT(failure != NULL);
+  ASSERT(temp_reg != kNoRegister);
   if (FLAG_inline_alloc) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, kNoRegister, failure, near_jump);
-    Isolate* isolate = Isolate::Current();
-    Heap* heap = isolate->heap();
-    Heap::Space space = heap->SpaceForAllocation(cid);
-    movl(instance, Address::Absolute(heap->TopAddress(space)));
+    MaybeTraceAllocation(cid, temp_reg, failure, near_jump,
+                         /* inline_isolate = */ false);
+    Heap::Space space = Heap::SpaceForAllocation(cid);
+    movl(temp_reg, Address(THR, Thread::heap_offset()));
+    movl(instance, Address(temp_reg, Heap::TopOffset(space)));
     movl(end_address, instance);
 
     addl(end_address, Immediate(instance_size));
@@ -2817,14 +2848,15 @@
     // Check if the allocation fits into the remaining space.
     // EAX: potential new object start.
     // EBX: potential next object start.
-    cmpl(end_address, Address::Absolute(heap->EndAddress(space)));
+    cmpl(end_address, Address(temp_reg, Heap::EndOffset(space)));
     j(ABOVE_EQUAL, failure);
 
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
-    movl(Address::Absolute(heap->TopAddress(space)), end_address);
+    movl(Address(temp_reg, Heap::TopOffset(space)), end_address);
     addl(instance, Immediate(kHeapObjectTag));
-    UpdateAllocationStatsWithSize(cid, instance_size, kNoRegister, space);
+    UpdateAllocationStatsWithSize(cid, instance_size, temp_reg, space,
+                                  /* inline_isolate = */ false);
 
     // Initialize the tags.
     uword tags = 0;
@@ -2891,10 +2923,9 @@
 
 void Assembler::Stop(const char* message) {
   if (FLAG_print_stop_message) {
-    StubCode* stub_code = Isolate::Current()->stub_code();
     pushl(EAX);  // Preserve EAX.
     movl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
-    call(&stub_code->PrintStopMessageLabel());  // Passing message in EAX.
+    Call(*StubCode::PrintStopMessage_entry());  // Passing message in EAX.
     popl(EAX);  // Restore EAX.
   } else {
     // Emit the message address as immediate operand in the test instruction.
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 909ebda..bac86c4 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -17,6 +17,7 @@
 
 // Forward declarations.
 class RuntimeEntry;
+class StubEntry;
 
 class Immediate : public ValueObject {
  public:
@@ -731,6 +732,11 @@
 
   void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
 
+  void Call(const StubEntry& stub_entry);
+
+  void Jmp(const StubEntry& stub_entry);
+  void J(Condition condition, const StubEntry& stub_entry);
+
   /*
    * Loading and comparing classes of objects.
    */
@@ -876,7 +882,8 @@
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
                             Label* trace,
-                            bool near_jump);
+                            bool near_jump,
+                            bool inline_isolate = true);
 
   void UpdateAllocationStats(intptr_t cid,
                              Register temp_reg,
@@ -909,7 +916,8 @@
                         Label* failure,
                         bool near_jump,
                         Register instance,
-                        Register end_address);
+                        Register end_address,
+                        Register temp);
 
   // Debugging and bringup support.
   void Stop(const char* message);
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index cb65f35..e4f9082 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -355,7 +355,7 @@
 
 
 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) {
-  ASSERT(allow_constant_pool());
+  ASSERT(constant_pool_allowed());
   ASSERT(!in_delay_slot_);
   ASSERT(rd != PP);
   if (Address::CanHoldOffset(offset)) {
@@ -456,6 +456,37 @@
 }
 
 
+void Assembler::Branch(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  Branch(&label);
+}
+
+
+void Assembler::BranchPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchPatchable(&label);
+}
+
+
+void Assembler::BranchLink(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLink(&label);
+}
+
+
+void Assembler::BranchLink(const StubEntry& stub_entry,
+                           Patchability patchable) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLink(&label, patchable);
+}
+
+
+void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  BranchLink(&label, kPatchable);
+}
+
+
 void Assembler::LoadObjectHelper(Register rd,
                                  const Object& object,
                                  bool is_unique) {
@@ -469,7 +500,7 @@
   // Smis and VM heap objects are never relocated; do not use object pool.
   if (object.IsSmi()) {
     LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
-  } else if (object.InVMHeap() || !allow_constant_pool()) {
+  } else if (object.InVMHeap() || !constant_pool_allowed()) {
     // Make sure that class CallPattern is able to decode this load immediate.
     int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
     const uint16_t object_low = Utils::Low16Bits(object_raw);
@@ -885,20 +916,29 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
-                                     Label* trace) {
+                                     Label* trace,
+                                     bool inline_isolate) {
   ASSERT(cid > 0);
   ASSERT(!in_delay_slot_);
   ASSERT(temp_reg != kNoRegister);
   ASSERT(temp_reg != TMP);
-  intptr_t state_offset;
-  ClassTable* class_table = Isolate::Current()->class_table();
-  ClassHeapStats** table_ptr =
-      class_table->StateAddressFor(cid, &state_offset);
-  if (cid < kNumPredefinedCids) {
-    LoadImmediate(temp_reg, reinterpret_cast<uword>(*table_ptr) + state_offset);
+  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
+  if (inline_isolate) {
+    ClassTable* class_table = Isolate::Current()->class_table();
+    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
+    if (cid < kNumPredefinedCids) {
+      LoadImmediate(temp_reg,
+                    reinterpret_cast<uword>(*table_ptr) + state_offset);
+    } else {
+      LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
+      lw(temp_reg, Address(temp_reg, 0));
+      AddImmediate(temp_reg, state_offset);
+    }
   } else {
-    LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
-    lw(temp_reg, Address(temp_reg, 0));
+    LoadIsolate(temp_reg);
+    intptr_t table_offset =
+        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+    lw(temp_reg, Address(temp_reg, table_offset));
     AddImmediate(temp_reg, state_offset);
   }
   lw(temp_reg, Address(temp_reg, 0));
@@ -917,30 +957,28 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure);
+    MaybeTraceAllocation(cls.id(), temp_reg, failure,
+                         /* inline_isolate = */ false);
     const intptr_t instance_size = cls.instance_size();
-    Heap* heap = Isolate::Current()->heap();
-    Heap::Space space = heap->SpaceForAllocation(cls.id());
-    const uword top_address = heap->TopAddress(space);
-    LoadImmediate(temp_reg, top_address);
-    lw(instance_reg, Address(temp_reg));
+    Heap::Space space = Heap::SpaceForAllocation(cls.id());
+    lw(temp_reg, Address(THR, Thread::heap_offset()));
+    lw(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
     // TODO(koda): Protect against unsigned overflow here.
     AddImmediate(instance_reg, instance_size);
 
     // instance_reg: potential next object start.
-    const uword end_address = heap->EndAddress(space);
-    ASSERT(top_address < end_address);
-    lw(TMP, Address(temp_reg, end_address - top_address));
+    lw(TMP, Address(temp_reg, Heap::EndOffset(space)));
     // Fail if heap end unsigned less than or equal to instance_reg.
     BranchUnsignedLessEqual(TMP, instance_reg, failure);
 
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
-    sw(instance_reg, Address(temp_reg));
+    sw(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
-    UpdateAllocationStats(cls.id(), temp_reg, space);
+    UpdateAllocationStats(cls.id(), temp_reg, space,
+                          /* inline_isolate = */ false);
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
     ASSERT(cls.id() != kIllegalCid);
@@ -968,27 +1006,27 @@
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
-    LoadImmediate(temp1, heap->TopAddress(space));
-    lw(instance, Address(temp1, 0));  // Potential new object start.
+    lw(temp1, Address(THR, Thread::heap_offset()));
+    // Potential new object start.
+    lw(instance, Address(temp1, heap->TopOffset(space)));
     // Potential next object start.
     AddImmediate(end_address, instance, instance_size);
     // Branch on unsigned overflow.
     BranchUnsignedLess(end_address, instance, failure);
 
     // Check if the allocation fits into the remaining space.
-    // instance: potential new object start.
+    // instance: potential new object start, /* inline_isolate = */ false.
     // end_address: potential next object start.
-    LoadImmediate(temp2, heap->EndAddress(space));
-    lw(temp2, Address(temp2, 0));
+    lw(temp2, Address(temp1, Heap::EndOffset(space)));
     BranchUnsignedGreaterEqual(end_address, temp2, failure);
 
-
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
-    sw(end_address, Address(temp1, 0));
+    sw(end_address, Address(temp1, Heap::TopOffset(space)));
     addiu(instance, instance, Immediate(kHeapObjectTag));
     LoadImmediate(temp1, instance_size);
-    UpdateAllocationStatsWithSize(cid, temp1, temp2, space);
+    UpdateAllocationStatsWithSize(cid, temp1, temp2, space,
+                                  /* inline_isolate = */ false);
 
     // Initialize the tags.
     // instance: new object start as a tagged pointer.
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 174ec9f..0f0897f 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -26,6 +26,7 @@
 
 // Forward declarations.
 class RuntimeEntry;
+class StubEntry;
 
 class Immediate : public ValueObject {
  public:
@@ -241,7 +242,7 @@
         delay_slot_available_(false),
         in_delay_slot_(false),
         comments_(),
-        allow_constant_pool_(true) { }
+        constant_pool_allowed_(true) { }
   ~Assembler() { }
 
   void PopRegister(Register r) { Pop(r); }
@@ -316,7 +317,8 @@
 
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
-                            Label* trace);
+                            Label* trace,
+                            bool inline_isolate = true);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
@@ -916,6 +918,8 @@
     jr(TMP);
   }
 
+  void Branch(const StubEntry& stub_entry);
+
   void BranchPatchable(const ExternalLabel* label) {
     ASSERT(!in_delay_slot_);
     const uint16_t low = Utils::Low16Bits(label->address());
@@ -926,12 +930,16 @@
     delay_slot_available_ = false;  // CodePatcher expects a nop.
   }
 
+  void BranchPatchable(const StubEntry& stub_entry);
+
   void BranchLink(const ExternalLabel* label) {
     ASSERT(!in_delay_slot_);
     LoadImmediate(T9, label->address());
     jalr(T9);
   }
 
+  void BranchLink(const StubEntry& stub_entry);
+
   void BranchLink(const ExternalLabel* label, Patchability patchable) {
     ASSERT(!in_delay_slot_);
     const int32_t offset = ObjectPool::element_offset(
@@ -943,10 +951,14 @@
     }
   }
 
+  void BranchLink(const StubEntry& stub_entry, Patchability patchable);
+
   void BranchLinkPatchable(const ExternalLabel* label) {
     BranchLink(label, kPatchable);
   }
 
+  void BranchLinkPatchable(const StubEntry& stub_entry);
+
   void Drop(intptr_t stack_elements) {
     ASSERT(stack_elements >= 0);
     if (stack_elements > 0) {
@@ -1622,11 +1634,11 @@
   static bool IsSafe(const Object& object) { return true; }
   static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
 
-  bool allow_constant_pool() const {
-    return allow_constant_pool_;
+  bool constant_pool_allowed() const {
+    return constant_pool_allowed_;
   }
-  void set_allow_constant_pool(bool b) {
-    allow_constant_pool_ = b;
+  void set_constant_pool_allowed(bool b) {
+    constant_pool_allowed_ = b;
   }
 
  private:
@@ -1656,7 +1668,7 @@
 
   GrowableArray<CodeComment*> comments_;
 
-  bool allow_constant_pool_;
+  bool constant_pool_allowed_;
 
   void LoadObjectHelper(Register rd, const Object& object, bool is_unique);
 
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 48118d5..fd27c9a 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -25,7 +25,7 @@
     : buffer_(),
       prologue_offset_(-1),
       comments_(),
-      allow_constant_pool_(true) {
+      constant_pool_allowed_(false) {
   // Far branching mode is only needed and implemented for MIPS and ARM.
   ASSERT(!use_far_branches);
 }
@@ -63,11 +63,10 @@
 
 void Assembler::LoadExternalLabel(Register dst,
                                   const ExternalLabel* label,
-                                  Patchability patchable,
-                                  Register pp) {
+                                  Patchability patchable) {
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper_.FindExternalLabel(label, patchable));
-  LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
+  LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
 }
 
 
@@ -83,7 +82,7 @@
 
 
 void Assembler::CallPatchable(const ExternalLabel* label) {
-  ASSERT(allow_constant_pool());
+  ASSERT(constant_pool_allowed());
   intptr_t call_start = buffer_.GetPosition();
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper_.FindExternalLabel(label, kPatchable));
@@ -92,10 +91,23 @@
 }
 
 
-void Assembler::Call(const ExternalLabel* label, Register pp) {
+void Assembler::Call(const ExternalLabel* label) {
+  ASSERT(constant_pool_allowed());
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
-  call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
+  call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag));
+}
+
+
+void Assembler::CallPatchable(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  CallPatchable(&label);
+}
+
+
+void Assembler::Call(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  Call(&label);
 }
 
 
@@ -126,12 +138,12 @@
 }
 
 
-void Assembler::PushImmediate(const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    LoadImmediate(TMP, imm, pp);
-    pushq(TMP);
-  } else {
+void Assembler::PushImmediate(const Immediate& imm) {
+  if (imm.is_int32()) {
     pushq(imm);
+  } else {
+    LoadImmediate(TMP, imm);
+    pushq(TMP);
   }
 }
 
@@ -782,7 +794,7 @@
   } float_not_constant =
       { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)));
   xorps(dst, Address(TMP, 0));
 }
 
@@ -796,7 +808,7 @@
   } float_negate_constant =
       { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)));
   xorps(dst, Address(TMP, 0));
 }
 
@@ -810,7 +822,7 @@
   } float_absolute_constant =
       { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF };
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)));
   andps(dst, Address(TMP, 0));
 }
 
@@ -824,7 +836,7 @@
   } float_zerow_constant =
       { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 };
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)));
   andps(dst, Address(TMP, 0));
 }
 
@@ -1012,7 +1024,7 @@
   } double_negate_constant =
       { 0x8000000000000000LL, 0x8000000000000000LL };
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)));
   xorpd(dst, Address(TMP, 0));
 }
 
@@ -1060,7 +1072,7 @@
   } double_absolute_const =
       { 0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL };
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&double_absolute_const)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&double_absolute_const)));
   andpd(dst, Address(TMP, 0));
 }
 
@@ -1473,6 +1485,7 @@
     EmitRegisterREX(reg, REX_W);
     EmitComplex(7, Operand(reg), imm);
   } else {
+    ASSERT(reg != TMP);
     movq(TMP, imm);
     cmpq(reg, TMP);
   }
@@ -1496,24 +1509,23 @@
 }
 
 
-void Assembler::CompareImmediate(Register reg, const Immediate& imm,
-                                 Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    LoadImmediate(TMP, imm, pp);
-    cmpq(reg, TMP);
-  } else {
+void Assembler::CompareImmediate(Register reg, const Immediate& imm) {
+  if (imm.is_int32()) {
     cmpq(reg, imm);
+  } else {
+    ASSERT(reg != TMP);
+    LoadImmediate(TMP, imm);
+    cmpq(reg, TMP);
   }
 }
 
 
-void Assembler::CompareImmediate(const Address& address, const Immediate& imm,
-                                 Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    LoadImmediate(TMP, imm, pp);
-    cmpq(address, TMP);
-  } else {
+void Assembler::CompareImmediate(const Address& address, const Immediate& imm) {
+  if (imm.is_int32()) {
     cmpq(address, imm);
+  } else {
+    LoadImmediate(TMP, imm);
+    cmpq(address, TMP);
   }
 }
 
@@ -1608,13 +1620,13 @@
 }
 
 
-void Assembler::TestImmediate(Register dst, const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    ASSERT(dst != TMP);
-    LoadImmediate(TMP, imm, pp);
-    testq(dst, TMP);
-  } else {
+void Assembler::TestImmediate(Register dst, const Immediate& imm) {
+  if (imm.is_int32()) {
     testq(dst, imm);
+  } else {
+    ASSERT(dst != TMP);
+    LoadImmediate(TMP, imm);
+    testq(dst, TMP);
   }
 }
 
@@ -1691,19 +1703,20 @@
     EmitRegisterREX(dst, REX_W);
     EmitComplex(4, Operand(dst), imm);
   } else {
+    ASSERT(dst != TMP);
     movq(TMP, imm);
     andq(dst, TMP);
   }
 }
 
 
-void Assembler::AndImmediate(Register dst, const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    ASSERT(dst != TMP);
-    LoadImmediate(TMP, imm, pp);
-    andq(dst, TMP);
-  } else {
+void Assembler::AndImmediate(Register dst, const Immediate& imm) {
+  if (imm.is_int32()) {
     andq(dst, imm);
+  } else {
+    ASSERT(dst != TMP);
+    LoadImmediate(TMP, imm);
+    andq(dst, TMP);
   }
 }
 
@@ -1731,19 +1744,20 @@
     EmitRegisterREX(dst, REX_W);
     EmitComplex(1, Operand(dst), imm);
   } else {
+    ASSERT(dst != TMP);
     movq(TMP, imm);
     orq(dst, TMP);
   }
 }
 
 
-void Assembler::OrImmediate(Register dst, const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    ASSERT(dst != TMP);
-    LoadImmediate(TMP, imm, pp);
-    orq(dst, TMP);
-  } else {
+void Assembler::OrImmediate(Register dst, const Immediate& imm) {
+  if (imm.is_int32()) {
     orq(dst, imm);
+  } else {
+    ASSERT(dst != TMP);
+    LoadImmediate(TMP, imm);
+    orq(dst, TMP);
   }
 }
 
@@ -1779,19 +1793,20 @@
     EmitRegisterREX(dst, REX_W);
     EmitComplex(6, Operand(dst), imm);
   } else {
+    ASSERT(dst != TMP);
     movq(TMP, imm);
     xorq(dst, TMP);
   }
 }
 
 
-void Assembler::XorImmediate(Register dst, const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    ASSERT(dst != TMP);
-    LoadImmediate(TMP, imm, pp);
-    xorq(dst, TMP);
-  } else {
+void Assembler::XorImmediate(Register dst, const Immediate& imm) {
+  if (imm.is_int32()) {
     xorq(dst, imm);
+  } else {
+    ASSERT(dst != TMP);
+    LoadImmediate(TMP, imm);
+    xorq(dst, TMP);
   }
 }
 
@@ -1877,6 +1892,7 @@
     EmitRegisterREX(dst, REX_W);
     EmitComplex(0, Operand(dst), imm);
   } else {
+    ASSERT(dst != TMP);
     movq(TMP, imm);
     addq(dst, TMP);
   }
@@ -1918,6 +1934,7 @@
     EmitRegisterREX(dst, REX_W);
     EmitComplex(2, Operand(dst), imm);
   } else {
+    ASSERT(dst != TMP);
     movq(TMP, imm);
     adcq(dst, TMP);
   }
@@ -2074,19 +2091,20 @@
     EmitOperand(reg & 7, Operand(reg));
     EmitImmediate(imm);
   } else {
+    ASSERT(reg != TMP);
     movq(TMP, imm);
     imulq(reg, TMP);
   }
 }
 
 
-void Assembler::MulImmediate(Register reg, const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    ASSERT(reg != TMP);
-    LoadImmediate(TMP, imm, pp);
-    imulq(reg, TMP);
-  } else {
+void Assembler::MulImmediate(Register reg, const Immediate& imm) {
+  if (imm.is_int32()) {
     imulq(reg, imm);
+  } else {
+    ASSERT(reg != TMP);
+    LoadImmediate(TMP, imm);
+    imulq(reg, TMP);
   }
 }
 
@@ -2123,6 +2141,7 @@
     EmitRegisterREX(reg, REX_W);
     EmitComplex(5, Operand(reg), imm);
   } else {
+    ASSERT(reg != TMP);
     movq(TMP, imm);
     subq(reg, TMP);
   }
@@ -2172,6 +2191,7 @@
     EmitRegisterREX(dst, REX_W);
     EmitComplex(3, Operand(dst), imm);
   } else {
+    ASSERT(dst != TMP);
     movq(TMP, imm);
     sbbq(dst, TMP);
   }
@@ -2543,6 +2563,13 @@
 }
 
 
+void Assembler::J(Condition condition, const StubEntry& stub_entry,
+                  Register pp) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  J(condition, &label, pp);
+}
+
+
 void Assembler::jmp(Register reg) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   Operand operand(reg);
@@ -2598,8 +2625,14 @@
 }
 
 
+void Assembler::jmp(const StubEntry& stub_entry) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  jmp(&label);
+}
+
+
 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) {
-  ASSERT(allow_constant_pool());
+  ASSERT((pp != PP) || constant_pool_allowed());
   intptr_t call_start = buffer_.GetPosition();
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper_.FindExternalLabel(label, kPatchable));
@@ -2609,13 +2642,26 @@
 }
 
 
+void Assembler::JmpPatchable(const StubEntry& stub_entry, Register pp) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  JmpPatchable(&label, pp);
+}
+
+
 void Assembler::Jmp(const ExternalLabel* label, Register pp) {
+  ASSERT((pp != PP) || constant_pool_allowed());
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
   jmp(Address(pp, offset - kHeapObjectTag));
 }
 
 
+void Assembler::Jmp(const StubEntry& stub_entry, Register pp) {
+  const ExternalLabel label(stub_entry.EntryPoint());
+  Jmp(&label, pp);
+}
+
+
 void Assembler::lock() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF0);
@@ -2664,7 +2710,7 @@
 }
 
 
-void Assembler::AddImmediate(Register reg, const Immediate& imm, Register pp) {
+void Assembler::AddImmediate(Register reg, const Immediate& imm) {
   const int64_t value = imm.value();
   if (value == 0) {
     return;
@@ -2673,22 +2719,21 @@
     if (value == 1) {
       incq(reg);
     } else {
-      if (CanLoadImmediateFromPool(imm, pp)) {
-        ASSERT(reg != TMP);
-        LoadImmediate(TMP, imm, pp);
-        addq(reg, TMP);
-      } else {
+      if (imm.is_int32()) {
         addq(reg, imm);
+      } else {
+        ASSERT(reg != TMP);
+        LoadImmediate(TMP, imm);
+        addq(reg, TMP);
       }
     }
   } else {
-    SubImmediate(reg, Immediate(-value), pp);
+    SubImmediate(reg, Immediate(-value));
   }
 }
 
 
-void Assembler::AddImmediate(const Address& address, const Immediate& imm,
-                             Register pp) {
+void Assembler::AddImmediate(const Address& address, const Immediate& imm) {
   const int64_t value = imm.value();
   if (value == 0) {
     return;
@@ -2697,20 +2742,20 @@
     if (value == 1) {
       incq(address);
     } else {
-      if (CanLoadImmediateFromPool(imm, pp)) {
-        LoadImmediate(TMP, imm, pp);
-        addq(address, TMP);
-      } else {
+      if (imm.is_int32()) {
         addq(address, imm);
+      } else {
+        LoadImmediate(TMP, imm);
+        addq(address, TMP);
       }
     }
   } else {
-    SubImmediate(address, Immediate(-value), pp);
+    SubImmediate(address, Immediate(-value));
   }
 }
 
 
-void Assembler::SubImmediate(Register reg, const Immediate& imm, Register pp) {
+void Assembler::SubImmediate(Register reg, const Immediate& imm) {
   const int64_t value = imm.value();
   if (value == 0) {
     return;
@@ -2719,22 +2764,21 @@
     if (value == 1) {
       decq(reg);
     } else {
-      if (CanLoadImmediateFromPool(imm, pp)) {
-        ASSERT(reg != TMP);
-        LoadImmediate(TMP, imm, pp);
-        subq(reg, TMP);
-      } else {
+      if (imm.is_int32()) {
         subq(reg, imm);
+      } else {
+        ASSERT(reg != TMP);
+        LoadImmediate(TMP, imm);
+        subq(reg, TMP);
       }
     }
   } else {
-    AddImmediate(reg, Immediate(-value), pp);
+    AddImmediate(reg, Immediate(-value));
   }
 }
 
 
-void Assembler::SubImmediate(const Address& address, const Immediate& imm,
-                             Register pp) {
+void Assembler::SubImmediate(const Address& address, const Immediate& imm) {
   const int64_t value = imm.value();
   if (value == 0) {
     return;
@@ -2743,15 +2787,15 @@
     if (value == 1) {
       decq(address);
     } else {
-      if (CanLoadImmediateFromPool(imm, pp)) {
-        LoadImmediate(TMP, imm, pp);
-        subq(address, TMP);
-      } else {
+      if (imm.is_int32()) {
         subq(address, imm);
+      } else {
+        LoadImmediate(TMP, imm);
+        subq(address, TMP);
       }
     }
   } else {
-    AddImmediate(address, Immediate(-value), pp);
+    AddImmediate(address, Immediate(-value));
   }
 }
 
@@ -2770,7 +2814,7 @@
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
   ASSERT(!Thread::CanLoadFromThread(object));
-  if (!allow_constant_pool()) {
+  if (!constant_pool_allowed()) {
     return false;
   }
 
@@ -2787,11 +2831,12 @@
 }
 
 
-void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
-                                       int32_t offset) {
+void Assembler::LoadWordFromPoolOffset(Register dst, int32_t offset) {
+  ASSERT(constant_pool_allowed());
+  ASSERT(dst != PP);
   // This sequence must be of fixed size. AddressBaseImm32
   // forces the address operand to use a fixed-size imm32 encoding.
-  movq(dst, Address::AddressBaseImm32(pp, offset));
+  movq(dst, Address::AddressBaseImm32(PP, offset));
 }
 
 
@@ -2802,7 +2847,6 @@
 
 void Assembler::LoadObjectHelper(Register dst,
                                  const Object& object,
-                                 Register pp,
                                  bool is_unique) {
   if (Thread::CanLoadFromThread(object)) {
     movq(dst, Address(THR, Thread::OffsetFromThread(object)));
@@ -2810,62 +2854,70 @@
     const int32_t offset = ObjectPool::element_offset(
         is_unique ? object_pool_wrapper_.AddObject(object)
                   : object_pool_wrapper_.FindObject(object));
-    LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
+    LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
   } else {
     ASSERT(object.IsSmi() || object.InVMHeap());
-    LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
+    LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
 
 
-void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
-  LoadObjectHelper(dst, object, pp, false);
+void Assembler::LoadFunctionFromCalleePool(Register dst,
+                                           const Function& function,
+                                           Register new_pp) {
+  ASSERT(!constant_pool_allowed());
+  ASSERT(new_pp != PP);
+  const int32_t offset =
+      ObjectPool::element_offset(object_pool_wrapper_.FindObject(function));
+  movq(dst, Address::AddressBaseImm32(new_pp, offset - kHeapObjectTag));
 }
 
 
-void Assembler::LoadUniqueObject(Register dst,
-                                 const Object& object,
-                                 Register pp) {
-  LoadObjectHelper(dst, object, pp, true);
+void Assembler::LoadObject(Register dst, const Object& object) {
+  LoadObjectHelper(dst, object, false);
 }
 
 
-void Assembler::StoreObject(const Address& dst, const Object& object,
-                            Register pp) {
+void Assembler::LoadUniqueObject(Register dst, const Object& object) {
+  LoadObjectHelper(dst, object, true);
+}
+
+
+void Assembler::StoreObject(const Address& dst, const Object& object) {
   if (Thread::CanLoadFromThread(object)) {
     movq(TMP, Address(THR, Thread::OffsetFromThread(object)));
     movq(dst, TMP);
   } else if (CanLoadFromObjectPool(object)) {
-    LoadObject(TMP, object, pp);
+    LoadObject(TMP, object);
     movq(dst, TMP);
   } else {
-    MoveImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
+    MoveImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
 
 
-void Assembler::PushObject(const Object& object, Register pp) {
+void Assembler::PushObject(const Object& object) {
   if (Thread::CanLoadFromThread(object)) {
     pushq(Address(THR, Thread::OffsetFromThread(object)));
   } else if (CanLoadFromObjectPool(object)) {
-    LoadObject(TMP, object, pp);
+    LoadObject(TMP, object);
     pushq(TMP);
   } else {
-    PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
+    PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
 
 
-void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
+void Assembler::CompareObject(Register reg, const Object& object) {
   if (Thread::CanLoadFromThread(object)) {
     cmpq(reg, Address(THR, Thread::OffsetFromThread(object)));
   } else if (CanLoadFromObjectPool(object)) {
     const int32_t offset =
         ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
-    cmpq(reg, Address(pp, offset-kHeapObjectTag));
+    cmpq(reg, Address(PP, offset-kHeapObjectTag));
   } else {
     CompareImmediate(
-        reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
+        reg, Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
 
@@ -2875,33 +2927,22 @@
 }
 
 
-bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) {
-  if (!allow_constant_pool()) {
-    return false;
-  }
-  return !imm.is_int32() && (pp != kNoRegister);
-}
-
-
-void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    // It's a 64-bit constant and we're not in the VM isolate, so load from
-    // object pool.
-    int32_t offset = ObjectPool::element_offset(FindImmediate(imm.value()));
-    LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag);
-  } else {
+void Assembler::LoadImmediate(Register reg, const Immediate& imm) {
+  if (imm.is_int32() || !constant_pool_allowed()) {
     movq(reg, imm);
+  } else {
+    int32_t offset = ObjectPool::element_offset(FindImmediate(imm.value()));
+    LoadWordFromPoolOffset(reg, offset - kHeapObjectTag);
   }
 }
 
 
-void Assembler::MoveImmediate(const Address& dst, const Immediate& imm,
-                              Register pp) {
-  if (CanLoadImmediateFromPool(imm, pp)) {
-    LoadImmediate(TMP, imm, pp);
-    movq(dst, TMP);
-  } else {
+void Assembler::MoveImmediate(const Address& dst, const Immediate& imm) {
+  if (imm.is_int32()) {
     movq(dst, imm);
+  } else {
+    LoadImmediate(TMP, imm);
+    movq(dst, TMP);
   }
 }
 
@@ -3087,18 +3128,17 @@
 void Assembler::StoreIntoObjectNoBarrier(Register object,
                                          const Address& dest,
                                          const Object& value,
-                                         Register pp,
                                          FieldContent old_content) {
   VerifyHeapWord(dest, old_content);
   if (VerifiedMemory::enabled()) {
-    Register temp = (pp == RCX) ? RDX : RCX;
+    const Register temp = RCX;
     pushq(temp);
     leaq(temp, dest);
-    StoreObject(Address(temp, 0), value, pp);
-    StoreObject(Address(temp, VerifiedMemory::offset()), value, pp);
+    StoreObject(Address(temp, 0), value);
+    StoreObject(Address(temp, VerifiedMemory::offset()), value);
     popq(temp);
   } else {
-    StoreObject(dest, value, pp);
+    StoreObject(dest, value);
   }
   // TODO(koda): Use 'object', verify that generational barrier's not needed.
 }
@@ -3155,7 +3195,7 @@
   } double_negate_constant =
       {0x8000000000000000LL, 0x8000000000000000LL};
   LoadImmediate(
-      TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP);
+      TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)));
   xorpd(d, Address(TMP, 0));
 }
 
@@ -3167,7 +3207,7 @@
   } double_abs_constant =
       {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
   LoadImmediate(TMP,
-      Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)), PP);
+      Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)));
   andpd(reg, Address(TMP, 0));
 }
 
@@ -3183,9 +3223,9 @@
       EmitUint8(0xB8 | (RDI & 7));
       EmitInt64(message_address);
     } else {
-      LoadImmediate(RDI, Immediate(message_address), PP);
+      LoadImmediate(RDI, Immediate(message_address));
     }
-    call(&Isolate::Current()->stub_code()->PrintStopMessageLabel());
+    call(&StubCode::PrintStopMessage_entry()->label());
     popq(RDI);  // Restore RDI register.
     popq(TMP);  // Restore TMP register.
   } else {
@@ -3261,7 +3301,7 @@
                               intptr_t xmm_register_set) {
   const intptr_t xmm_regs_count = RegisterSet::RegisterCount(xmm_register_set);
   if (xmm_regs_count > 0) {
-    AddImmediate(RSP, Immediate(-xmm_regs_count * kFpuRegisterSize), PP);
+    AddImmediate(RSP, Immediate(-xmm_regs_count * kFpuRegisterSize));
     // Store XMM registers with the lowest register number at the lowest
     // address.
     intptr_t offset = 0;
@@ -3310,7 +3350,7 @@
       }
     }
     ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
-    AddImmediate(RSP, Immediate(offset), PP);
+    AddImmediate(RSP, Immediate(offset));
   }
 }
 
@@ -3380,16 +3420,19 @@
   movq(pp, Address::AddressRIPRelative(
       -entry_to_rip_offset - object_pool_pc_dist));
   ASSERT(CodeSize() == entry_to_rip_offset);
+  set_constant_pool_allowed(pp == PP);
 }
 
 
 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size,
                                        Register new_pp,
                                        Register pc_marker_override) {
+  ASSERT(!constant_pool_allowed());
   EnterFrame(0);
   pushq(pc_marker_override);
   pushq(PP);
   movq(PP, new_pp);
+  set_constant_pool_allowed(true);
   if (frame_size != 0) {
     subq(RSP, Immediate(frame_size));
   }
@@ -3397,6 +3440,10 @@
 
 
 void Assembler::LeaveDartFrame() {
+  // LeaveDartFrame is called from stubs (pp disallowed) and from Dart code (pp
+  // allowed), so there is no point in checking the current value of
+  // constant_pool_allowed().
+  set_constant_pool_allowed(false);
   // Restore caller's PP register that was pushed in EnterDartFrame.
   movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize)));
   LeaveFrame();
@@ -3411,12 +3458,14 @@
 void Assembler::EnterOsrFrame(intptr_t extra_size,
                               Register new_pp,
                               Register pc_marker_override) {
+  ASSERT(!constant_pool_allowed());
   if (prologue_offset_ == -1) {
     Comment("PrologueOffset = %" Pd "", CodeSize());
     prologue_offset_ = CodeSize();
   }
   movq(Address(RBP, kPcMarkerSlotFromFp * kWordSize), pc_marker_override);
   movq(PP, new_pp);
+  set_constant_pool_allowed(true);
   if (extra_size != 0) {
     subq(RSP, Immediate(extra_size));
   }
@@ -3424,14 +3473,16 @@
 
 
 void Assembler::EnterStubFrame() {
+  set_constant_pool_allowed(false);
   EnterFrame(0);
   pushq(Immediate(0));  // Push 0 in the saved PC area for stub frames.
   pushq(PP);  // Save caller's pool pointer
-  LoadPoolPointer(PP);
+  LoadPoolPointer();
 }
 
 
 void Assembler::LeaveStubFrame() {
+  set_constant_pool_allowed(false);
   // Restore caller's PP register that was pushed in EnterStubFrame.
   movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize)));
   LeaveFrame();
@@ -3440,19 +3491,25 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Label* trace,
-                                     bool near_jump) {
+                                     bool near_jump,
+                                     bool inline_isolate) {
   ASSERT(cid > 0);
-  intptr_t state_offset;
-  ClassTable* class_table = Isolate::Current()->class_table();
-  ClassHeapStats** table_ptr =
-      class_table->StateAddressFor(cid, &state_offset);
+  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
   Register temp_reg = TMP;
-  if (cid < kNumPredefinedCids) {
-    movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr)));
+  if (inline_isolate) {
+    ClassTable* class_table = Isolate::Current()->class_table();
+    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
+    if (cid < kNumPredefinedCids) {
+      movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr)));
+    } else {
+      movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr)));
+      movq(temp_reg, Address(temp_reg, 0));
+    }
   } else {
-    Register temp_reg = TMP;
-    movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr)));
-    movq(temp_reg, Address(temp_reg, 0));
+    LoadIsolate(temp_reg);
+    intptr_t table_offset =
+        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+    movq(temp_reg, Address(temp_reg, table_offset));
   }
   testb(Address(temp_reg, state_offset),
         Immediate(ClassHeapStats::TraceAllocationMask()));
@@ -3518,36 +3575,34 @@
                             Label* failure,
                             bool near_jump,
                             Register instance_reg,
-                            Register pp) {
+                            Register temp) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), failure, near_jump);
-    Heap* heap = Isolate::Current()->heap();
+    MaybeTraceAllocation(cls.id(), failure, near_jump,
+                         /* inline_isolate = */ false);
     const intptr_t instance_size = cls.instance_size();
-    Heap::Space space = heap->SpaceForAllocation(cls.id());
-    LoadImmediate(TMP, Immediate(heap->TopAddress(space)), pp);
-    movq(instance_reg, Address(TMP, 0));
-    AddImmediate(instance_reg, Immediate(instance_size), pp);
+    Heap::Space space = Heap::SpaceForAllocation(cls.id());
+    movq(temp, Address(THR, Thread::heap_offset()));
+    movq(instance_reg, Address(temp, Heap::TopOffset(space)));
+    addq(instance_reg, Immediate(instance_size));
     // instance_reg: potential next object start.
-    LoadImmediate(TMP, Immediate(heap->EndAddress(space)), pp);
-    cmpq(instance_reg, Address(TMP, 0));
+    cmpq(instance_reg, Address(temp, Heap::EndOffset(space)));
     j(ABOVE_EQUAL, failure, near_jump);
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
-    LoadImmediate(TMP, Immediate(heap->TopAddress(space)), pp);
-    movq(Address(TMP, 0), instance_reg);
-    UpdateAllocationStats(cls.id(), space);
+    movq(Address(temp, Heap::TopOffset(space)), instance_reg);
+    UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
     ASSERT(instance_size >= kHeapObjectTag);
-    AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size), pp);
+    AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size));
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
     ASSERT(cls.id() != kIllegalCid);
     tags = RawObject::ClassIdTag::update(cls.id(), tags);
     MoveImmediate(FieldAddress(instance_reg, Object::tags_offset()),
-                  Immediate(tags), pp);
+                  Immediate(tags));
   } else {
     jmp(failure);
   }
@@ -3559,19 +3614,18 @@
                                  Label* failure,
                                  bool near_jump,
                                  Register instance,
-                                 Register end_address) {
+                                 Register end_address,
+                                 Register temp) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, failure, near_jump);
-    Isolate* isolate = Isolate::Current();
-    Heap* heap = isolate->heap();
-    Heap::Space space = heap->SpaceForAllocation(cid);
-    movq(instance, Immediate(heap->TopAddress(space)));
-    movq(instance, Address(instance, 0));
-    movq(end_address, RAX);
+    MaybeTraceAllocation(cid, failure, near_jump, /* inline_isolate = */ false);
+    Heap::Space space = Heap::SpaceForAllocation(cid);
+    movq(temp, Address(THR, Thread::heap_offset()));
+    movq(instance, Address(temp, Heap::TopOffset(space)));
+    movq(end_address, instance);
 
     addq(end_address, Immediate(instance_size));
     j(CARRY, failure);
@@ -3579,16 +3633,15 @@
     // Check if the allocation fits into the remaining space.
     // instance: potential new object start.
     // end_address: potential next object start.
-    movq(TMP, Immediate(heap->EndAddress(space)));
-    cmpq(end_address, Address(TMP, 0));
+    cmpq(end_address, Address(temp, Heap::EndOffset(space)));
     j(ABOVE_EQUAL, failure);
 
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
-    movq(TMP, Immediate(heap->TopAddress(space)));
-    movq(Address(TMP, 0), end_address);
+    movq(Address(temp, Heap::TopOffset(space)), end_address);
     addq(instance, Immediate(kHeapObjectTag));
-    UpdateAllocationStatsWithSize(cid, instance_size, space);
+    UpdateAllocationStatsWithSize(cid, instance_size, space,
+                                  /* inline_isolate = */ false);
 
     // Initialize the tags.
     // instance: new object start as a tagged pointer.
@@ -3747,7 +3800,7 @@
 }
 
 
-void Assembler::LoadClassById(Register result, Register class_id, Register pp) {
+void Assembler::LoadClassById(Register result, Register class_id) {
   ASSERT(result != class_id);
   LoadIsolate(result);
   const intptr_t offset =
@@ -3757,9 +3810,9 @@
 }
 
 
-void Assembler::LoadClass(Register result, Register object, Register pp) {
+void Assembler::LoadClass(Register result, Register object) {
   LoadClassId(TMP, object);
-  LoadClassById(result, TMP, pp);
+  LoadClassById(result, TMP);
 }
 
 
@@ -3794,7 +3847,7 @@
 
   // Load up a null object. We only need it so we can use LoadClassId on it in
   // the case that object is a Smi.
-  LoadObject(result, Object::null_object(), PP);
+  LoadObject(result, Object::null_object());
   // Check if the object is a Smi.
   testq(object, Immediate(kSmiTagMask));
   // If the object *is* a Smi, use the null object instead.
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index b7db5a5..edc7bc2 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -19,6 +19,7 @@
 
 // Forward declarations.
 class RuntimeEntry;
+class StubEntry;
 
 class Immediate : public ValueObject {
  public:
@@ -370,7 +371,7 @@
   void pushq(Register reg);
   void pushq(const Address& address);
   void pushq(const Immediate& imm);
-  void PushImmediate(const Immediate& imm, Register pp);
+  void PushImmediate(const Immediate& imm);
 
   void popq(Register reg);
   void popq(const Address& address);
@@ -527,9 +528,8 @@
   void cmpq(Register reg0, Register reg1);
   void cmpq(Register reg, const Address& address);
 
-  void CompareImmediate(Register reg, const Immediate& imm, Register pp);
-  void CompareImmediate(const Address& address, const Immediate& imm,
-                        Register pp);
+  void CompareImmediate(Register reg, const Immediate& imm);
+  void CompareImmediate(const Address& address, const Immediate& imm);
 
   void testl(Register reg1, Register reg2);
   void testl(Register reg, const Immediate& imm);
@@ -537,7 +537,7 @@
 
   void testq(Register reg1, Register reg2);
   void testq(Register reg, const Immediate& imm);
-  void TestImmediate(Register dst, const Immediate& imm, Register pp);
+  void TestImmediate(Register dst, const Immediate& imm);
 
   void andl(Register dst, Register src);
   void andl(Register dst, const Immediate& imm);
@@ -551,18 +551,18 @@
   void andq(Register dst, Register src);
   void andq(Register dst, const Address& address);
   void andq(Register dst, const Immediate& imm);
-  void AndImmediate(Register dst, const Immediate& imm, Register pp);
+  void AndImmediate(Register dst, const Immediate& imm);
 
   void orq(Register dst, Register src);
   void orq(Register dst, const Address& address);
   void orq(Register dst, const Immediate& imm);
-  void OrImmediate(Register dst, const Immediate& imm, Register pp);
+  void OrImmediate(Register dst, const Immediate& imm);
 
   void xorq(Register dst, Register src);
   void xorq(Register dst, const Address& address);
   void xorq(const Address& dst, Register src);
   void xorq(Register dst, const Immediate& imm);
-  void XorImmediate(Register dst, const Immediate& imm, Register pp);
+  void XorImmediate(Register dst, const Immediate& imm);
 
   void addl(Register dst, Register src);
   void addl(Register dst, const Immediate& imm);
@@ -597,7 +597,7 @@
   void imulq(Register dst, Register src);
   void imulq(Register dst, const Address& address);
   void imulq(Register dst, const Immediate& imm);
-  void MulImmediate(Register reg, const Immediate& imm, Register pp);
+  void MulImmediate(Register reg, const Immediate& imm);
   void mulq(Register reg);
 
   void subl(Register dst, Register src);
@@ -693,6 +693,7 @@
   // Note: verified_mem mode forces far jumps.
   void jmp(Label* label, bool near = kFarJump);
   void jmp(const ExternalLabel* label);
+  void jmp(const StubEntry& stub_entry);
 
   void lock();
   void cmpxchgl(const Address& address, Register reg);
@@ -739,44 +740,48 @@
   void MoveRegister(Register to, Register from);
   void PopRegister(Register r);
 
-  // Macros accepting a pp Register argument may attempt to load values from
-  // the object pool when possible. Unless you are sure that the untagged object
-  // pool pointer is in another register, or that it is not available at all,
-  // PP should be passed for pp.
+  // Macros for adding/subtracting an immediate value that may be loaded from
+  // the constant pool.
   // TODO(koda): Assert that these are not used for heap objects.
-  void AddImmediate(Register reg, const Immediate& imm, Register pp);
-  void AddImmediate(const Address& address, const Immediate& imm, Register pp);
-  void SubImmediate(Register reg, const Immediate& imm, Register pp);
-  void SubImmediate(const Address& address, const Immediate& imm, Register pp);
+  void AddImmediate(Register reg, const Immediate& imm);
+  void AddImmediate(const Address& address, const Immediate& imm);
+  void SubImmediate(Register reg, const Immediate& imm);
+  void SubImmediate(const Address& address, const Immediate& imm);
 
   void Drop(intptr_t stack_elements, Register tmp = TMP);
 
-  bool allow_constant_pool() const {
-    return allow_constant_pool_;
+  bool constant_pool_allowed() const {
+    return constant_pool_allowed_;
   }
-  void set_allow_constant_pool(bool b) {
-    allow_constant_pool_ = b;
+  void set_constant_pool_allowed(bool b) {
+    constant_pool_allowed_ = b;
   }
 
-  bool CanLoadImmediateFromPool(const Immediate& imm, Register pp);
-  void LoadImmediate(Register reg, const Immediate& imm, Register pp);
+  void LoadImmediate(Register reg, const Immediate& imm);
   void LoadIsolate(Register dst);
-  void LoadObject(Register dst, const Object& obj, Register pp);
-  void LoadUniqueObject(Register dst, const Object& obj, Register pp);
+  void LoadObject(Register dst, const Object& obj);
+  void LoadUniqueObject(Register dst, const Object& obj);
   void LoadExternalLabel(Register dst,
                          const ExternalLabel* label,
-                         Patchability patchable,
-                         Register pp);
+                         Patchability patchable);
+  void LoadFunctionFromCalleePool(Register dst,
+                                  const Function& function,
+                                  Register new_pp);
   void JmpPatchable(const ExternalLabel* label, Register pp);
+  void JmpPatchable(const StubEntry& stub_entry, Register pp);
   void Jmp(const ExternalLabel* label, Register pp);
+  void Jmp(const StubEntry& stub_entry, Register pp);
   void J(Condition condition, const ExternalLabel* label, Register pp);
+  void J(Condition condition, const StubEntry& stub_entry, Register pp);
   void CallPatchable(const ExternalLabel* label);
-  void Call(const ExternalLabel* label, Register pp);
+  void CallPatchable(const StubEntry& stub_entry);
+  void Call(const ExternalLabel* label);
+  void Call(const StubEntry& stub_entry);
   // Unaware of write barrier (use StoreInto* methods for storing to objects).
   // TODO(koda): Add StackAddress/HeapAddress types to prevent misuse.
-  void StoreObject(const Address& dst, const Object& obj, Register pp);
-  void PushObject(const Object& object, Register pp);
-  void CompareObject(Register reg, const Object& object, Register pp);
+  void StoreObject(const Address& dst, const Object& obj);
+  void PushObject(const Object& object);
+  void CompareObject(Register reg, const Object& object);
 
   // When storing into a heap object field, knowledge of the previous content
   // is expressed through these constants.
@@ -804,13 +809,11 @@
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 const Object& value,
-                                Register pp,
                                 FieldContent old_content = kHeapObjectOrSmi);
   void InitializeFieldNoBarrier(Register object,
                                 const Address& dest,
-                                const Object& value,
-                                Register pp) {
-    return StoreIntoObjectNoBarrier(object, dest, value, pp, kEmptyOrSmiOrNull);
+                                const Object& value) {
+    return StoreIntoObjectNoBarrier(object, dest, value, kEmptyOrSmiOrNull);
   }
 
   // Stores a Smi value into a heap object field that always contains a Smi.
@@ -854,9 +857,9 @@
    */
   void LoadClassId(Register result, Register object);
 
-  void LoadClassById(Register result, Register class_id, Register pp);
+  void LoadClassById(Register result, Register class_id);
 
-  void LoadClass(Register result, Register object, Register pp);
+  void LoadClass(Register result, Register object);
 
   void CompareClassId(Register object, intptr_t class_id);
 
@@ -923,7 +926,7 @@
     buffer_.FinalizeInstructions(region);
   }
 
-  void LoadPoolPointer(Register pp);
+  void LoadPoolPointer(Register pp = PP);
 
   // Set up a Dart frame on entry with a frame pointer and PC information to
   // enable easy access to the RawInstruction object of code corresponding
@@ -944,7 +947,6 @@
   //   ...
   //   pushq r15
   //   .....
-  void EnterDartFrame(intptr_t frame_size);
   void EnterDartFrameWithInfo(intptr_t frame_size,
                               Register new_pp, Register pc_marker_override);
   void LeaveDartFrame();
@@ -1001,26 +1003,26 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid,
                             Label* trace,
-                            bool near_jump);
+                            bool near_jump,
+                            bool inline_isolate = true);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
   // Allocated instance is returned in 'instance_reg'.
   // Only the tags field of the object is initialized.
-  // Loads large immediates from the object pool with pool pointer in PP if it
-  // is not kNoRegister
   void TryAllocate(const Class& cls,
                    Label* failure,
                    bool near_jump,
                    Register instance_reg,
-                   Register pp);
+                   Register temp);
 
   void TryAllocateArray(intptr_t cid,
                         intptr_t instance_size,
                         Label* failure,
                         bool near_jump,
                         Register instance,
-                        Register end_address);
+                        Register end_address,
+                        Register temp);
 
   // Debugging and bringup support.
   void Stop(const char* message, bool fixed_length_encoding = false);
@@ -1073,15 +1075,12 @@
   };
 
   GrowableArray<CodeComment*> comments_;
-  bool allow_constant_pool_;
+  bool constant_pool_allowed_;
 
   intptr_t FindImmediate(int64_t imm);
   bool CanLoadFromObjectPool(const Object& object) const;
-  void LoadObjectHelper(Register dst,
-                        const Object& obj,
-                        Register pp,
-                        bool is_unique);
-  void LoadWordFromPoolOffset(Register dst, Register pp, int32_t offset);
+  void LoadObjectHelper(Register dst, const Object& obj, bool is_unique);
+  void LoadWordFromPoolOffset(Register dst, int32_t offset);
 
   inline void EmitUint8(uint8_t value);
   inline void EmitInt32(int32_t value);
@@ -1132,7 +1131,7 @@
                      Register value,
                      FieldContent old_content);
   // Unaware of write barrier (use StoreInto* methods for storing to objects).
-  void MoveImmediate(const Address& dst, const Immediate& imm, Register pp);
+  void MoveImmediate(const Address& dst, const Immediate& imm);
 
   void ComputeCounterAddressesForCid(intptr_t cid,
                                      Heap::Space space,
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index a10b52e..cd99603 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -2026,7 +2026,7 @@
     double b;
   } constant0 = { 1.0, 2.0 };
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
   __ movups(XMM10, Address(RAX, 0));
   __ negatepd(XMM10);
@@ -2049,7 +2049,7 @@
     double b;
   } constant0 = { -1.0, 2.0 };
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
   __ movups(XMM10, Address(RAX, 0));
   __ abspd(XMM10);
@@ -2496,7 +2496,7 @@
 
 ASSEMBLER_TEST_GENERATE(PackedNegate, assembler) {
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ movl(RAX, Immediate(bit_cast<int32_t, float>(12.3f)));
   __ movd(XMM0, RAX);
   __ shufps(XMM0, XMM0, Immediate(0x0));
@@ -2516,7 +2516,7 @@
 
 ASSEMBLER_TEST_GENERATE(PackedAbsolute, assembler) {
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ movl(RAX, Immediate(bit_cast<int32_t, float>(-15.3f)));
   __ movd(XMM0, RAX);
   __ shufps(XMM0, XMM0, Immediate(0x0));
@@ -2536,7 +2536,7 @@
 
 ASSEMBLER_TEST_GENERATE(PackedSetWZero, assembler) {
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(12.3f)));
   __ zerowps(XMM0);
   __ shufps(XMM0, XMM0, Immediate(0xFF));  // Copy the W lane which is now 0.0.
@@ -2658,8 +2658,8 @@
   } constant1 =
       { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadImmediate(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)), PP);
+  __ LoadPoolPointer();
+  __ LoadImmediate(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
   __ movups(XMM9, Address(RAX, 0));
   __ notps(XMM9);
   __ movaps(XMM0, XMM9);
@@ -3067,26 +3067,26 @@
   Label fail;
   __ EnterFrame(0);
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadObject(RAX, obj, PP);
-  __ CompareObject(RAX, obj, PP);
+  __ LoadPoolPointer();
+  __ LoadObject(RAX, obj);
+  __ CompareObject(RAX, obj);
   __ j(NOT_EQUAL, &fail);
-  __ LoadObject(RCX, obj, PP);
-  __ CompareObject(RCX, obj, PP);
+  __ LoadObject(RCX, obj);
+  __ CompareObject(RCX, obj);
   __ j(NOT_EQUAL, &fail);
   const Smi& smi = Smi::ZoneHandle(Smi::New(15));
-  __ LoadObject(RCX, smi, PP);
-  __ CompareObject(RCX, smi, PP);
+  __ LoadObject(RCX, smi);
+  __ CompareObject(RCX, smi);
   __ j(NOT_EQUAL, &fail);
   __ pushq(RAX);
-  __ StoreObject(Address(RSP, 0), obj, PP);
+  __ StoreObject(Address(RSP, 0), obj);
   __ popq(RCX);
-  __ CompareObject(RCX, obj, PP);
+  __ CompareObject(RCX, obj);
   __ j(NOT_EQUAL, &fail);
   __ pushq(RAX);
-  __ StoreObject(Address(RSP, 0), smi, PP);
+  __ StoreObject(Address(RSP, 0), smi);
   __ popq(RCX);
-  __ CompareObject(RCX, smi, PP);
+  __ CompareObject(RCX, smi);
   __ j(NOT_EQUAL, &fail);
   __ movl(RAX, Immediate(1));  // OK
   __ popq(PP);  // Restore caller's pool pointer.
@@ -3307,7 +3307,7 @@
 // Called from assembler_test.cc.
 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ pushq(THR);
   __ movq(THR, CallingConventions::kArg4Reg);
   __ pushq(CTX);
@@ -3433,7 +3433,7 @@
 
 ASSEMBLER_TEST_GENERATE(DoubleAbs, assembler) {
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   __ DoubleAbs(XMM0);
   __ popq(PP);  // Restore caller's pool pointer.
   __ ret();
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index ef224e2..26618b5 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -229,8 +229,6 @@
       return NULL;
     case Token::kEQ:
     case Token::kNE:
-    case Token::kEQ_STRICT:
-    case Token::kNE_STRICT:
       // The comparison is a compile time const if both operands are either a
       // number, string, or boolean value (but not necessarily the same type).
       if ((left_val->IsNumber() ||
@@ -244,6 +242,11 @@
         return &Bool::False();
       }
       return NULL;
+    case Token::kEQ_STRICT:
+    case Token::kNE_STRICT:
+      // identical(a, b) is a compile time const if both operands are
+      // compile time constants, regardless of their type.
+      return &Bool::True();
     default:
       return NULL;
   }
diff --git a/runtime/vm/base_isolate.h b/runtime/vm/base_isolate.h
index fc6de2b..33c5f4d3 100644
--- a/runtime/vm/base_isolate.h
+++ b/runtime/vm/base_isolate.h
@@ -26,28 +26,6 @@
   void AssertCurrentThreadIsMutator() const {}
 #endif  // DEBUG
 
-  int32_t no_safepoint_scope_depth() const {
-#if defined(DEBUG)
-    return no_safepoint_scope_depth_;
-#else
-    return 0;
-#endif
-  }
-
-  void IncrementNoSafepointScopeDepth() {
-#if defined(DEBUG)
-    ASSERT(no_safepoint_scope_depth_ < INT_MAX);
-    no_safepoint_scope_depth_ += 1;
-#endif
-  }
-
-  void DecrementNoSafepointScopeDepth() {
-#if defined(DEBUG)
-    ASSERT(no_safepoint_scope_depth_ > 0);
-    no_safepoint_scope_depth_ -= 1;
-#endif
-  }
-
   int32_t no_callback_scope_depth() const {
     return no_callback_scope_depth_;
   }
@@ -69,20 +47,14 @@
  protected:
   BaseIsolate()
       : mutator_thread_(NULL),
-#if defined(DEBUG)
-        no_safepoint_scope_depth_(0),
-#endif
-        no_callback_scope_depth_(0)
-  {}
+        no_callback_scope_depth_(0) {
+  }
 
   ~BaseIsolate() {
     // Do not delete stack resources: top_resource_ and current_zone_.
   }
 
   Thread* mutator_thread_;
-#if defined(DEBUG)
-  int32_t no_safepoint_scope_depth_;
-#endif
   int32_t no_callback_scope_depth_;
 
  private:
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index a6d6c18..7f51ac4 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -258,6 +258,68 @@
 }
 
 
+// Emulates DartUtils::PrepareForScriptLoading.
+static Dart_Handle PreparePackageRoot(const char* package_root,
+                                      Dart_Handle builtin_lib) {
+  // First ensure all required libraries are available.
+  Dart_Handle url = NewString(bin::DartUtils::kCoreLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle core_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(core_lib);
+  url = NewString(bin::DartUtils::kAsyncLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle async_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(async_lib);
+  url = NewString(bin::DartUtils::kIsolateLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle isolate_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(isolate_lib);
+  url = NewString(bin::DartUtils::kInternalLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle internal_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(internal_lib);
+  Dart_Handle io_lib =
+      bin::Builtin::LoadAndCheckLibrary(bin::Builtin::kIOLibrary);
+  DART_CHECK_VALID(io_lib);
+
+  // We need to ensure that all the scripts loaded so far are finalized
+  // as we are about to invoke some Dart code below to setup closures.
+  Dart_Handle result = Dart_FinalizeLoading(false);
+  DART_CHECK_VALID(result);
+
+  // Necessary parts from PrepareBuiltinLibrary.
+  // Setup the internal library's 'internalPrint' function.
+  result = Dart_Invoke(builtin_lib, NewString("_getPrintClosure"), 0, NULL);
+  DART_CHECK_VALID(result);
+  result = Dart_SetField(internal_lib, NewString("_printClosure"), result);
+  DART_CHECK_VALID(result);
+#if defined(TARGET_OS_WINDOWS)
+    result = Dart_SetField(builtin_lib, NewString("_isWindows"), Dart_True());
+    DART_CHECK_VALID(result);
+#endif  // defined(TARGET_OS_WINDOWS)
+  // Set current working directory.
+  result = bin::DartUtils::SetWorkingDirectory(builtin_lib);
+  DART_CHECK_VALID(result);
+  // Set the package root for builtin.dart.
+  result = NewString(package_root);
+  DART_CHECK_VALID(result);
+  const int kNumArgs = 1;
+  Dart_Handle dart_args[kNumArgs];
+  dart_args[0] = result;
+  result = Dart_Invoke(builtin_lib,
+                       NewString("_setPackageRoot"),
+                       kNumArgs,
+                       dart_args);
+  DART_CHECK_VALID(result);
+
+  bin::DartUtils::PrepareAsyncLibrary(async_lib, isolate_lib);
+  bin::DartUtils::PrepareCoreLibrary(core_lib, builtin_lib, false);
+  bin::DartUtils::PrepareIsolateLibrary(isolate_lib);
+  bin::DartUtils::PrepareIOLibrary(io_lib);
+  return Dart_True();
+}
+
+
 static Dart_NativeFunction NativeResolver(Dart_Handle name,
                                           int arg_count,
                                           bool* auto_setup_scope) {
@@ -280,7 +342,8 @@
   const char* path_separator = File::PathSeparator();
   OS::SNPrint(buffer, 2048, packages_path,
               executable_path, path_separator, path_separator);
-  bin::DartUtils::PrepareForScriptLoading(buffer, false, false, builtin_lib);
+  Dart_Handle result = PreparePackageRoot(buffer, builtin_lib);
+  DART_CHECK_VALID(result);
 }
 
 BENCHMARK(Dart2JSCompileAll) {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index cab3102..0358a00 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -70,6 +70,7 @@
   V(Bigint_allocate, 4)                                                        \
   V(Developer_debugger, 2)                                                     \
   V(Developer_inspect, 1)                                                      \
+  V(Developer_log, 8)                                                          \
   V(Double_getIsNegative, 1)                                                   \
   V(Double_getIsInfinite, 1)                                                   \
   V(Double_getIsNaN, 1)                                                        \
diff --git a/runtime/vm/cha.h b/runtime/vm/cha.h
index b4007b2..fac6577 100644
--- a/runtime/vm/cha.h
+++ b/runtime/vm/cha.h
@@ -19,7 +19,7 @@
 class CHA : public StackResource {
  public:
   explicit CHA(Thread* thread)
-      : StackResource(thread->isolate()),
+      : StackResource(thread),
         thread_(thread),
         leaf_classes_(thread->zone(), 1),
         previous_(thread->cha()) {
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index c4dbfe8..28b7f75 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -450,10 +450,8 @@
 }
 
 
-ClassHeapStats** ClassTable::StateAddressFor(intptr_t cid,
-                                             intptr_t* state_offset) {
-  *state_offset = ClassOffsetFor(cid)+ ClassHeapStats::state_offset();
-  return TableAddressFor(cid);
+intptr_t ClassTable::StateOffsetFor(intptr_t cid) {
+  return ClassOffsetFor(cid)+ ClassHeapStats::state_offset();
 }
 
 
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 93fb514..aebf15c 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -155,7 +155,7 @@
     return table_[index];
   }
 
-  intptr_t IsValidIndex(intptr_t index) const {
+  bool IsValidIndex(intptr_t index) const {
     return (index > 0) && (index < top_);
   }
 
@@ -205,8 +205,7 @@
   static intptr_t CounterOffsetFor(intptr_t cid, bool is_new_space);
 
   // Used by the generated code.
-  ClassHeapStats** StateAddressFor(intptr_t cid,
-                                   intptr_t* state_offset);
+  static intptr_t StateOffsetFor(intptr_t cid);
 
   // Used by the generated code.
   static intptr_t SizeOffsetFor(intptr_t cid, bool is_new_space);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index dd977b2..5df3636 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -23,6 +23,7 @@
 #include "vm/runtime_entry.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
+#include "vm/thread_registry.h"
 #include "vm/verifier.h"
 
 namespace dart {
@@ -1053,23 +1054,72 @@
   // a zigzagged lookup to see if this call failed because of an arity mismatch,
   // need for conversion, or there really is no such method.
 
+#define NO_SUCH_METHOD()                                                       \
+  const Object& result = Object::Handle(                                       \
+      DartEntry::InvokeNoSuchMethod(receiver,                                  \
+                                    target_name,                               \
+                                    orig_arguments,                            \
+                                    orig_arguments_desc));                     \
+  CheckResultError(result);                                                    \
+  arguments.SetReturn(result);                                                 \
+
+#define CLOSURIZE(some_function)                                               \
+  const Function& closure_function =                                           \
+      Function::Handle(some_function.ImplicitClosureFunction());               \
+  const Object& result =                                                       \
+      Object::Handle(closure_function.ImplicitInstanceClosure(receiver));      \
+  arguments.SetReturn(result);                                                 \
+
   const bool is_getter = Field::IsGetterName(target_name);
   if (is_getter) {
-    // o.foo failed, closurize o.foo() if it exists
-    const String& field_name =
-      String::Handle(Field::NameFromGetter(target_name));
+    // o.foo (o.get:foo) failed, closurize o.foo() if it exists. Or,
+    // o#foo (o.get:#foo) failed, closurizee o.foo or o.foo(), whichever is
+    // encountered first on the inheritance chain. Or,
+    // o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists.
+    String& field_name =
+        String::Handle(Field::NameFromGetter(target_name));
+
+    const bool is_extractor = field_name.CharAt(0) == '#';
+    if (is_extractor) {
+      field_name = String::SubString(field_name, 1);
+      ASSERT(!Field::IsGetterName(field_name));
+      field_name = Symbols::New(field_name);
+
+      if (!Field::IsSetterName(field_name)) {
+        const String& getter_name =
+            String::Handle(Field::GetterName(field_name));
+
+        // Zigzagged lookup: closure either a regular method or a getter.
+        while (!cls.IsNull()) {
+          function ^= cls.LookupDynamicFunction(field_name);
+          if (!function.IsNull()) {
+            CLOSURIZE(function);
+            return;
+          }
+          function ^= cls.LookupDynamicFunction(getter_name);
+          if (!function.IsNull()) {
+            CLOSURIZE(function);
+            return;
+          }
+          cls = cls.SuperClass();
+        }
+        NO_SUCH_METHOD();
+        return;
+      } else {
+        // Fall through for non-ziggaged lookup for o#foo=.
+      }
+    }
+
     while (!cls.IsNull()) {
       function ^= cls.LookupDynamicFunction(field_name);
       if (!function.IsNull()) {
-        const Function& closure_function =
-            Function::Handle(function.ImplicitClosureFunction());
-        const Object& result =
-            Object::Handle(closure_function.ImplicitInstanceClosure(receiver));
-        arguments.SetReturn(result);
+        CLOSURIZE(function);
         return;
       }
       cls = cls.SuperClass();
     }
+
+    // Fall through for noSuchMethod
   } else {
     // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
     // number of arguments, or try (o.foo).call(...)
@@ -1116,14 +1166,10 @@
     }
   }
 
-  // Handle noSuchMethod invocation.
-  const Object& result = Object::Handle(
-      DartEntry::InvokeNoSuchMethod(receiver,
-                                    target_name,
-                                    orig_arguments,
-                                    orig_arguments_desc));
-  CheckResultError(result);
-  arguments.SetReturn(result);
+  NO_SUCH_METHOD();
+
+#undef NO_SUCH_METHOD
+#undef CLOSURIZE
 }
 
 
@@ -1299,11 +1345,14 @@
   }
 
   uword interrupt_bits = isolate->GetAndClearInterrupts();
-  if ((interrupt_bits & Isolate::kStoreBufferInterrupt) != 0) {
-    if (FLAG_verbose_gc) {
-      OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
+  if ((interrupt_bits & Isolate::kVMInterrupt) != 0) {
+    isolate->thread_registry()->CheckSafepoint();
+    if (isolate->store_buffer()->Overflowed()) {
+      if (FLAG_verbose_gc) {
+        OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
+      }
+      isolate->heap()->CollectGarbage(Heap::kNew);
     }
-    isolate->heap()->CollectGarbage(Heap::kNew);
   }
   if ((interrupt_bits & Isolate::kMessageInterrupt) != 0) {
     bool ok = isolate->message_handler()->HandleOOBMessages();
@@ -1508,7 +1557,7 @@
   alloc_class ^= stub.owner();
   Code& alloc_stub = Code::Handle(isolate, alloc_class.allocation_stub());
   if (alloc_stub.IsNull()) {
-    alloc_stub = isolate->stub_code()->GetAllocationStubForClass(alloc_class);
+    alloc_stub = StubCode::GetAllocationStubForClass(alloc_class);
     ASSERT(!CodePatcher::IsEntryPatched(alloc_stub));
   }
   const Instructions& instrs =
diff --git a/runtime/vm/code_patcher_arm64_test.cc b/runtime/vm/code_patcher_arm64_test.cc
index e02fee9..bb7008a 100644
--- a/runtime/vm/code_patcher_arm64_test.cc
+++ b/runtime/vm/code_patcher_arm64_test.cc
@@ -39,10 +39,11 @@
                                                          15,
                                                          1));
 
-  __ LoadObject(R5, ic_data, PP);
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  ExternalLabel target_label(stub_code->OneArgCheckInlineCacheEntryPoint());
-  __ BranchLinkPatchable(&target_label);
+  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
+  __ set_constant_pool_allowed(true);
+
+  __ LoadObject(R5, ic_data);
+  __ BranchLinkPatchable(*StubCode::OneArgCheckInlineCache_entry());
   __ ret();
 }
 
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index 1603e7c..525b3db 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -39,10 +39,11 @@
                                                          15,
                                                          1));
 
+  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
+  __ set_constant_pool_allowed(true);
+
   __ LoadObject(R5, ic_data);
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  ExternalLabel target_label(stub_code->OneArgCheckInlineCacheEntryPoint());
-  __ BranchLinkPatchable(&target_label);
+  __ BranchLinkPatchable(*StubCode::OneArgCheckInlineCache_entry());
   __ Ret();
 }
 
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index c0321e8..a9c62f4 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -40,9 +40,7 @@
                                                          1));
 
   __ LoadObject(ECX, ic_data);
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  ExternalLabel target_label(stub_code->OneArgCheckInlineCacheEntryPoint());
-  __ call(&target_label);
+  __ Call(*StubCode::OneArgCheckInlineCache_entry());
   __ ret();
 }
 
diff --git a/runtime/vm/code_patcher_mips_test.cc b/runtime/vm/code_patcher_mips_test.cc
index 3c73a3c..78e698b 100644
--- a/runtime/vm/code_patcher_mips_test.cc
+++ b/runtime/vm/code_patcher_mips_test.cc
@@ -40,9 +40,7 @@
                                                          1));
 
   __ LoadObject(S5, ic_data);
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  ExternalLabel target_label(stub_code->OneArgCheckInlineCacheEntryPoint());
-  __ BranchLinkPatchable(&target_label);
+  __ BranchLinkPatchable(*StubCode::OneArgCheckInlineCache_entry());
   __ Ret();
 }
 
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index f6ad37f..ca98231 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -39,10 +39,11 @@
                                                          15,
                                                          1));
 
-  __ LoadObject(RBX, ic_data, PP);
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  ExternalLabel target_label(stub_code->OneArgCheckInlineCacheEntryPoint());
-  __ CallPatchable(&target_label);
+  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
+  __ set_constant_pool_allowed(true);
+
+  __ LoadObject(RBX, ic_data);
+  __ CallPatchable(*StubCode::OneArgCheckInlineCache_entry());
   __ ret();
 }
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 491b571..1eb55f3 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -744,6 +744,12 @@
                  inlined_id_array.Length() * sizeof(uword));
         code.SetInlinedIdToFunction(inlined_id_array);
 
+        const Array& caller_inlining_id_map_array =
+            Array::Handle(isolate, graph_compiler.CallerInliningIdMap());
+        INC_STAT(isolate, total_code_size,
+                 caller_inlining_id_map_array.Length() * sizeof(uword));
+        code.SetInlinedCallerIdMap(caller_inlining_id_map_array);
+
         graph_compiler.FinalizePcDescriptors(code);
         code.set_deopt_info_array(deopt_info_array);
 
@@ -971,6 +977,27 @@
 }
 
 
+#if defined(DEBUG)
+// Verifies that the inliner is always in the list of inlined functions.
+// If this fails run with --trace-inlining-intervals to get more information.
+static void CheckInliningIntervals(const Function& function) {
+  const Code& code = Code::Handle(function.CurrentCode());
+  const Array& intervals = Array::Handle(code.GetInlinedIntervals());
+  if (intervals.IsNull() || (intervals.Length() == 0)) return;
+  Smi& start = Smi::Handle();
+  GrowableArray<Function*> inlined_functions;
+  for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) {
+    start ^= intervals.At(i + Code::kInlIntStart);
+    ASSERT(!start.IsNull());
+    if (start.IsNull()) continue;
+    code.GetInlinedFunctionsAt(start.Value(), &inlined_functions);
+    ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() ==
+           function.raw());
+  }
+}
+#endif
+
+
 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
                                        const Function& function,
                                        bool optimized,
@@ -1059,6 +1086,9 @@
       DisassembleCode(function, true);
       ISL_Print("*** END CODE\n");
     }
+#if defined(DEBUG)
+    CheckInliningIntervals(function);
+#endif
     return Error::null();
   } else {
     Thread* const thread = Thread::Current();
@@ -1081,6 +1111,13 @@
   VMTagScope tagScope(isolate, VMTag::kCompileUnoptimizedTagId);
   TIMELINE_FUNCTION_COMPILATION_DURATION(isolate, "Function", function);
 
+  if (!isolate->compilation_allowed()) {
+    FATAL3("Precompilation missed function %s (%" Pd ", %s)\n",
+           function.ToLibNamePrefixedQualifiedCString(),
+           function.token_pos(),
+           Function::KindToCString(function.kind()));
+  }
+
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
 
@@ -1241,6 +1278,33 @@
 }
 
 
+void Compiler::CompileStaticInitializer(const Field& field) {
+  ASSERT(field.is_static());
+  if (field.initializer() != Function::null()) {
+    // TODO(rmacnak): Investigate why this happens for _enum_names.
+    OS::Print("Warning: Ignoring repeated request for initializer for %s\n",
+              field.ToCString());
+    return;
+  }
+  ASSERT(field.initializer() == Function::null());
+  Isolate* isolate = Isolate::Current();
+  StackZone zone(isolate);
+
+  ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
+
+  parsed_function->AllocateVariables();
+  // Non-optimized code generator.
+  DartCompilationPipeline pipeline;
+  CompileParsedFunctionHelper(&pipeline,
+                              parsed_function,
+                              false,  // optimized
+                              Isolate::kNoDeoptId);
+
+  const Function& initializer = parsed_function->function();
+  field.set_initializer(initializer);
+}
+
+
 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
   ASSERT(field.is_static());
   // The VM sets the field's value to transiton_sentinel prior to
@@ -1248,23 +1312,31 @@
   ASSERT(field.value() == Object::transition_sentinel().raw());
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
-    Isolate* const isolate = Isolate::Current();
-    StackZone zone(isolate);
-    ParsedFunction* parsed_function =
-        Parser::ParseStaticFieldInitializer(field);
+    Function& initializer = Function::Handle(field.initializer());
 
-    parsed_function->AllocateVariables();
-    // Non-optimized code generator.
-    DartCompilationPipeline pipeline;
-    CompileParsedFunctionHelper(&pipeline,
-                                parsed_function,
-                                false,
-                                Isolate::kNoDeoptId);
-    // Eagerly create local var descriptors.
-    CreateLocalVarDescriptors(*parsed_function);
+    // Under precompilation, the initializer may have already been compiled, in
+    // which case use it. Under lazy compilation or early in precompilation, the
+    // initializer has not yet been created, so create it now, but don't bother
+    // remembering it because it won't be used again.
+    if (initializer.IsNull()) {
+      Isolate* const isolate = Isolate::Current();
+      StackZone zone(isolate);
+      ParsedFunction* parsed_function =
+          Parser::ParseStaticFieldInitializer(field);
 
+      parsed_function->AllocateVariables();
+      // Non-optimized code generator.
+      DartCompilationPipeline pipeline;
+      CompileParsedFunctionHelper(&pipeline,
+                                  parsed_function,
+                                  false,  // optimized
+                                  Isolate::kNoDeoptId);
+      // Eagerly create local var descriptors.
+      CreateLocalVarDescriptors(*parsed_function);
+
+      initializer = parsed_function->function().raw();
+    }
     // Invoke the function to evaluate the expression.
-    const Function& initializer = parsed_function->function();
     const Object& result = PassiveObject::Handle(
         DartEntry::InvokeFunction(initializer, Object::empty_array()));
     return result.raw();
diff --git a/runtime/vm/compiler.h b/runtime/vm/compiler.h
index e8052c7..746d5d8 100644
--- a/runtime/vm/compiler.h
+++ b/runtime/vm/compiler.h
@@ -72,6 +72,7 @@
   // The return value is either a RawInstance on success or a RawError
   // on compilation failure.
   static RawObject* EvaluateStaticInitializer(const Field& field);
+  static void CompileStaticInitializer(const Field& field);
 
   // Generates local var descriptors and sets it in 'code'. Do not call if the
   // local var descriptor already exists.
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index 18a47ac..aa5b892 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -90,9 +90,8 @@
   EXPECT(!cls.IsNull());
 
   Isolate* isolate = Isolate::Current();
-  StubCode* stub_code = isolate->stub_code();
   const Code& stub = Code::Handle(isolate,
-                                  stub_code->GetAllocationStubForClass(cls));
+                                  StubCode::GetAllocationStubForClass(cls));
   Class& owner = Class::Handle();
   owner ^= stub.owner();
   owner.DisableAllocationStub();
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 35bab84..29818e1 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -735,7 +735,7 @@
 
 
 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
-  const Definition* def = instr->value()->definition();
+  Definition* def = instr->value()->definition();
   const Object& value = def->constant_value();
   if (IsNonConstant(value)) {
     const AbstractType& checked_type = instr->type();
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index f1834b8..f84cf68 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -111,7 +111,6 @@
 const Register TMP2 = R17;
 const Register CTX = R28;  // Location of current context at method entry.
 const Register PP = R27;  // Caches object pool pointer in generated code.
-const Register kNoPP = kNoRegister;
 const Register FPREG = FP;  // Frame pointer register.
 const Register SPREG = R18;  // Stack pointer register.
 const Register LRREG = LR;  // Link register.
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 7bb4fe3..60439a2 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -33,18 +33,8 @@
 
 namespace dart {
 
-DEFINE_FLAG(int, new_gen_semi_max_size, (kWordSize <= 4) ? 16 : 32,
-            "Max size of new gen semi space in MB");
-DEFINE_FLAG(int, old_gen_heap_size, 0,
-            "Max size of old gen heap size in MB, or 0 for unlimited,"
-            "e.g: --old_gen_heap_size=1024 allows up to 1024MB old gen heap");
-DEFINE_FLAG(int, external_max_size, (kWordSize <= 4) ? 512 : 1024,
-            "Max total size of external allocations in MB, or 0 for unlimited,"
-            "e.g: --external_max_size=1024 allows up to 1024MB of externals");
-
 DEFINE_FLAG(bool, keep_code, false,
             "Keep deoptimized code for profiling.");
-
 DECLARE_FLAG(bool, print_class_table);
 DECLARE_FLAG(bool, trace_isolates);
 
@@ -129,10 +119,6 @@
 
     StackZone zone(vm_isolate_);
     HandleScope handle_scope(vm_isolate_);
-    Heap::Init(vm_isolate_,
-               0,  // New gen size 0; VM isolate should only allocate in old.
-               FLAG_old_gen_heap_size * MBInWords,
-               FLAG_external_max_size * MBInWords);
     Object::InitNull(vm_isolate_);
     ObjectStore::Init(vm_isolate_);
     TargetCPUFeatures::InitOnce();
@@ -250,10 +236,6 @@
   ASSERT(isolate != NULL);
   StackZone zone(isolate);
   HandleScope handle_scope(isolate);
-  Heap::Init(isolate,
-             FLAG_new_gen_semi_max_size * MBInWords,
-             FLAG_old_gen_heap_size * MBInWords,
-             FLAG_external_max_size * MBInWords);
   ObjectStore::Init(isolate);
 
   // Setup for profiling.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index b701c0e..038bfc8 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1364,28 +1364,31 @@
   }
   Isolate* isolate = Dart::CreateIsolate(isolate_name, *flags);
   free(isolate_name);
-  StackZone zone(isolate);
-  HANDLESCOPE(isolate);
-  // We enter an API scope here as InitializeIsolate could compile some
-  // bootstrap library files which call out to a tag handler that may create
-  // Api Handles when an error is encountered.
-  Dart_EnterScope();
-  const Error& error_obj =
-      Error::Handle(isolate, Dart::InitializeIsolate(snapshot, callback_data));
-  if (error_obj.IsNull()) {
-#if defined(DART_NO_SNAPSHOT)
-    if (FLAG_check_function_fingerprints) {
-      Library::CheckFunctionFingerprints();
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    // We enter an API scope here as InitializeIsolate could compile some
+    // bootstrap library files which call out to a tag handler that may create
+    // Api Handles when an error is encountered.
+    Dart_EnterScope();
+    const Error& error_obj =
+        Error::Handle(isolate,
+                      Dart::InitializeIsolate(snapshot, callback_data));
+    if (error_obj.IsNull()) {
+  #if defined(DART_NO_SNAPSHOT)
+      if (FLAG_check_function_fingerprints) {
+        Library::CheckFunctionFingerprints();
+      }
+  #endif  // defined(DART_NO_SNAPSHOT).
+      // We exit the API scope entered above.
+      Dart_ExitScope();
+      START_TIMER(isolate, time_total_runtime);
+      return Api::CastIsolate(isolate);
     }
-#endif  // defined(DART_NO_SNAPSHOT).
+    *error = strdup(error_obj.ToErrorCString());
     // We exit the API scope entered above.
     Dart_ExitScope();
-    START_TIMER(isolate, time_total_runtime);
-    return Api::CastIsolate(isolate);
   }
-  *error = strdup(error_obj.ToErrorCString());
-  // We exit the API scope entered above.
-  Dart_ExitScope();
   Dart::ShutdownIsolate();
   return reinterpret_cast<Dart_Isolate>(NULL);
 }
@@ -1439,7 +1442,7 @@
   CHECK_NO_ISOLATE(Isolate::Current());
   // TODO(16615): Validate isolate parameter.
   Isolate* iso = reinterpret_cast<Isolate*>(isolate);
-  if (iso->mutator_thread() != NULL) {
+  if (iso->HasMutatorThread()) {
     FATAL("Multiple mutators within one isolate is not supported.");
   }
   Thread::EnsureInit();
@@ -1773,19 +1776,20 @@
 // --- Scopes ----
 
 DART_EXPORT void Dart_EnterScope() {
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
   ApiLocalScope* new_scope = state->reusable_scope();
   if (new_scope == NULL) {
     new_scope = new ApiLocalScope(state->top_scope(),
-                                  isolate->top_exit_frame_info());
+                                  thread->top_exit_frame_info());
     ASSERT(new_scope != NULL);
   } else {
-    new_scope->Reinit(isolate,
+    new_scope->Reinit(thread,
                       state->top_scope(),
-                      isolate->top_exit_frame_info());
+                      thread->top_exit_frame_info());
     state->set_reusable_scope(NULL);
   }
   state->set_top_scope(new_scope);  // New scope is now the top scope.
@@ -1793,14 +1797,15 @@
 
 
 DART_EXPORT void Dart_ExitScope() {
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
   CHECK_ISOLATE_SCOPE(isolate);
   ApiState* state = isolate->api_state();
   ApiLocalScope* scope = state->top_scope();
   ApiLocalScope* reusable_scope = state->reusable_scope();
   state->set_top_scope(scope->previous());  // Reset top scope to previous.
   if (reusable_scope == NULL) {
-    scope->Reset(isolate);  // Reset the old scope which we just exited.
+    scope->Reset(thread);  // Reset the old scope which we just exited.
     state->set_reusable_scope(scope);
   } else {
     ASSERT(reusable_scope != scope);
@@ -3587,7 +3592,8 @@
                                                   Dart_TypedData_Type* type,
                                                   void** data,
                                                   intptr_t* len) {
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
   DARTSCOPE(isolate);
   intptr_t class_id = Api::ClassId(object);
   if (!RawObject::IsExternalTypedDataClassId(class_id) &&
@@ -3625,7 +3631,7 @@
     ASSERT(!obj.IsNull());
     length = obj.Length();
     size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
-    isolate->IncrementNoSafepointScopeDepth();
+    thread->IncrementNoSafepointScopeDepth();
     START_NO_CALLBACK_SCOPE(isolate);
     data_tmp = obj.DataAddr(0);
   } else {
@@ -3639,7 +3645,7 @@
     val ^= TypedDataView::OffsetInBytes(view_obj);
     intptr_t offset_in_bytes = val.Value();
     const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj));
-    isolate->IncrementNoSafepointScopeDepth();
+    thread->IncrementNoSafepointScopeDepth();
     START_NO_CALLBACK_SCOPE(isolate);
     if (TypedData::IsTypedData(obj)) {
       const TypedData& data_obj = TypedData::Cast(obj);
@@ -3677,7 +3683,8 @@
 
 
 DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) {
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
   DARTSCOPE(isolate);
   intptr_t class_id = Api::ClassId(object);
   if (!RawObject::IsExternalTypedDataClassId(class_id) &&
@@ -3686,7 +3693,7 @@
     RETURN_TYPE_ERROR(isolate, object, 'TypedData');
   }
   if (!RawObject::IsExternalTypedDataClassId(class_id)) {
-    isolate->DecrementNoSafepointScopeDepth();
+    thread->DecrementNoSafepointScopeDepth();
     END_NO_CALLBACK_SCOPE(isolate);
   }
   if (FLAG_verify_acquired_data) {
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 2ee1c37..aa08099 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -481,6 +481,9 @@
     object_id = NextAvailableObjectId();
   }
 
+  intptr_t tags = ReadTags();
+  USE(tags);
+
   // Reading of regular dart instances has limited support in order to
   // read typed data views.
   if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
@@ -502,10 +505,6 @@
     AddBackRef(object_id, value, kIsNotDeserialized);
     return value;
   }
-
-  intptr_t tags = ReadTags();
-  USE(tags);
-
   return ReadInternalVMObject(class_id, object_id);
 }
 
@@ -682,6 +681,13 @@
       AddBackRef(object_id, object, kIsDeserialized);
       return object;
     }
+    case kCapabilityCid: {
+      int64_t id = Read<int64_t>();
+      Dart_CObject* object = AllocateDartCObject(Dart_CObject_kCapability);
+      object->value.as_capability.id = id;
+      AddBackRef(object_id, object, kIsDeserialized);
+      return object;
+    }
 
 #define READ_TYPED_DATA_HEADER(type)                                           \
       intptr_t len = ReadSmiValue();                                           \
@@ -1060,6 +1066,7 @@
     WriteInlinedHeader(object);
     // Write out the class information.
     WriteIndexedObject(kArrayCid);
+    WriteTags(0);
     // Write out the length information.
     WriteSmi(array_length);
     // Add object to forward list so that this object is serialized later.
@@ -1268,6 +1275,13 @@
       WriteRawPointerValue(reinterpret_cast<intptr_t>(callback));
       break;
     }
+    case Dart_CObject_kCapability: {
+      WriteInlinedHeader(object);
+      WriteIndexedObject(kCapabilityCid);
+      WriteTags(0);
+      Write<uint64_t>(object->value.as_capability.id);
+      break;
+    }
     default:
       UNREACHABLE();
   }
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index 4f293540..207aab4 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -35,11 +35,11 @@
  public:
   // Create an empty zone.
   ApiZone() : zone_() {
-    Isolate* isolate = Isolate::Current();
-    Zone* current_zone = isolate != NULL ? isolate->current_zone() : NULL;
-    zone_.Link(current_zone);
-    if (isolate != NULL) {
-      isolate->set_current_zone(&zone_);
+    Thread* thread = Thread::Current();
+    Zone* zone = thread != NULL ? thread->zone() : NULL;
+    zone_.Link(zone);
+    if (thread != NULL) {
+      thread->set_zone(&zone_);
     }
 #ifdef DEBUG
     if (FLAG_trace_zones) {
@@ -52,15 +52,15 @@
 
   // Delete all memory associated with the zone.
   ~ApiZone() {
-    Isolate* isolate = Isolate::Current();
+    Thread* thread = Thread::Current();
 #if defined(DEBUG)
-    if (isolate == NULL) {
+    if (thread == NULL) {
       ASSERT(zone_.handles()->CountScopedHandles() == 0);
       ASSERT(zone_.handles()->CountZoneHandles() == 0);
     }
 #endif
-    if ((isolate != NULL) && (isolate->current_zone() == &zone_)) {
-      isolate->set_current_zone(zone_.previous_);
+    if ((thread != NULL) && (thread->zone() == &zone_)) {
+      thread->set_zone(zone_.previous_);
     }
 #ifdef DEBUG
     if (FLAG_trace_zones) {
@@ -101,18 +101,18 @@
 
   Zone* GetZone() { return &zone_; }
 
-  void Reinit(Isolate* isolate) {
-    if (isolate == NULL) {
+  void Reinit(Thread* thread) {
+    if (thread == NULL) {
       zone_.Link(NULL);
     } else {
-      zone_.Link(isolate->current_zone());
-      isolate->set_current_zone(&zone_);
+      zone_.Link(thread->zone());
+      thread->set_zone(&zone_);
     }
   }
 
-  void Reset(Isolate* isolate) {
-    if ((isolate != NULL) && (isolate->current_zone() == &zone_)) {
-      isolate->set_current_zone(zone_.previous_);
+  void Reset(Thread* thread) {
+    if ((thread != NULL) && (thread->zone() == &zone_)) {
+      thread->set_zone(zone_.previous_);
     }
     zone_.DeleteAll();
   }
@@ -592,16 +592,16 @@
   }
 
   // Reinit the ApiLocalScope to new values.
-  void Reinit(Isolate* isolate, ApiLocalScope* previous, uword stack_marker) {
+  void Reinit(Thread* thread, ApiLocalScope* previous, uword stack_marker) {
     previous_ = previous;
     stack_marker_ = stack_marker;
-    zone_.Reinit(isolate);
+    zone_.Reinit(thread);
   }
 
   // Reset the ApiLocalScope so that it can be reused again.
-  void Reset(Isolate* isolate) {
+  void Reset(Thread* thread) {
     local_handles_.Reset();
-    zone_.Reset(isolate);
+    zone_.Reset(thread);
     previous_ = NULL;
     stack_marker_ = 0;
   }
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 817b7e9..211ce7f 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -93,7 +93,7 @@
   }
   // Now Call the invoke stub which will invoke the dart function.
   invokestub entrypoint = reinterpret_cast<invokestub>(
-      isolate->stub_code()->InvokeDartCodeEntryPoint());
+      StubCode::InvokeDartCode_entry()->EntryPoint());
   const Code& code = Code::Handle(zone, function.CurrentCode());
   ASSERT(!code.IsNull());
   ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
diff --git a/runtime/vm/debugger_arm.cc b/runtime/vm/debugger_arm.cc
index e84ffa9..e0a366d 100644
--- a/runtime/vm/debugger_arm.cc
+++ b/runtime/vm/debugger_arm.cc
@@ -20,15 +20,14 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   uword stub_target = 0;
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = stub_code->ICCallBreakpointEntryPoint();
+      stub_target = StubCode::ICCallBreakpoint_entry()->EntryPoint();
       break;
     case RawPcDescriptors::kRuntimeCall:
-      stub_target = stub_code->RuntimeCallBreakpointEntryPoint();
+      stub_target = StubCode::RuntimeCallBreakpoint_entry()->EntryPoint();
       break;
     default:
       UNREACHABLE();
diff --git a/runtime/vm/debugger_arm64.cc b/runtime/vm/debugger_arm64.cc
index 0674495..8c59d24 100644
--- a/runtime/vm/debugger_arm64.cc
+++ b/runtime/vm/debugger_arm64.cc
@@ -20,15 +20,14 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   uword stub_target = 0;
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = stub_code->ICCallBreakpointEntryPoint();
+      stub_target = StubCode::ICCallBreakpoint_entry()->EntryPoint();
       break;
     case RawPcDescriptors::kRuntimeCall: {
-      stub_target = stub_code->RuntimeCallBreakpointEntryPoint();
+      stub_target = StubCode::RuntimeCallBreakpoint_entry()->EntryPoint();
       break;
     }
     default:
diff --git a/runtime/vm/debugger_ia32.cc b/runtime/vm/debugger_ia32.cc
index 6b9ae72..408c838 100644
--- a/runtime/vm/debugger_ia32.cc
+++ b/runtime/vm/debugger_ia32.cc
@@ -26,7 +26,6 @@
   ASSERT(!is_enabled_);
   const Code& code = Code::Handle(code_);
   const Instructions& instrs = Instructions::Handle(code.instructions());
-  Isolate* isolate = Isolate::Current();
   {
     WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
     switch (breakpoint_kind_) {
@@ -34,13 +33,13 @@
       case RawPcDescriptors::kUnoptStaticCall: {
         saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
         CodePatcher::PatchStaticCallAt(
-            pc_, code, isolate->stub_code()->ICCallBreakpointEntryPoint());
+            pc_, code, StubCode::ICCallBreakpoint_entry()->EntryPoint());
         break;
       }
       case RawPcDescriptors::kRuntimeCall: {
         saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
         CodePatcher::PatchStaticCallAt(
-            pc_, code, isolate->stub_code()->RuntimeCallBreakpointEntryPoint());
+            pc_, code, StubCode::RuntimeCallBreakpoint_entry()->EntryPoint());
         break;
       }
       default:
diff --git a/runtime/vm/debugger_mips.cc b/runtime/vm/debugger_mips.cc
index cd661db..651714b 100644
--- a/runtime/vm/debugger_mips.cc
+++ b/runtime/vm/debugger_mips.cc
@@ -20,15 +20,14 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   uword stub_target = 0;
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = stub_code->ICCallBreakpointEntryPoint();
+      stub_target = StubCode::ICCallBreakpoint_entry()->EntryPoint();
       break;
     case RawPcDescriptors::kRuntimeCall:
-      stub_target = stub_code->RuntimeCallBreakpointEntryPoint();
+      stub_target = StubCode::RuntimeCallBreakpoint_entry()->EntryPoint();
       break;
     default:
       UNREACHABLE();
diff --git a/runtime/vm/debugger_x64.cc b/runtime/vm/debugger_x64.cc
index 39b1ac1..531876d 100644
--- a/runtime/vm/debugger_x64.cc
+++ b/runtime/vm/debugger_x64.cc
@@ -22,15 +22,14 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   uword stub_target = 0;
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = stub_code->ICCallBreakpointEntryPoint();
+      stub_target = StubCode::ICCallBreakpoint_entry()->EntryPoint();
       break;
     case RawPcDescriptors::kRuntimeCall:
-      stub_target = stub_code->RuntimeCallBreakpointEntryPoint();
+      stub_target = StubCode::RuntimeCallBreakpoint_entry()->EntryPoint();
       break;
     default:
       UNREACHABLE();
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index fa2e441..9f79640 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -220,7 +220,7 @@
 #else
   // Prepare for unwinding frames by destroying all the stack resources
   // in the previous frames.
-  StackResource::Unwind(thread->isolate());
+  StackResource::Unwind(thread);
 
   // Call a stub to set up the exception object in kExceptionObjectReg,
   // to set up the stacktrace object in kStackTraceObjectReg, and to
@@ -228,7 +228,7 @@
   typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*,
                               Thread*);
   ExcpHandler func = reinterpret_cast<ExcpHandler>(
-      StubCode::JumpToExceptionHandlerEntryPoint());
+      StubCode::JumpToExceptionHandler_entry()->EntryPoint());
 
   // Unpoison the stack before we tear it down in the generated stub code.
   uword current_sp = Isolate::GetCurrentStackPointer() - 1024;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 9457956..ce0fb5a 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -38,8 +38,11 @@
 DEFINE_FLAG(bool, support_debugger, true, "Emit code needed for debugging");
 DEFINE_FLAG(bool, trace_type_check_elimination, false,
             "Trace type check elimination at compile time.");
+DEFINE_FLAG(bool, precompile_collect_closures, false,
+            "Collect all closure functions referenced from compiled code.");
 
 DECLARE_FLAG(int, optimization_counter_threshold);
+DECLARE_FLAG(bool, profile_vm);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 DECLARE_FLAG(bool, use_field_guards);
 
@@ -2664,8 +2667,27 @@
 }
 
 
+// TODO(rmacnak): De-dup closures in inlined-finally and track down other
+// stragglers to use Class::closures instead.
+static void CollectClosureFunction(const Function& function) {
+  if (function.HasCode()) return;
+
+  Isolate* isolate = Isolate::Current();
+  if (isolate->collected_closures() == GrowableObjectArray::null()) {
+    isolate->set_collected_closures(
+        GrowableObjectArray::Handle(GrowableObjectArray::New()));
+  }
+  const GrowableObjectArray& functions =
+      GrowableObjectArray::Handle(isolate, isolate->collected_closures());
+  functions.Add(function);
+}
+
+
 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
   const Function& function = node->function();
+  if (FLAG_precompile_collect_closures) {
+    CollectClosureFunction(function);
+  }
 
   if (function.IsImplicitStaticClosureFunction()) {
     const Instance& closure =
@@ -4762,6 +4784,9 @@
 
 
 FlowGraph* FlowGraphBuilder::BuildGraph() {
+  VMTagScope tagScope(Thread::Current()->isolate(),
+                      VMTag::kCompileFlowGraphBuilderTagId,
+                      FLAG_profile_vm);
   if (FLAG_print_ast) {
     // Print the function ast before IL generation.
     AstPrinter::PrintFunctionNodes(parsed_function());
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 1efd006..c7d3215 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -66,6 +66,7 @@
 DECLARE_FLAG(bool, use_cha_deopt);
 DECLARE_FLAG(bool, use_osr);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
+DECLARE_FLAG(bool, precompile_collect_closures);
 
 
 static void NooptModeHandler(bool value) {
@@ -103,6 +104,27 @@
                     "Run fast unoptimized code only.");
 
 
+DECLARE_FLAG(bool, lazy_dispatchers);
+DECLARE_FLAG(bool, interpret_irregexp);
+DECLARE_FLAG(bool, enable_mirrors);
+
+
+static void PrecompileModeHandler(bool value) {
+  if (value) {
+    NooptModeHandler(true);
+    FLAG_lazy_dispatchers = false;
+    FLAG_interpret_irregexp = true;
+    FLAG_enable_mirrors = false;
+    FLAG_precompile_collect_closures = true;
+  }
+}
+
+
+DEFINE_FLAG_HANDLER(PrecompileModeHandler,
+                    precompile,
+                    "Precompilation mode");
+
+
 // Assign locations to incoming arguments, i.e., values pushed above spill slots
 // with PushArgument.  Recursively allocates from outermost to innermost
 // environment.
@@ -405,7 +427,7 @@
   intptr_t inlining_id;
   IntervalStruct(intptr_t s, intptr_t id) : start(s), inlining_id(id) {}
   void Dump() {
-    OS::Print("start: %" Px " id: %" Pd "",  start, inlining_id);
+    ISL_Print("start: 0x%" Px " iid: %" Pd " ",  start, inlining_id);
   }
 };
 
@@ -450,8 +472,7 @@
       // Compose intervals.
       if (instr->has_inlining_id() && is_optimizing()) {
         if (prev_inlining_id != instr->inlining_id()) {
-          intervals.Add(IntervalStruct(prev_offset,
-                                       prev_inlining_id));
+          intervals.Add(IntervalStruct(prev_offset, prev_inlining_id));
           prev_offset = assembler()->CodeSize();
           prev_inlining_id = instr->inlining_id();
           if (prev_inlining_id > max_inlining_id) {
@@ -460,8 +481,7 @@
         }
       }
       if (FLAG_code_comments ||
-          FLAG_disassemble ||
-          FLAG_disassemble_optimized) {
+          FLAG_disassemble || FLAG_disassemble_optimized) {
         if (FLAG_source_lines) {
           EmitSourceLine(instr);
         }
@@ -496,6 +516,7 @@
   }
 
   if (is_optimizing()) {
+    LogBlock lb(Isolate::Current());
     intervals.Add(IntervalStruct(prev_offset, prev_inlining_id));
     inlined_code_intervals_ =
         Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld);
@@ -504,13 +525,14 @@
     Smi& inline_id = Smi::Handle();
     for (intptr_t i = 0; i < intervals.length(); i++) {
       if (FLAG_trace_inlining_intervals && is_optimizing()) {
-        const Function* function =
-            inline_id_to_function_.At(intervals[i].inlining_id);
+        const Function& function =
+            *inline_id_to_function_.At(intervals[i].inlining_id);
         intervals[i].Dump();
-        OS::Print(" %s parent %" Pd "\n",
-            function->ToQualifiedCString(),
-            caller_inline_id_[intervals[i].inlining_id]);
+        ISL_Print(" parent iid %" Pd " %s\n",
+            caller_inline_id_[intervals[i].inlining_id],
+            function.ToQualifiedCString());
       }
+
       const intptr_t id = intervals[i].inlining_id;
       start_h = Smi::New(intervals[i].start);
       inline_id = Smi::New(id);
@@ -519,23 +541,24 @@
       const intptr_t p = i * Code::kInlIntNumEntries;
       inlined_code_intervals_.SetAt(p + Code::kInlIntStart, start_h);
       inlined_code_intervals_.SetAt(p + Code::kInlIntInliningId, inline_id);
-      inlined_code_intervals_.SetAt(
-          p + Code::kInlIntCallerId, caller_inline_id);
     }
   }
   set_current_block(NULL);
   if (FLAG_trace_inlining_intervals && is_optimizing()) {
-    OS::Print("Intervals:\n");
+    LogBlock lb(Isolate::Current());
+    ISL_Print("Intervals:\n");
+    for (intptr_t cc = 0; cc < caller_inline_id_.length(); cc++) {
+      ISL_Print("  iid: %" Pd " caller iid: %" Pd "\n",
+          cc, caller_inline_id_[cc]);
+    }
     Smi& temp = Smi::Handle();
     for (intptr_t i = 0; i < inlined_code_intervals_.Length();
          i += Code::kInlIntNumEntries) {
       temp ^= inlined_code_intervals_.At(i + Code::kInlIntStart);
       ASSERT(!temp.IsNull());
-      OS::Print("% " Pd " start: %" Px " ", i, temp.Value());
+      ISL_Print("% " Pd " start: 0x%" Px " ", i, temp.Value());
       temp ^= inlined_code_intervals_.At(i + Code::kInlIntInliningId);
-      OS::Print("inl-id: %" Pd " ", temp.Value());
-      temp ^= inlined_code_intervals_.At(i + Code::kInlIntCallerId);
-      OS::Print("caller-id: %" Pd " \n", temp.Value());
+      ISL_Print("iid: %" Pd " ", temp.Value());
     }
   }
 }
@@ -1049,8 +1072,6 @@
     return;
   }
   ASSERT(!ic_data.IsNull());
-  uword label_address = 0;
-  StubCode* stub_code = isolate()->stub_code();
   if (is_optimizing() && (ic_data.NumberOfUsedChecks() == 0)) {
     // Emit IC call that will count and thus may need reoptimization at
     // function entry.
@@ -1059,17 +1080,18 @@
            || flow_graph().IsCompiledForOsr());
     switch (ic_data.NumArgsTested()) {
       case 1:
-        label_address = stub_code->OneArgOptimizedCheckInlineCacheEntryPoint();
-        break;
+        EmitOptimizedInstanceCall(
+            *StubCode::OneArgOptimizedCheckInlineCache_entry(), ic_data,
+            argument_count, deopt_id, token_pos, locs);
+        return;
       case 2:
-        label_address = stub_code->TwoArgsOptimizedCheckInlineCacheEntryPoint();
-        break;
+        EmitOptimizedInstanceCall(
+            *StubCode::TwoArgsOptimizedCheckInlineCache_entry(), ic_data,
+            argument_count, deopt_id, token_pos, locs);
+        return;
       default:
         UNIMPLEMENTED();
     }
-    ExternalLabel target_label(label_address);
-    EmitOptimizedInstanceCall(&target_label, ic_data,
-                              argument_count, deopt_id, token_pos, locs);
     return;
   }
 
@@ -1086,17 +1108,18 @@
 
   switch (ic_data.NumArgsTested()) {
     case 1:
-      label_address = stub_code->OneArgCheckInlineCacheEntryPoint();
+      EmitInstanceCall(
+          *StubCode::OneArgCheckInlineCache_entry(), ic_data, argument_count,
+          deopt_id, token_pos, locs);
       break;
     case 2:
-      label_address = stub_code->TwoArgsCheckInlineCacheEntryPoint();
+      EmitInstanceCall(
+          *StubCode::TwoArgsCheckInlineCache_entry(), ic_data, argument_count,
+          deopt_id, token_pos, locs);
       break;
     default:
       UNIMPLEMENTED();
   }
-  ExternalLabel target_label(label_address);
-  EmitInstanceCall(&target_label, ic_data, argument_count,
-                   deopt_id, token_pos, locs);
 }
 
 
@@ -1678,6 +1701,21 @@
 }
 
 
+RawArray* FlowGraphCompiler::CallerInliningIdMap() const {
+  if (caller_inline_id_.length() == 0) {
+    return Object::empty_array().raw();
+  }
+  const Array& res = Array::Handle(
+      Array::New(caller_inline_id_.length(), Heap::kOld));
+  Smi& smi = Smi::Handle();
+  for (intptr_t i = 0; i < caller_inline_id_.length(); i++) {
+    smi = Smi::New(caller_inline_id_[i]);
+    res.SetAt(i, smi);
+  }
+  return res.raw();
+}
+
+
 void FlowGraphCompiler::EmitPolymorphicInstanceCall(
     const ICData& ic_data,
     intptr_t argument_count,
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 2ea19ee..536720e 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -337,13 +337,13 @@
                            LocationSummary* locs);
 
   void GenerateCall(intptr_t token_pos,
-                    const ExternalLabel* label,
+                    const StubEntry& stub_entry,
                     RawPcDescriptors::Kind kind,
                     LocationSummary* locs);
 
   void GenerateDartCall(intptr_t deopt_id,
                         intptr_t token_pos,
-                        const ExternalLabel* label,
+                        const StubEntry& stub_entry,
                         RawPcDescriptors::Kind kind,
                         LocationSummary* locs);
 
@@ -393,14 +393,14 @@
   static int32_t EdgeCounterIncrementSizeInBytes();
 #endif  // !TARGET_ARCH_ARM64 && !TARGET_ARCH_MIPS
 
-  void EmitOptimizedInstanceCall(ExternalLabel* target_label,
+  void EmitOptimizedInstanceCall(const StubEntry& stub_entry,
                                  const ICData& ic_data,
                                  intptr_t argument_count,
                                  intptr_t deopt_id,
                                  intptr_t token_pos,
                                  LocationSummary* locs);
 
-  void EmitInstanceCall(ExternalLabel* target_label,
+  void EmitInstanceCall(const StubEntry& stub_entry,
                         const ICData& ic_data,
                         intptr_t argument_count,
                         intptr_t deopt_id,
@@ -539,6 +539,8 @@
 
   RawArray* InliningIdToFunction() const;
 
+  RawArray* CallerInliningIdMap() const;
+
  private:
   friend class CheckStackOverflowSlowPath;  // For pending_deoptimization_env_.
 
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index d169b8d..f7b1fb4 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -67,14 +67,13 @@
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
-  assembler()->set_allow_constant_pool(false);
+  ASSERT(!assembler()->constant_pool_allowed());
 }
 
 
 void FlowGraphCompiler::ExitIntrinsicMode() {
   ASSERT(intrinsic_mode());
   intrinsic_mode_ = false;
-  assembler()->set_allow_constant_pool(true);
 }
 
 
@@ -99,15 +98,17 @@
   // The real frame starts here.
   builder->MarkFrameStart();
 
+  Zone* zone = compiler->zone();
+
   // Current PP, FP, and PC.
-  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+  builder->AddPp(Function::Handle(zone, current->code().function()), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(Function::Handle(current->code().function()),
+  builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
                             deopt_id(),
                             slot_ix++);
 
   // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
-  builder->AddPcMarker(Function::Handle(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(zone), slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -125,17 +126,19 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+    builder->AddPp(
+        Function::Handle(zone, current->code().function()), slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(Function::Handle(current->code().function()),
-                              Isolate::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
+    builder->AddReturnAddress(
+        Function::Handle(zone, current->code().function()),
+        Isolate::ToDeoptAfter(current->deopt_id()),
+        slot_ix++);
 
     // PC marker.
-    builder->AddPcMarker(Function::Handle(previous->code().function()),
+    builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                          slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
@@ -168,7 +171,7 @@
   builder->AddCallerPc(slot_ix++);
 
   // PC marker.
-  builder->AddPcMarker(Function::Handle(previous->code().function()),
+  builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                        slot_ix++);
 
   // For the outermost environment, set the incoming arguments.
@@ -194,12 +197,11 @@
 
   ASSERT(deopt_env() != NULL);
 
-  StubCode* stub_code = compiler->isolate()->stub_code();
   // LR may be live. It will be clobbered by BranchLink, so cache it in IP.
   // It will be restored at the top of the deoptimization stub, specifically in
   // GenerateDeoptimizationSequence in stub_code_arm.cc.
   __ mov(IP, Operand(LR));
-  __ BranchLink(&stub_code->DeoptimizeLabel());
+  __ BranchLink(*StubCode::Deoptimize_entry());
   set_pc_offset(assem->CodeSize());
 #undef __
 }
@@ -235,20 +237,19 @@
   ASSERT(instance_reg == R0);
   ASSERT(temp_reg == kNoRegister);  // Unused on ARM.
   const SubtypeTestCache& type_test_cache =
-      SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
-  StubCode* stub_code = isolate()->stub_code();
+      SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
   __ LoadUniqueObject(R2, type_test_cache);
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
     __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
-    __ BranchLink(&stub_code->Subtype1TestCacheLabel());
+    __ BranchLink(*StubCode::Subtype1TestCache_entry());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
     __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
-    __ BranchLink(&stub_code->Subtype2TestCacheLabel());
+    __ BranchLink(*StubCode::Subtype2TestCache_entry());
   } else if (test_kind == kTestTypeThreeArgs) {
     ASSERT(type_arguments_reg == R1);
-    __ BranchLink(&stub_code->Subtype3TestCacheLabel());
+    __ BranchLink(*StubCode::Subtype3TestCache_entry());
   } else {
     UNREACHABLE();
   }
@@ -271,11 +272,11 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::ZoneHandle(type.type_class());
+  const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
   const Register kInstanceReg = R0;
-  Error& malformed_error = Error::Handle();
-  const Type& int_type = Type::Handle(Type::IntType());
+  Error& malformed_error = Error::Handle(zone());
+  const Type& int_type = Type::Handle(zone(), Type::IntType());
   const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
   // Malformed type should have been handled at graph construction time.
   ASSERT(smi_is_ok || malformed_error.IsNull());
@@ -289,7 +290,7 @@
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
   const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(type.arguments());
+      TypeArguments::ZoneHandle(zone(), type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -310,12 +311,12 @@
     // If one type argument only, check if type argument is Object or dynamic.
     if (type_arguments.Length() == 1) {
       const AbstractType& tp_argument = AbstractType::ZoneHandle(
-          type_arguments.TypeAt(0));
+          zone(), type_arguments.TypeAt(0));
       ASSERT(!tp_argument.IsMalformed());
       if (tp_argument.IsType()) {
         ASSERT(tp_argument.HasResolvedTypeClass());
         // Check if type argument is dynamic or Object.
-        const Type& object_type = Type::Handle(Type::ObjectType());
+        const Type& object_type = Type::Handle(zone(), Type::ObjectType());
         if (object_type.IsSubtypeOf(tp_argument, NULL)) {
           // Instance class test only necessary.
           return GenerateSubtype1TestCacheLookup(
@@ -361,16 +362,16 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::Handle(type.type_class());
+  const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
   const Register kInstanceReg = R0;
   __ tst(kInstanceReg, Operand(kSmiTagMask));
   // If instance is Smi, check directly.
-  const Class& smi_class = Class::Handle(Smi::Class());
-  if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
+  const Class& smi_class = Class::Handle(zone(), Smi::Class());
+  if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
                             type_class,
-                            TypeArguments::Handle(),
+                            TypeArguments::Handle(zone()),
                             NULL)) {
     __ b(is_instance_lbl, EQ);
   } else {
@@ -399,7 +400,7 @@
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
-  if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
+  if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
     GenerateNumberTypeCheck(
         kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
     return false;
@@ -468,18 +469,18 @@
         FieldAddress(R1, TypeArguments::type_at_offset(type_param.index())));
     // R2: concrete type of type.
     // Check if type argument is dynamic.
-    __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType()));
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::DynamicType()));
     __ b(is_instance_lbl, EQ);
-    __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType()));
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::ObjectType()));
     __ b(is_instance_lbl, EQ);
 
     // For Smi check quickly against int and num interfaces.
     Label not_smi;
     __ tst(R0, Operand(kSmiTagMask));  // Value is Smi?
     __ b(&not_smi, NE);
-    __ CompareObject(R2, Type::ZoneHandle(Type::IntType()));
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::IntType()));
     __ b(is_instance_lbl, EQ);
-    __ CompareObject(R2, Type::ZoneHandle(Type::Number()));
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::Number()));
     __ b(is_instance_lbl, EQ);
     // Smi must be handled in runtime.
     Label fall_through;
@@ -492,7 +493,7 @@
     const Register kTypeArgumentsReg = R1;
     const Register kTempReg = kNoRegister;
     const SubtypeTestCache& type_test_cache =
-        SubtypeTestCache::ZoneHandle(
+        SubtypeTestCache::ZoneHandle(zone(),
             GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
                                         kInstanceReg,
                                         kTypeArgumentsReg,
@@ -543,7 +544,7 @@
     return SubtypeTestCache::null();
   }
   if (type.IsInstantiated()) {
-    const Class& type_class = Class::ZoneHandle(type.type_class());
+    const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
     // A class equality check is only applicable with a dst type of a
     // non-parameterized class, non-signature class, or with a raw dst type of
     // a parameterized class.
@@ -612,7 +613,7 @@
   }
 
   // Generate inline instanceof test.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, type,
                                         &is_instance, &is_not_instance);
 
@@ -707,7 +708,7 @@
   }
 
   // Generate inline type check, linking to runtime call if not assignable.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, dst_type,
                                         &is_assignable, &runtime_call);
 
@@ -864,7 +865,7 @@
       __ Bind(&load_default_value);
       // Load R5 with default argument.
       const Object& value = Object::ZoneHandle(
-          parsed_function().default_parameter_values().At(
+          zone(), parsed_function().default_parameter_values().At(
               param_pos - num_fixed_params));
       __ LoadObject(R5, value);
       __ Bind(&assign_optional_parameter);
@@ -900,7 +901,7 @@
       __ b(&next_parameter, GT);
       // Load R5 with default argument.
       const Object& value = Object::ZoneHandle(
-          parsed_function().default_parameter_values().At(i));
+          zone(), parsed_function().default_parameter_values().At(i));
       __ LoadObject(R5, value);
       // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
       // We do not use the final allocation index of the variable here, i.e.
@@ -922,8 +923,12 @@
 
   __ Bind(&wrong_num_arguments);
   if (function.IsClosureFunction()) {
+    ASSERT(assembler()->constant_pool_allowed());
     __ LeaveDartFrame();  // The arguments are still on the stack.
-    __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+    // Do not use caller's pool ptr in branch.
+    ASSERT(!assembler()->constant_pool_allowed());
+    __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
+    __ set_constant_pool_allowed(true);
     // The noSuchMethod call may return to the caller, but not here.
   } else if (check_correct_named_args) {
     __ Stop("Wrong arguments");
@@ -983,7 +988,6 @@
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = R6;
-    StubCode* stub_code = isolate()->stub_code();
 
     // The pool pointer is not setup before entering the Dart frame.
     // Preserve PP of caller.
@@ -994,6 +998,7 @@
     __ LoadObject(function_reg, function);  // Uses PP.
     // Restore PP of caller.
     __ mov(PP, Operand(R7));
+    __ set_constant_pool_allowed(false);
 
     // Patch point is after the eventually inlined function object.
     entry_patch_pc_offset_ = assembler()->CodeSize();
@@ -1009,7 +1014,7 @@
     }
     __ CompareImmediate(R7, GetOptimizationThreshold());
     ASSERT(function_reg == R6);
-    __ Branch(&stub_code->OptimizeFunctionLabel(), GE);
+    __ Branch(*StubCode::OptimizeFunction_entry(), GE);
   } else if (!flow_graph().IsCompiledForOsr()) {
     entry_patch_pc_offset_ = assembler()->CodeSize();
   }
@@ -1040,13 +1045,13 @@
   TryIntrinsify();
 
   EmitFrameEntry();
+  ASSERT(assembler()->constant_pool_allowed());
 
   const Function& function = parsed_function().function();
 
   const int num_fixed_params = function.num_fixed_parameters();
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
-  StubCode* stub_code = isolate()->stub_code();
 
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
@@ -1073,8 +1078,12 @@
       __ b(&correct_num_arguments, EQ);
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction()) {
+        ASSERT(assembler()->constant_pool_allowed());
         __ LeaveDartFrame();  // The arguments are still on the stack.
-        __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+        // Do not use caller's pool ptr in branch.
+        ASSERT(!assembler()->constant_pool_allowed());
+        __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
+        __ set_constant_pool_allowed(true);
         // The noSuchMethod call may return to the caller, but not here.
       } else {
         __ Stop("Wrong number of arguments");
@@ -1125,24 +1134,25 @@
   VisitBlocks();
 
   __ bkpt(0);
+  ASSERT(assembler()->constant_pool_allowed());
   GenerateDeferredCode();
   // Emit function patching code. This will be swapped with the first 3
   // instructions at entry point.
   patch_code_pc_offset_ = assembler()->CodeSize();
-  __ BranchPatchable(&stub_code->FixCallersTargetLabel());
+  __ BranchPatchable(*StubCode::FixCallersTarget_entry());
 
   if (is_optimizing()) {
     lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Branch(&stub_code->DeoptimizeLazyLabel());
+    __ Branch(*StubCode::DeoptimizeLazy_entry());
   }
 }
 
 
 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
-                                     const ExternalLabel* label,
+                                     const StubEntry& stub_entry,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ BranchLinkPatchable(label);
+  __ BranchLinkPatchable(stub_entry);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
 }
@@ -1150,10 +1160,10 @@
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          intptr_t token_pos,
-                                         const ExternalLabel* label,
+                                         const StubEntry& stub_entry,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  __ BranchLinkPatchable(label);
+  __ BranchLinkPatchable(stub_entry);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
   // Marks either the continuation point in unoptimized code or the
@@ -1201,8 +1211,9 @@
   // overflow; and though we do not reset the counters when we optimize or
   // deoptimize, there is a bound on the number of
   // optimization/deoptimization cycles we will attempt.
-  const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
-  counter.SetAt(0, Smi::Handle(Smi::New(0)));
+  ASSERT(assembler_->constant_pool_allowed());
+  const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
+  counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
   __ Comment("Edge counter");
   __ LoadUniqueObject(R0, counter);
   intptr_t increment_start = assembler_->CodeSize();
@@ -1233,13 +1244,13 @@
 
 
 void FlowGraphCompiler::EmitOptimizedInstanceCall(
-    ExternalLabel* target_label,
+    const StubEntry& stub_entry,
     const ICData& ic_data,
     intptr_t argument_count,
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
   // to inlining in optimized code, that function may not correspond to the
@@ -1251,24 +1262,24 @@
   __ LoadUniqueObject(R5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
 }
 
 
-void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
+void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
                                          const ICData& ic_data,
                                          intptr_t argument_count,
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   __ LoadUniqueObject(R5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
@@ -1282,12 +1293,12 @@
     intptr_t token_pos,
     LocationSummary* locs) {
   MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
-  const String& name = String::Handle(ic_data.target_name());
+  const String& name = String::Handle(zone(), ic_data.target_name());
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ic_data.arguments_descriptor());
+      Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
-  const MegamorphicCache& cache =
-      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
+      zone(), table->Lookup(name, arguments_descriptor));
   const Register receiverR = R0;
   const Register cacheR = R1;
   const Register targetR = R1;
@@ -1295,8 +1306,7 @@
   __ LoadObject(cacheR, cache);
 
   if (FLAG_use_megamorphic_stub) {
-    StubCode* stub_code = isolate()->stub_code();
-    __ BranchLink(&stub_code->MegamorphicLookupLabel());
+    __ BranchLink(*StubCode::MegamorphicLookup_entry());
   } else  {
     StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
   }
@@ -1325,14 +1335,12 @@
     intptr_t token_pos,
     LocationSummary* locs,
     const ICData& ic_data) {
-  StubCode* stub_code = isolate()->stub_code();
-  const uword label_address =
-      stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
-  ExternalLabel target_label(label_address);
+  const StubEntry* stub_entry =
+      StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &target_label,
+                   *stub_entry,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count);
@@ -1346,13 +1354,12 @@
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  StubCode* stub_code = isolate()->stub_code();
   __ LoadObject(R4, arguments_descriptor);
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &stub_code->CallStaticFunctionLabel(),
+                   *StubCode::CallStaticFunction_entry(),
                    RawPcDescriptors::kOther,
                    locs);
   AddStaticCallTarget(function);
@@ -1366,16 +1373,15 @@
     bool needs_number_check,
     intptr_t token_pos) {
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
     __ Push(reg);
     __ PushObject(obj);
     if (is_optimizing()) {
       __ BranchLinkPatchable(
-          &stub_code->OptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
       __ BranchLinkPatchable(
-          &stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1397,15 +1403,14 @@
                                                        bool needs_number_check,
                                                        intptr_t token_pos) {
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ Push(left);
     __ Push(right);
     if (is_optimizing()) {
       __ BranchLinkPatchable(
-          &stub_code->OptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
       __ BranchLinkPatchable(
-          &stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1522,9 +1527,8 @@
   ASSERT(is_optimizing());
   __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
-                                                 argument_names));
-  StubCode* stub_code = isolate()->stub_code();
+      Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
+                                                         argument_names));
 
   // Load receiver into R0.
   __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
@@ -1548,10 +1552,10 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
-    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
     AddStaticCallTarget(function);
     __ Drop(argument_count);
     if (kNumChecks > 1) {
@@ -1589,7 +1593,7 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
     const Function& function = *sorted[i].target;
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index f951807..a473953 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -64,14 +64,13 @@
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
-  assembler()->set_allow_constant_pool(false);
+  ASSERT(!assembler()->constant_pool_allowed());
 }
 
 
 void FlowGraphCompiler::ExitIntrinsicMode() {
   ASSERT(intrinsic_mode());
   intrinsic_mode_ = false;
-  assembler()->set_allow_constant_pool(true);
 }
 
 
@@ -96,11 +95,13 @@
   // The real frame starts here.
   builder->MarkFrameStart();
 
+  Zone* zone = compiler->zone();
+
   // Current PP, FP, and PC.
-  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
-  builder->AddPcMarker(Function::Handle(), slot_ix++);
+  builder->AddPp(Function::Handle(zone, current->code().function()), slot_ix++);
+  builder->AddPcMarker(Function::Handle(zone), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(Function::Handle(current->code().function()),
+  builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
                             deopt_id(),
                             slot_ix++);
 
@@ -120,16 +121,18 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
-    builder->AddPcMarker(Function::Handle(previous->code().function()),
+    builder->AddPp(Function::Handle(
+        zone, current->code().function()), slot_ix++);
+    builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                          slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(Function::Handle(current->code().function()),
-                              Isolate::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
+    builder->AddReturnAddress(
+        Function::Handle(zone, current->code().function()),
+        Isolate::ToDeoptAfter(current->deopt_id()),
+        slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
     // we must read them from the previous environment.
@@ -158,7 +161,7 @@
   // For the outermost environment, set caller PC, caller PP, and caller FP.
   builder->AddCallerPp(slot_ix++);
   // PC marker.
-  builder->AddPcMarker(Function::Handle(previous->code().function()),
+  builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                        slot_ix++);
   builder->AddCallerFp(slot_ix++);
   builder->AddCallerPc(slot_ix++);
@@ -186,8 +189,7 @@
 
   ASSERT(deopt_env() != NULL);
 
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  __ BranchLink(&stub_code->DeoptimizeLabel(), PP);
+  __ BranchLink(*StubCode::Deoptimize_entry());
   set_pc_offset(assem->CodeSize());
 #undef __
 }
@@ -201,9 +203,9 @@
                                            Label* is_true,
                                            Label* is_false) {
   Label fall_through;
-  __ CompareObject(bool_register, Object::null_object(), PP);
+  __ CompareObject(bool_register, Object::null_object());
   __ b(&fall_through, EQ);
-  __ CompareObject(bool_register, Bool::True(), PP);
+  __ CompareObject(bool_register, Bool::True());
   __ b(is_true, EQ);
   __ b(is_false);
   __ Bind(&fall_through);
@@ -222,20 +224,19 @@
   ASSERT(instance_reg == R0);
   ASSERT(temp_reg == kNoRegister);  // Unused on ARM.
   const SubtypeTestCache& type_test_cache =
-      SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
-  StubCode* stub_code = isolate()->stub_code();
-  __ LoadUniqueObject(R2, type_test_cache, PP);
+      SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
+  __ LoadUniqueObject(R2, type_test_cache);
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
-    __ LoadObject(R1, Object::null_object(), PP);
-    __ BranchLink(&stub_code->Subtype1TestCacheLabel(), PP);
+    __ LoadObject(R1, Object::null_object());
+    __ BranchLink(*StubCode::Subtype1TestCache_entry());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
-    __ LoadObject(R1, Object::null_object(), PP);
-    __ BranchLink(&stub_code->Subtype2TestCacheLabel(), PP);
+    __ LoadObject(R1, Object::null_object());
+    __ BranchLink(*StubCode::Subtype2TestCache_entry());
   } else if (test_kind == kTestTypeThreeArgs) {
     ASSERT(type_arguments_reg == R1);
-    __ BranchLink(&stub_code->Subtype3TestCacheLabel(), PP);
+    __ BranchLink(*StubCode::Subtype3TestCache_entry());
   } else {
     UNREACHABLE();
   }
@@ -258,11 +259,11 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::ZoneHandle(type.type_class());
+  const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
   const Register kInstanceReg = R0;
-  Error& malformed_error = Error::Handle();
-  const Type& int_type = Type::Handle(Type::IntType());
+  Error& malformed_error = Error::Handle(zone());
+  const Type& int_type = Type::Handle(zone(), Type::IntType());
   const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
   // Malformed type should have been handled at graph construction time.
   ASSERT(smi_is_ok || malformed_error.IsNull());
@@ -276,7 +277,7 @@
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
   const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(type.arguments());
+      TypeArguments::ZoneHandle(zone(), type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -284,8 +285,8 @@
     if (is_raw_type) {
       const Register kClassIdReg = R2;
       // dynamic type argument, check only classes.
-      __ LoadClassId(kClassIdReg, kInstanceReg, PP);
-      __ CompareImmediate(kClassIdReg, type_class.id(), PP);
+      __ LoadClassId(kClassIdReg, kInstanceReg);
+      __ CompareImmediate(kClassIdReg, type_class.id());
       __ b(is_instance_lbl, EQ);
       // List is a very common case.
       if (IsListClass(type_class)) {
@@ -297,12 +298,12 @@
     // If one type argument only, check if type argument is Object or dynamic.
     if (type_arguments.Length() == 1) {
       const AbstractType& tp_argument = AbstractType::ZoneHandle(
-          type_arguments.TypeAt(0));
+          zone(), type_arguments.TypeAt(0));
       ASSERT(!tp_argument.IsMalformed());
       if (tp_argument.IsType()) {
         ASSERT(tp_argument.HasResolvedTypeClass());
         // Check if type argument is dynamic or Object.
-        const Type& object_type = Type::Handle(Type::ObjectType());
+        const Type& object_type = Type::Handle(zone(), Type::ObjectType());
         if (object_type.IsSubtypeOf(tp_argument, NULL)) {
           // Instance class test only necessary.
           return GenerateSubtype1TestCacheLookup(
@@ -329,7 +330,7 @@
                                       Label* is_equal_lbl,
                                       Label* is_not_equal_lbl) {
   for (intptr_t i = 0; i < class_ids.length(); i++) {
-    __ CompareImmediate(class_id_reg, class_ids[i], PP);
+    __ CompareImmediate(class_id_reg, class_ids[i]);
     __ b(is_equal_lbl, EQ);
   }
   __ b(is_not_equal_lbl);
@@ -348,16 +349,16 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::Handle(type.type_class());
+  const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
   const Register kInstanceReg = R0;
   __ tsti(kInstanceReg, Immediate(kSmiTagMask));
   // If instance is Smi, check directly.
-  const Class& smi_class = Class::Handle(Smi::Class());
-  if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
+  const Class& smi_class = Class::Handle(zone(), Smi::Class());
+  if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
                             type_class,
-                            TypeArguments::Handle(),
+                            TypeArguments::Handle(zone()),
                             NULL)) {
     __ b(is_instance_lbl, EQ);
   } else {
@@ -365,28 +366,28 @@
   }
   // Compare if the classes are equal.
   const Register kClassIdReg = R2;
-  __ LoadClassId(kClassIdReg, kInstanceReg, PP);
-  __ CompareImmediate(kClassIdReg, type_class.id(), PP);
+  __ LoadClassId(kClassIdReg, kInstanceReg);
+  __ CompareImmediate(kClassIdReg, type_class.id());
   __ b(is_instance_lbl, EQ);
   // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted
   // interfaces.
   // Bool interface can be implemented only by core class Bool.
   if (type.IsBoolType()) {
-    __ CompareImmediate(kClassIdReg, kBoolCid, PP);
+    __ CompareImmediate(kClassIdReg, kBoolCid);
     __ b(is_instance_lbl, EQ);
     __ b(is_not_instance_lbl);
     return false;
   }
   if (type.IsFunctionType()) {
     // Check if instance is a closure.
-    __ LoadClassById(R3, kClassIdReg, PP);
-    __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset(), PP);
-    __ CompareObject(R3, Object::null_object(), PP);
+    __ LoadClassById(R3, kClassIdReg);
+    __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset());
+    __ CompareObject(R3, Object::null_object());
     __ b(is_instance_lbl, NE);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
-  if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
+  if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
     GenerateNumberTypeCheck(
         kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
     return false;
@@ -414,12 +415,12 @@
     Label* is_not_instance_lbl) {
   __ Comment("Subtype1TestCacheLookup");
   const Register kInstanceReg = R0;
-  __ LoadClass(R1, kInstanceReg, PP);
+  __ LoadClass(R1, kInstanceReg);
   // R1: instance class.
   // Check immediate superclass equality.
-  __ LoadFieldFromOffset(R2, R1, Class::super_type_offset(), PP);
-  __ LoadFieldFromOffset(R2, R2, Type::type_class_offset(), PP);
-  __ CompareObject(R2, type_class, PP);
+  __ LoadFieldFromOffset(R2, R1, Class::super_type_offset());
+  __ LoadFieldFromOffset(R2, R2, Type::type_class_offset());
+  __ CompareObject(R2, type_class);
   __ b(is_instance_lbl, EQ);
 
   const Register kTypeArgumentsReg = kNoRegister;
@@ -449,24 +450,24 @@
     __ ldr(R1, Address(SP));  // Get instantiator type arguments.
     // R1: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
-    __ CompareObject(R1, Object::null_object(), PP);
+    __ CompareObject(R1, Object::null_object());
     __ b(is_instance_lbl, EQ);
     __ LoadFieldFromOffset(
-        R2, R1, TypeArguments::type_at_offset(type_param.index()), PP);
+        R2, R1, TypeArguments::type_at_offset(type_param.index()));
     // R2: concrete type of type.
     // Check if type argument is dynamic.
-    __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType()), PP);
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::DynamicType()));
     __ b(is_instance_lbl, EQ);
-    __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType()), PP);
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::ObjectType()));
     __ b(is_instance_lbl, EQ);
 
     // For Smi check quickly against int and num interfaces.
     Label not_smi;
     __ tsti(R0, Immediate(kSmiTagMask));  // Value is Smi?
     __ b(&not_smi, NE);
-    __ CompareObject(R2, Type::ZoneHandle(Type::IntType()), PP);
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::IntType()));
     __ b(is_instance_lbl, EQ);
-    __ CompareObject(R2, Type::ZoneHandle(Type::Number()), PP);
+    __ CompareObject(R2, Type::ZoneHandle(zone(), Type::Number()));
     __ b(is_instance_lbl, EQ);
     // Smi must be handled in runtime.
     Label fall_through;
@@ -479,7 +480,7 @@
     const Register kTypeArgumentsReg = R1;
     const Register kTempReg = kNoRegister;
     const SubtypeTestCache& type_test_cache =
-        SubtypeTestCache::ZoneHandle(
+        SubtypeTestCache::ZoneHandle(zone(),
             GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
                                         kInstanceReg,
                                         kTypeArgumentsReg,
@@ -530,7 +531,7 @@
     return SubtypeTestCache::null();
   }
   if (type.IsInstantiated()) {
-    const Class& type_class = Class::ZoneHandle(type.type_class());
+    const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
     // A class equality check is only applicable with a dst type of a
     // non-parameterized class, non-signature class, or with a raw dst type of
     // a parameterized class.
@@ -595,12 +596,12 @@
     // We can only inline this null check if the type is instantiated at compile
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
-    __ CompareObject(R0, Object::null_object(), PP);
+    __ CompareObject(R0, Object::null_object());
     __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ);
   }
 
   // Generate inline instanceof test.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, type,
                                         &is_instance, &is_not_instance);
 
@@ -611,13 +612,13 @@
     // Load instantiator (R2) and its type arguments (R1).
     __ ldr(R1, Address(SP, 0 * kWordSize));
     __ ldr(R2, Address(SP, 1 * kWordSize));
-    __ PushObject(Object::null_object(), PP);  // Make room for the result.
+    __ PushObject(Object::null_object());  // Make room for the result.
     __ Push(R0);  // Push the instance.
-    __ PushObject(type, PP);  // Push the type.
+    __ PushObject(type);  // Push the type.
     // Push instantiator (R2) and its type arguments (R1).
     __ Push(R2);
     __ Push(R1);
-    __ LoadUniqueObject(R0, test_cache, PP);
+    __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
     GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
@@ -625,21 +626,21 @@
     __ Drop(5);
     if (negate_result) {
       __ Pop(R1);
-      __ LoadObject(R0, Bool::True(), PP);
+      __ LoadObject(R0, Bool::True());
       __ CompareRegisters(R1, R0);
       __ b(&done, NE);
-      __ LoadObject(R0, Bool::False(), PP);
+      __ LoadObject(R0, Bool::False());
     } else {
       __ Pop(R0);
     }
     __ b(&done);
   }
   __ Bind(&is_not_instance);
-  __ LoadObject(R0, Bool::Get(negate_result), PP);
+  __ LoadObject(R0, Bool::Get(negate_result));
   __ b(&done);
 
   __ Bind(&is_instance);
-  __ LoadObject(R0, Bool::Get(!negate_result), PP);
+  __ LoadObject(R0, Bool::Get(!negate_result));
   __ Bind(&done);
   // Remove instantiator (R2) and its type arguments (R1).
   __ Drop(2);
@@ -674,15 +675,15 @@
   __ Push(R1);
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
-  __ CompareObject(R0, Object::null_object(), PP);
+  __ CompareObject(R0, Object::null_object());
   __ b(&is_assignable, EQ);
 
   // Generate throw new TypeError() if the type is malformed or malbounded.
   if (dst_type.IsMalformedOrMalbounded()) {
-    __ PushObject(Object::null_object(), PP);  // Make room for the result.
+    __ PushObject(Object::null_object());  // Make room for the result.
     __ Push(R0);  // Push the source object.
-    __ PushObject(dst_name, PP);  // Push the name of the destination.
-    __ PushObject(dst_type, PP);  // Push the type of the destination.
+    __ PushObject(dst_name);  // Push the name of the destination.
+    __ PushObject(dst_type);  // Push the type of the destination.
     GenerateRuntimeCall(token_pos,
                         deopt_id,
                         kBadTypeErrorRuntimeEntry,
@@ -699,7 +700,7 @@
   }
 
   // Generate inline type check, linking to runtime call if not assignable.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, dst_type,
                                         &is_assignable, &runtime_call);
 
@@ -707,14 +708,14 @@
   // Load instantiator (R2) and its type arguments (R1).
   __ ldr(R1, Address(SP));
   __ ldr(R2, Address(SP, 1 * kWordSize));
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
+  __ PushObject(Object::null_object());  // Make room for the result.
   __ Push(R0);  // Push the source object.
-  __ PushObject(dst_type, PP);  // Push the type of the destination.
+  __ PushObject(dst_type);  // Push the type of the destination.
   // Push instantiator (R2) and its type arguments (R1).
   __ Push(R2);
   __ Push(R1);
-  __ PushObject(dst_name, PP);  // Push the name of the destination.
-  __ LoadUniqueObject(R0, test_cache, PP);
+  __ PushObject(dst_name);  // Push the name of the destination.
+  __ LoadUniqueObject(R0, test_cache);
   __ Push(R0);
   GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
@@ -760,20 +761,20 @@
   const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
 
   __ LoadFieldFromOffset(
-      R8, R4, ArgumentsDescriptor::positional_count_offset(), PP);
+      R8, R4, ArgumentsDescriptor::positional_count_offset());
   // Check that min_num_pos_args <= num_pos_args.
   Label wrong_num_arguments;
-  __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args), PP);
+  __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args));
   __ b(&wrong_num_arguments, LT);
   // Check that num_pos_args <= max_num_pos_args.
-  __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args), PP);
+  __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args));
   __ b(&wrong_num_arguments, GT);
 
   // Copy positional arguments.
   // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied
   // to fp[kFirstLocalSlotFromFp - i].
 
-  __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP);
+  __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
   // Since R7 and R8 are Smi, use LSL 2 instead of LSL 3.
   // Let R7 point to the last passed positional argument, i.e. to
   // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)].
@@ -783,7 +784,7 @@
 
   // Let R6 point to the last copied positional argument, i.e. to
   // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)].
-  __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize, PP);
+  __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize);
   __ sub(R6, R6, Operand(R8, LSL, 2));  // R8 is a Smi.
   __ SmiUntag(R8);
   Label loop, loop_condition;
@@ -827,14 +828,14 @@
       opt_param_position[i + 1] = pos;
     }
     // Generate code handling each optional parameter in alphabetical order.
-    __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP);
+    __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
     __ LoadFieldFromOffset(
-        R8, R4, ArgumentsDescriptor::positional_count_offset(), PP);
+        R8, R4, ArgumentsDescriptor::positional_count_offset());
     __ SmiUntag(R8);
     // Let R7 point to the first passed argument, i.e. to
     // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi.
     __ add(R7, FP, Operand(R7, LSL, 2));
-    __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize, PP);
+    __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize);
     // Let R6 point to the entry of the first named argument.
     __ add(R6, R4, Operand(
         ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
@@ -843,13 +844,13 @@
       const int param_pos = opt_param_position[i];
       // Check if this named parameter was passed in.
       // Load R5 with the name of the argument.
-      __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset(), PP);
+      __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset());
       ASSERT(opt_param[i]->name().IsSymbol());
-      __ CompareObject(R5, opt_param[i]->name(), PP);
+      __ CompareObject(R5, opt_param[i]->name());
       __ b(&load_default_value, NE);
       // Load R5 with passed-in argument at provided arg_pos, i.e. at
       // fp[kParamEndSlotFromFp + num_args - arg_pos].
-      __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset(), PP);
+      __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset());
       // R5 is arg_pos as Smi.
       // Point to next named entry.
       __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size()));
@@ -861,16 +862,16 @@
       __ Bind(&load_default_value);
       // Load R5 with default argument.
       const Object& value = Object::ZoneHandle(
-          parsed_function().default_parameter_values().At(
+          zone(), parsed_function().default_parameter_values().At(
               param_pos - num_fixed_params));
-      __ LoadObject(R5, value, PP);
+      __ LoadObject(R5, value);
       __ Bind(&assign_optional_parameter);
       // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
       // We do not use the final allocation index of the variable here, i.e.
       // scope->VariableAt(i)->index(), because captured variables still need
       // to be copied to the context that is not yet allocated.
       const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
-      __ StoreToOffset(R5, FP, computed_param_pos * kWordSize, PP);
+      __ StoreToOffset(R5, FP, computed_param_pos * kWordSize);
     }
     delete[] opt_param;
     delete[] opt_param_position;
@@ -878,13 +879,13 @@
       // Check that R6 now points to the null terminator in the arguments
       // descriptor.
       __ ldr(R5, Address(R6));
-      __ CompareObject(R5, Object::null_object(), PP);
+      __ CompareObject(R5, Object::null_object());
       __ b(&all_arguments_processed, EQ);
     }
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ LoadFieldFromOffset(
-        R8, R4, ArgumentsDescriptor::positional_count_offset(), PP);
+        R8, R4, ArgumentsDescriptor::positional_count_offset());
     __ SmiUntag(R8);
     for (int i = 0; i < num_opt_pos_params; i++) {
       Label next_parameter;
@@ -892,22 +893,22 @@
       // arguments have been passed, where k is param_pos, the position of this
       // optional parameter in the formal parameter list.
       const int param_pos = num_fixed_params + i;
-      __ CompareImmediate(R8, param_pos, PP);
+      __ CompareImmediate(R8, param_pos);
       __ b(&next_parameter, GT);
       // Load R5 with default argument.
       const Object& value = Object::ZoneHandle(
-          parsed_function().default_parameter_values().At(i));
-      __ LoadObject(R5, value, PP);
+          zone(), parsed_function().default_parameter_values().At(i));
+      __ LoadObject(R5, value);
       // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
       // We do not use the final allocation index of the variable here, i.e.
       // scope->VariableAt(i)->index(), because captured variables still need
       // to be copied to the context that is not yet allocated.
       const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
-      __ StoreToOffset(R5, FP, computed_param_pos * kWordSize, PP);
+      __ StoreToOffset(R5, FP, computed_param_pos * kWordSize);
       __ Bind(&next_parameter);
     }
     if (check_correct_named_args) {
-      __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP);
+      __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
       __ SmiUntag(R7);
       // Check that R8 equals R7, i.e. no named arguments passed.
       __ CompareRegisters(R8, R7);
@@ -917,9 +918,12 @@
 
   __ Bind(&wrong_num_arguments);
   if (function.IsClosureFunction()) {
+    ASSERT(assembler()->constant_pool_allowed());
     __ LeaveDartFrame();  // The arguments are still on the stack.
-    __ BranchPatchable(
-        &isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+    // Do not use caller's pool ptr in branch.
+    ASSERT(!assembler()->constant_pool_allowed());
+    __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry());
+    __ set_constant_pool_allowed(true);
     // The noSuchMethod call may return to the caller, but not here.
   } else if (check_correct_named_args) {
     __ Stop("Wrong arguments");
@@ -933,11 +937,11 @@
   // an issue anymore.
 
   // R4 : arguments descriptor array.
-  __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset(), PP);
+  __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset());
   __ SmiUntag(R8);
   __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize));
   const Address original_argument_addr(R7, R8, UXTX, Address::Scaled);
-  __ LoadObject(TMP, Object::null_object(), PP);
+  __ LoadObject(TMP, Object::null_object());
   Label null_args_loop, null_args_loop_condition;
   __ b(&null_args_loop_condition);
   __ Bind(&null_args_loop);
@@ -953,8 +957,8 @@
   // SP: receiver.
   // Sequence node has one return node, its input is load field node.
   __ Comment("Inlined Getter");
-  __ LoadFromOffset(R0, SP, 0 * kWordSize, PP);
-  __ LoadFromOffset(R0, R0, offset - kHeapObjectTag, PP);
+  __ LoadFromOffset(R0, SP, 0 * kWordSize);
+  __ LoadFromOffset(R0, R0, offset - kHeapObjectTag);
   __ ret();
 }
 
@@ -965,56 +969,48 @@
   // SP+0: value.
   // Sequence node has one store node and one return NULL node.
   __ Comment("Inlined Setter");
-  __ LoadFromOffset(R0, SP, 1 * kWordSize, PP);  // Receiver.
-  __ LoadFromOffset(R1, SP, 0 * kWordSize, PP);  // Value.
-  __ StoreIntoObjectOffset(R0, offset, R1, PP);
-  __ LoadObject(R0, Object::null_object(), PP);
+  __ LoadFromOffset(R0, SP, 1 * kWordSize);  // Receiver.
+  __ LoadFromOffset(R1, SP, 0 * kWordSize);  // Value.
+  __ StoreIntoObjectOffset(R0, offset, R1);
+  __ LoadObject(R0, Object::null_object());
   __ ret();
 }
 
 
 void FlowGraphCompiler::EmitFrameEntry() {
   const Function& function = parsed_function().function();
-  Register new_pp = kNoPP;
+  Register new_pp = kNoRegister;
   if (CanOptimizeFunction() &&
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = R6;
-    StubCode* stub_code = isolate()->stub_code();
     new_pp = R13;
-
-    // Set up pool pointer in new_pp.
+    // The pool pointer is not setup before entering the Dart frame.
+    // Temporarily setup pool pointer for this dart function.
     __ LoadPoolPointer(new_pp);
 
     // Load function object using the callee's pool pointer.
-    __ LoadObject(function_reg, function, new_pp);
+    __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
 
     // Patch point is after the eventually inlined function object.
     entry_patch_pc_offset_ = assembler()->CodeSize();
 
     __ LoadFieldFromOffset(
-        R7, function_reg, Function::usage_counter_offset(), new_pp, kWord);
+        R7, function_reg, Function::usage_counter_offset(), kWord);
     // Reoptimization of an optimized function is triggered by counting in
     // IC stubs, but not at the entry of the function.
     if (!is_optimizing()) {
       __ add(R7, R7, Operand(1));
       __ StoreFieldToOffset(
-          R7, function_reg, Function::usage_counter_offset(), new_pp, kWord);
+          R7, function_reg, Function::usage_counter_offset(), kWord);
     }
-    __ CompareImmediate(R7, GetOptimizationThreshold(), new_pp);
+    __ CompareImmediate(R7, GetOptimizationThreshold());
     ASSERT(function_reg == R6);
     Label dont_optimize;
     __ b(&dont_optimize, LT);
-    __ Branch(&stub_code->OptimizeFunctionLabel(), new_pp);
+    __ Branch(*StubCode::OptimizeFunction_entry());
     __ Bind(&dont_optimize);
   } else if (!flow_graph().IsCompiledForOsr()) {
-    // We have to load the PP here too because a load of an external label
-    // may be patched at the AddCurrentDescriptor below.
-    new_pp = R13;
-
-    // Set up pool pointer in new_pp.
-    __ LoadPoolPointer(new_pp);
-
     entry_patch_pc_offset_ = assembler()->CodeSize();
   }
   __ Comment("Enter frame");
@@ -1044,13 +1040,13 @@
   TryIntrinsify();
 
   EmitFrameEntry();
+  ASSERT(assembler()->constant_pool_allowed());
 
   const Function& function = parsed_function().function();
 
   const int num_fixed_params = function.num_fixed_parameters();
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
-  StubCode* stub_code = isolate()->stub_code();
 
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
@@ -1068,18 +1064,21 @@
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
       Label correct_num_arguments, wrong_num_arguments;
-      __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset(), PP);
-      __ CompareImmediate(R0, Smi::RawValue(num_fixed_params), PP);
+      __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset());
+      __ CompareImmediate(R0, Smi::RawValue(num_fixed_params));
       __ b(&wrong_num_arguments, NE);
       __ LoadFieldFromOffset(R1, R4,
-            ArgumentsDescriptor::positional_count_offset(), PP);
+            ArgumentsDescriptor::positional_count_offset());
       __ CompareRegisters(R0, R1);
       __ b(&correct_num_arguments, EQ);
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction()) {
+        ASSERT(assembler()->constant_pool_allowed());
         __ LeaveDartFrame();  // The arguments are still on the stack.
-        __ BranchPatchable(
-            &isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+        // Do not use caller's pool ptr in branch.
+        ASSERT(!assembler()->constant_pool_allowed());
+        __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry());
+        __ set_constant_pool_allowed(true);
         // The noSuchMethod call may return to the caller, but not here.
       } else {
         __ Stop("Wrong number of arguments");
@@ -1107,22 +1106,22 @@
     const intptr_t context_index =
         parsed_function().current_context_var()->index();
     if (num_locals > 1) {
-      __ LoadObject(R0, Object::null_object(), PP);
+      __ LoadObject(R0, Object::null_object());
     }
     for (intptr_t i = 0; i < num_locals; ++i) {
       // Subtract index i (locals lie at lower addresses than FP).
       if (((slot_base - i) == context_index)) {
         if (function.IsClosureFunction()) {
-          __ StoreToOffset(CTX, FP, (slot_base - i) * kWordSize, PP);
+          __ StoreToOffset(CTX, FP, (slot_base - i) * kWordSize);
         } else {
           const Context& empty_context = Context::ZoneHandle(
               zone(), isolate()->object_store()->empty_context());
-          __ LoadObject(R1, empty_context, PP);
-          __ StoreToOffset(R1, FP, (slot_base - i) * kWordSize, PP);
+          __ LoadObject(R1, empty_context);
+          __ StoreToOffset(R1, FP, (slot_base - i) * kWordSize);
         }
       } else {
         ASSERT(num_locals > 1);
-        __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize, PP);
+        __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize);
       }
     }
   }
@@ -1130,25 +1129,26 @@
   VisitBlocks();
 
   __ brk(0);
+  ASSERT(assembler()->constant_pool_allowed());
   GenerateDeferredCode();
 
   // Emit function patching code. This will be swapped with the first 3
   // instructions at entry point.
   patch_code_pc_offset_ = assembler()->CodeSize();
-  __ BranchPatchable(&stub_code->FixCallersTargetLabel());
+  __ BranchPatchable(*StubCode::FixCallersTarget_entry());
 
   if (is_optimizing()) {
     lazy_deopt_pc_offset_ = assembler()->CodeSize();
-  __ BranchPatchable(&stub_code->DeoptimizeLazyLabel());
+  __ BranchPatchable(*StubCode::DeoptimizeLazy_entry());
   }
 }
 
 
 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
-                                     const ExternalLabel* label,
+                                     const StubEntry& stub_entry,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ BranchLinkPatchable(label);
+  __ BranchLinkPatchable(stub_entry);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
 }
@@ -1156,10 +1156,10 @@
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          intptr_t token_pos,
-                                         const ExternalLabel* label,
+                                         const StubEntry& stub_entry,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  __ BranchLinkPatchable(label);
+  __ BranchLinkPatchable(stub_entry);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
   // Marks either the continuation point in unoptimized code or the
@@ -1204,24 +1204,25 @@
   // overflow; and though we do not reset the counters when we optimize or
   // deoptimize, there is a bound on the number of
   // optimization/deoptimization cycles we will attempt.
-  const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
-  counter.SetAt(0, Smi::Handle(Smi::New(0)));
+  ASSERT(assembler_->constant_pool_allowed());
+  const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
+  counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
   __ Comment("Edge counter");
-  __ LoadUniqueObject(R0, counter, PP);
-  __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0), PP);
+  __ LoadUniqueObject(R0, counter);
+  __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0));
   __ add(TMP, TMP, Operand(Smi::RawValue(1)));
-  __ StoreFieldToOffset(TMP, R0, Array::element_offset(0), PP);
+  __ StoreFieldToOffset(TMP, R0, Array::element_offset(0));
 }
 
 
 void FlowGraphCompiler::EmitOptimizedInstanceCall(
-    ExternalLabel* target_label,
+    const StubEntry& stub_entry,
     const ICData& ic_data,
     intptr_t argument_count,
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
   // to inlining in optimized code, that function may not correspond to the
@@ -1229,28 +1230,28 @@
   // reoptimized and which counter needs to be incremented.
   // Pass the function explicitly, it is used in IC stub.
 
-  __ LoadObject(R6, parsed_function().function(), PP);
-  __ LoadUniqueObject(R5, ic_data, PP);
+  __ LoadObject(R6, parsed_function().function());
+  __ LoadUniqueObject(R5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
 }
 
 
-void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
+void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
                                          const ICData& ic_data,
                                          intptr_t argument_count,
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
-  __ LoadUniqueObject(R5, ic_data, PP);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  __ LoadUniqueObject(R5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
@@ -1264,26 +1265,25 @@
     intptr_t token_pos,
     LocationSummary* locs) {
   MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
-  const String& name = String::Handle(ic_data.target_name());
+  const String& name = String::Handle(zone(), ic_data.target_name());
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ic_data.arguments_descriptor());
+      Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
-  const MegamorphicCache& cache =
-      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
+      zone(), table->Lookup(name, arguments_descriptor));
   const Register receiverR = R0;
   const Register cacheR = R1;
   const Register targetR = R1;
-  __ LoadFromOffset(receiverR, SP, (argument_count - 1) * kWordSize, PP);
-  __ LoadObject(cacheR, cache, PP);
+  __ LoadFromOffset(receiverR, SP, (argument_count - 1) * kWordSize);
+  __ LoadObject(cacheR, cache);
 
   if (FLAG_use_megamorphic_stub) {
-    StubCode* stub_code = isolate()->stub_code();
-    __ BranchLink(&stub_code->MegamorphicLookupLabel(), PP);
+    __ BranchLink(*StubCode::MegamorphicLookup_entry());
   } else  {
     StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
   }
-  __ LoadObject(R5, ic_data, PP);
-  __ LoadObject(R4, arguments_descriptor, PP);
+  __ LoadObject(R5, ic_data);
+  __ LoadObject(R4, arguments_descriptor);
   __ blr(targetR);
   AddCurrentDescriptor(RawPcDescriptors::kOther,
       Isolate::kNoDeoptId, token_pos);
@@ -1306,14 +1306,12 @@
     intptr_t token_pos,
     LocationSummary* locs,
     const ICData& ic_data) {
-  StubCode* stub_code = isolate()->stub_code();
-  const uword label_address =
-      stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
-  ExternalLabel target_label(label_address);
-  __ LoadObject(R5, ic_data, PP);
+  const StubEntry* stub_entry =
+      StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
+  __ LoadObject(R5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &target_label,
+                   *stub_entry,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count);
@@ -1327,13 +1325,12 @@
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  StubCode* stub_code = isolate()->stub_code();
-  __ LoadObject(R4, arguments_descriptor, PP);
+  __ LoadObject(R4, arguments_descriptor);
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &stub_code->CallStaticFunctionLabel(),
+                   *StubCode::CallStaticFunction_entry(),
                    RawPcDescriptors::kOther,
                    locs);
   AddStaticCallTarget(function);
@@ -1347,16 +1344,15 @@
     bool needs_number_check,
     intptr_t token_pos) {
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
     __ Push(reg);
-    __ PushObject(obj, PP);
+    __ PushObject(obj);
     if (is_optimizing()) {
       __ BranchLinkPatchable(
-          &stub_code->OptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
       __ BranchLinkPatchable(
-          &stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1367,7 +1363,7 @@
     __ Drop(1);  // Discard constant.
     __ Pop(reg);  // Restore 'reg'.
   } else {
-    __ CompareObject(reg, obj, PP);
+    __ CompareObject(reg, obj);
   }
   return EQ;
 }
@@ -1378,15 +1374,14 @@
                                                        bool needs_number_check,
                                                        intptr_t token_pos) {
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ Push(left);
     __ Push(right);
     if (is_optimizing()) {
       __ BranchLinkPatchable(
-          &stub_code->OptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
       __ BranchLinkPatchable(
-          &stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1487,13 +1482,12 @@
 
   __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
-                                                 argument_names));
-  StubCode* stub_code = isolate()->stub_code();
+      Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
+                                                         argument_names));
 
   // Load receiver into R0.
-  __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize, PP);
-  __ LoadObject(R4, arguments_descriptor, PP);
+  __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
+  __ LoadObject(R4, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
   const intptr_t kNumChecks = ic_data.NumberOfChecks();
@@ -1513,10 +1507,10 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
-    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
     AddStaticCallTarget(function);
     __ Drop(argument_count);
     if (kNumChecks > 1) {
@@ -1539,12 +1533,12 @@
   // will fail if there was only one check and receiver is not Smi.
   if (kSortedLen == 0) return;
 
-  __ LoadClassId(R2, R0, PP);
+  __ LoadClassId(R2, R0);
   for (intptr_t i = 0; i < kSortedLen; i++) {
     const bool kIsLastCheck = (i == (kSortedLen - 1));
     ASSERT(sorted[i].cid != kSmiCid);
     Label next_test;
-    __ CompareImmediate(R2, sorted[i].cid, PP);
+    __ CompareImmediate(R2, sorted[i].cid);
     if (kIsLastCheck) {
       __ b(failed, NE);
     } else {
@@ -1554,7 +1548,7 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
     const Function& function = *sorted[i].target;
@@ -1583,20 +1577,20 @@
     } else {
       ASSERT(destination.IsStackSlot());
       const intptr_t dest_offset = destination.ToStackSlotOffset();
-      __ StoreToOffset(source.reg(), destination.base_reg(), dest_offset, PP);
+      __ StoreToOffset(source.reg(), destination.base_reg(), dest_offset);
     }
   } else if (source.IsStackSlot()) {
     if (destination.IsRegister()) {
       const intptr_t source_offset = source.ToStackSlotOffset();
       __ LoadFromOffset(
-          destination.reg(), source.base_reg(), source_offset, PP);
+          destination.reg(), source.base_reg(), source_offset);
     } else {
       ASSERT(destination.IsStackSlot());
       const intptr_t source_offset = source.ToStackSlotOffset();
       const intptr_t dest_offset = destination.ToStackSlotOffset();
       ScratchRegisterScope tmp(this, kNoRegister);
-      __ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset, PP);
-      __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset, PP);
+      __ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset);
+      __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset);
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
@@ -1605,37 +1599,37 @@
       if (destination.IsDoubleStackSlot()) {
         const intptr_t dest_offset = destination.ToStackSlotOffset();
         VRegister src = source.fpu_reg();
-        __ StoreDToOffset(src, destination.base_reg(), dest_offset, PP);
+        __ StoreDToOffset(src, destination.base_reg(), dest_offset);
       } else {
         ASSERT(destination.IsQuadStackSlot());
         const intptr_t dest_offset = destination.ToStackSlotOffset();
         __ StoreQToOffset(
-            source.fpu_reg(), destination.base_reg(), dest_offset, PP);
+            source.fpu_reg(), destination.base_reg(), dest_offset);
       }
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
       const intptr_t source_offset = source.ToStackSlotOffset();
       const VRegister dst = destination.fpu_reg();
-      __ LoadDFromOffset(dst, source.base_reg(), source_offset, PP);
+      __ LoadDFromOffset(dst, source.base_reg(), source_offset);
     } else {
       ASSERT(destination.IsDoubleStackSlot());
       const intptr_t source_offset = source.ToStackSlotOffset();
       const intptr_t dest_offset = destination.ToStackSlotOffset();
-      __ LoadDFromOffset(VTMP, source.base_reg(), source_offset, PP);
-      __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP);
+      __ LoadDFromOffset(VTMP, source.base_reg(), source_offset);
+      __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset);
     }
   } else if (source.IsQuadStackSlot()) {
     if (destination.IsFpuRegister()) {
       const intptr_t source_offset = source.ToStackSlotOffset();
       __ LoadQFromOffset(
-          destination.fpu_reg(), source.base_reg(), source_offset, PP);
+          destination.fpu_reg(), source.base_reg(), source_offset);
     } else {
       ASSERT(destination.IsQuadStackSlot());
       const intptr_t source_offset = source.ToStackSlotOffset();
       const intptr_t dest_offset = destination.ToStackSlotOffset();
-      __ LoadQFromOffset(VTMP, source.base_reg(), source_offset, PP);
-      __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset, PP);
+      __ LoadQFromOffset(VTMP, source.base_reg(), source_offset);
+      __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset);
     }
   } else {
     ASSERT(source.IsConstant());
@@ -1644,10 +1638,9 @@
       if (constant.IsSmi() &&
           (source.constant_instruction()->representation() == kUnboxedInt32)) {
         __ LoadImmediate(destination.reg(),
-                         static_cast<int32_t>(Smi::Cast(constant).Value()),
-                         PP);
+                         static_cast<int32_t>(Smi::Cast(constant).Value()));
       } else {
-        __ LoadObject(destination.reg(), constant, PP);
+        __ LoadObject(destination.reg(), constant);
       }
     } else if (destination.IsFpuRegister()) {
       const VRegister dst = destination.fpu_reg();
@@ -1655,19 +1648,19 @@
         __ veor(dst, dst, dst);
       } else {
         ScratchRegisterScope tmp(this, kNoRegister);
-        __ LoadObject(tmp.reg(), constant, PP);
-        __ LoadDFieldFromOffset(dst, tmp.reg(), Double::value_offset(), PP);
+        __ LoadObject(tmp.reg(), constant);
+        __ LoadDFieldFromOffset(dst, tmp.reg(), Double::value_offset());
       }
     } else if (destination.IsDoubleStackSlot()) {
       if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
         __ veor(VTMP, VTMP, VTMP);
       } else {
         ScratchRegisterScope tmp(this, kNoRegister);
-        __ LoadObject(tmp.reg(), constant, PP);
-        __ LoadDFieldFromOffset(VTMP, tmp.reg(), Double::value_offset(), PP);
+        __ LoadObject(tmp.reg(), constant);
+        __ LoadDFieldFromOffset(VTMP, tmp.reg(), Double::value_offset());
       }
       const intptr_t dest_offset = destination.ToStackSlotOffset();
-      __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP);
+      __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset);
     } else {
       ASSERT(destination.IsStackSlot());
       const intptr_t dest_offset = destination.ToStackSlotOffset();
@@ -1675,12 +1668,11 @@
       if (constant.IsSmi() &&
           (source.constant_instruction()->representation() == kUnboxedInt32)) {
         __ LoadImmediate(tmp.reg(),
-                         static_cast<int32_t>(Smi::Cast(constant).Value()),
-                         PP);
+                         static_cast<int32_t>(Smi::Cast(constant).Value()));
       } else {
-        __ LoadObject(tmp.reg(), constant, PP);
+        __ LoadObject(tmp.reg(), constant);
       }
-      __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset, PP);
+      __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset);
     }
   }
 
@@ -1731,12 +1723,12 @@
         : source.ToStackSlotOffset();
 
     if (double_width) {
-      __ LoadDFromOffset(VTMP, base_reg, slot_offset, PP);
-      __ StoreDToOffset(reg, base_reg, slot_offset, PP);
+      __ LoadDFromOffset(VTMP, base_reg, slot_offset);
+      __ StoreDToOffset(reg, base_reg, slot_offset);
       __ fmovdd(reg, VTMP);
     } else {
-      __ LoadQFromOffset(VTMP, base_reg, slot_offset, PP);
-      __ StoreQToOffset(reg, base_reg, slot_offset, PP);
+      __ LoadQFromOffset(VTMP, base_reg, slot_offset);
+      __ StoreQToOffset(reg, base_reg, slot_offset);
       __ vmov(reg, VTMP);
     }
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
@@ -1745,20 +1737,20 @@
 
     ScratchFpuRegisterScope ensure_scratch(this, kNoFpuRegister);
     VRegister scratch = ensure_scratch.reg();
-    __ LoadDFromOffset(VTMP, source.base_reg(), source_offset, PP);
-    __ LoadDFromOffset(scratch, destination.base_reg(), dest_offset, PP);
-    __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP);
-    __ StoreDToOffset(scratch, source.base_reg(), source_offset, PP);
+    __ LoadDFromOffset(VTMP, source.base_reg(), source_offset);
+    __ LoadDFromOffset(scratch, destination.base_reg(), dest_offset);
+    __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset);
+    __ StoreDToOffset(scratch, source.base_reg(), source_offset);
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
     const intptr_t source_offset = source.ToStackSlotOffset();
     const intptr_t dest_offset = destination.ToStackSlotOffset();
 
     ScratchFpuRegisterScope ensure_scratch(this, kNoFpuRegister);
     VRegister scratch = ensure_scratch.reg();
-    __ LoadQFromOffset(VTMP, source.base_reg(), source_offset, PP);
-    __ LoadQFromOffset(scratch, destination.base_reg(), dest_offset, PP);
-    __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset, PP);
-    __ StoreQToOffset(scratch, source.base_reg(), source_offset, PP);
+    __ LoadQFromOffset(VTMP, source.base_reg(), source_offset);
+    __ LoadQFromOffset(scratch, destination.base_reg(), dest_offset);
+    __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset);
+    __ StoreQToOffset(scratch, source.base_reg(), source_offset);
   } else {
     UNREACHABLE();
   }
@@ -1811,8 +1803,8 @@
                                     intptr_t stack_offset) {
   ScratchRegisterScope tmp(this, reg);
   __ mov(tmp.reg(), reg);
-  __ LoadFromOffset(reg, base_reg, stack_offset, PP);
-  __ StoreToOffset(tmp.reg(), base_reg, stack_offset, PP);
+  __ LoadFromOffset(reg, base_reg, stack_offset);
+  __ StoreToOffset(tmp.reg(), base_reg, stack_offset);
 }
 
 
@@ -1822,10 +1814,10 @@
                                     intptr_t stack_offset2) {
   ScratchRegisterScope tmp1(this, kNoRegister);
   ScratchRegisterScope tmp2(this, tmp1.reg());
-  __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1, PP);
-  __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2, PP);
-  __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2, PP);
-  __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1, PP);
+  __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1);
+  __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2);
+  __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2);
+  __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 46ce12d..388b6d1 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -100,12 +100,14 @@
   // The real frame starts here.
   builder->MarkFrameStart();
 
+  Zone* zone = compiler->zone();
+
   // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
-  builder->AddPcMarker(Function::Handle(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(zone), slot_ix++);
 
   // Current FP and PC.
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(Function::Handle(current->code().function()),
+  builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
                             deopt_id(),
                             slot_ix++);
 
@@ -122,7 +124,8 @@
   }
 
   // Current PC marker and caller FP.
-  builder->AddPcMarker(Function::Handle(current->code().function()), slot_ix++);
+  builder->AddPcMarker(Function::Handle(
+      zone, current->code().function()), slot_ix++);
   builder->AddCallerFp(slot_ix++);
 
   Environment* previous = current;
@@ -130,9 +133,10 @@
   while (current != NULL) {
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(Function::Handle(current->code().function()),
-                              Isolate::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
+    builder->AddReturnAddress(
+        Function::Handle(zone, current->code().function()),
+        Isolate::ToDeoptAfter(current->deopt_id()),
+        slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
     // we must read them from the previous environment.
@@ -152,7 +156,7 @@
     }
 
     // PC marker and caller FP.
-    builder->AddPcMarker(Function::Handle(current->code().function()),
+    builder->AddPcMarker(Function::Handle(zone, current->code().function()),
                          slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
@@ -189,8 +193,7 @@
 
   ASSERT(deopt_env() != NULL);
 
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  __ call(&stub_code->DeoptimizeLabel());
+  __ Call(*StubCode::Deoptimize_entry());
   set_pc_offset(assem->CodeSize());
   __ int3();
 #undef __
@@ -225,24 +228,23 @@
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
   const SubtypeTestCache& type_test_cache =
-      SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
+      SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  StubCode* stub_code = isolate()->stub_code();
   __ LoadObject(temp_reg, type_test_cache);
   __ pushl(temp_reg);  // Subtype test cache.
   __ pushl(instance_reg);  // Instance.
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
     __ pushl(raw_null);
-    __ call(&stub_code->Subtype1TestCacheLabel());
+    __ Call(*StubCode::Subtype1TestCache_entry());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
     __ pushl(raw_null);
-    __ call(&stub_code->Subtype2TestCacheLabel());
+    __ Call(*StubCode::Subtype2TestCache_entry());
   } else if (test_kind == kTestTypeThreeArgs) {
     __ pushl(type_arguments_reg);
-    __ call(&stub_code->Subtype3TestCacheLabel());
+    __ Call(*StubCode::Subtype3TestCache_entry());
   } else {
     UNREACHABLE();
   }
@@ -270,11 +272,11 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::ZoneHandle(type.type_class());
+  const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
   const Register kInstanceReg = EAX;
-  Error& malformed_error = Error::Handle();
-  const Type& int_type = Type::Handle(Type::IntType());
+  Error& malformed_error = Error::Handle(zone());
+  const Type& int_type = Type::Handle(zone(), Type::IntType());
   const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
   // Malformed type should have been handled at graph construction time.
   ASSERT(smi_is_ok || malformed_error.IsNull());
@@ -288,7 +290,7 @@
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
   const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(type.arguments());
+      TypeArguments::ZoneHandle(zone(), type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -309,12 +311,12 @@
     // If one type argument only, check if type argument is Object or dynamic.
     if (type_arguments.Length() == 1) {
       const AbstractType& tp_argument = AbstractType::ZoneHandle(
-          type_arguments.TypeAt(0));
+          zone(), type_arguments.TypeAt(0));
       ASSERT(!tp_argument.IsMalformed());
       if (tp_argument.IsType()) {
         ASSERT(tp_argument.HasResolvedTypeClass());
         // Check if type argument is dynamic or Object.
-        const Type& object_type = Type::Handle(Type::ObjectType());
+        const Type& object_type = Type::Handle(zone(), Type::ObjectType());
         if (object_type.IsSubtypeOf(tp_argument, NULL)) {
           // Instance class test only necessary.
           return GenerateSubtype1TestCacheLookup(
@@ -359,16 +361,16 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::Handle(type.type_class());
+  const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
   const Register kInstanceReg = EAX;
   __ testl(kInstanceReg, Immediate(kSmiTagMask));
   // If instance is Smi, check directly.
-  const Class& smi_class = Class::Handle(Smi::Class());
-  if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
+  const Class& smi_class = Class::Handle(zone(), Smi::Class());
+  if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
                             type_class,
-                            TypeArguments::Handle(),
+                            TypeArguments::Handle(zone()),
                             NULL)) {
     __ j(ZERO, is_instance_lbl);
   } else {
@@ -399,7 +401,7 @@
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
-  if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
+  if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
     GenerateNumberTypeCheck(
         kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
     return false;
@@ -471,18 +473,18 @@
         FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index())));
     // EDI: concrete type of type.
     // Check if type argument is dynamic.
-    __ CompareObject(EDI, Type::ZoneHandle(Type::DynamicType()));
+    __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::DynamicType()));
     __ j(EQUAL,  is_instance_lbl);
-    __ CompareObject(EDI, Type::ZoneHandle(Type::ObjectType()));
+    __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::ObjectType()));
     __ j(EQUAL,  is_instance_lbl);
 
     // For Smi check quickly against int and num interfaces.
     Label not_smi;
     __ testl(EAX, Immediate(kSmiTagMask));  // Value is Smi?
     __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
-    __ CompareObject(EDI, Type::ZoneHandle(Type::IntType()));
+    __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::IntType()));
     __ j(EQUAL,  is_instance_lbl);
-    __ CompareObject(EDI, Type::ZoneHandle(Type::Number()));
+    __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::Number()));
     __ j(EQUAL,  is_instance_lbl);
     // Smi must be handled in runtime.
     Label fall_through;
@@ -495,7 +497,7 @@
     const Register kTypeArgumentsReg = EDX;
     const Register kTempReg = EDI;
     const SubtypeTestCache& type_test_cache =
-        SubtypeTestCache::ZoneHandle(
+        SubtypeTestCache::ZoneHandle(zone(),
             GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
                                         kInstanceReg,
                                         kTypeArgumentsReg,
@@ -546,7 +548,7 @@
     return SubtypeTestCache::null();
   }
   if (type.IsInstantiated()) {
-    const Class& type_class = Class::ZoneHandle(type.type_class());
+    const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
     // A class equality check is only applicable with a dst type of a
     // non-parameterized class, non-signature class, or with a raw dst type of
     // a parameterized class.
@@ -617,7 +619,7 @@
   }
 
   // Generate inline instanceof test.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, type,
                                         &is_instance, &is_not_instance);
 
@@ -718,7 +720,7 @@
   }
 
   // Generate inline type check, linking to runtime call if not assignable.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, dst_type,
                                         &is_assignable, &runtime_call);
 
@@ -882,7 +884,7 @@
       __ jmp(&assign_optional_parameter, Assembler::kNearJump);
       __ Bind(&load_default_value);
       // Load EAX with default argument.
-      const Object& value = Object::ZoneHandle(
+      const Object& value = Object::ZoneHandle(zone(),
           parsed_function().default_parameter_values().At(
               param_pos - num_fixed_params));
       __ LoadObject(EAX, value);
@@ -917,7 +919,7 @@
       __ cmpl(ECX, Immediate(param_pos));
       __ j(GREATER, &next_parameter, Assembler::kNearJump);
       // Load EAX with default argument.
-      const Object& value = Object::ZoneHandle(
+      const Object& value = Object::ZoneHandle(zone(),
           parsed_function().default_parameter_values().At(i));
       __ LoadObject(EAX, value);
       // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos].
@@ -941,7 +943,7 @@
   __ Bind(&wrong_num_arguments);
   if (function.IsClosureFunction()) {
     __ LeaveFrame();  // The arguments are still on the stack.
-    __ jmp(&isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+    __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
     // The noSuchMethod call may return to the caller, but not here.
   } else if (check_correct_named_args) {
     __ Stop("Wrong arguments");
@@ -1003,7 +1005,6 @@
   if (CanOptimizeFunction() &&
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
-    StubCode* stub_code = isolate()->stub_code();
     const Register function_reg = EDI;
     __ LoadObject(function_reg, function);
 
@@ -1018,7 +1019,7 @@
     __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()),
             Immediate(GetOptimizationThreshold()));
     ASSERT(function_reg == EDI);
-    __ j(GREATER_EQUAL, &stub_code->OptimizeFunctionLabel());
+    __ J(GREATER_EQUAL, *StubCode::OptimizeFunction_entry());
   } else if (!flow_graph().IsCompiledForOsr()) {
     entry_patch_pc_offset_ = assembler()->CodeSize();
   }
@@ -1048,7 +1049,6 @@
   const int num_fixed_params = function.num_fixed_parameters();
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
-  StubCode* stub_code = isolate()->stub_code();
 
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
@@ -1077,7 +1077,7 @@
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction()) {
         __ LeaveFrame();  // The arguments are still on the stack.
-        __ jmp(&stub_code->CallClosureNoSuchMethodLabel());
+        __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
         // The noSuchMethod call may return to the caller, but not here.
       } else {
         __ Stop("Wrong number of arguments");
@@ -1145,20 +1145,20 @@
   // Emit function patching code. This will be swapped with the first 5 bytes
   // at entry point.
   patch_code_pc_offset_ = assembler()->CodeSize();
-  __ jmp(&stub_code->FixCallersTargetLabel());
+  __ Jmp(*StubCode::FixCallersTarget_entry());
 
   if (is_optimizing()) {
     lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ jmp(&stub_code->DeoptimizeLazyLabel());
+    __ Jmp(*StubCode::DeoptimizeLazy_entry());
   }
 }
 
 
 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
-                                     const ExternalLabel* label,
+                                     const StubEntry& stub_entry,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ call(label);
+  __ Call(stub_entry);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
 }
@@ -1166,10 +1166,10 @@
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          intptr_t token_pos,
-                                         const ExternalLabel* label,
+                                         const StubEntry& stub_entry,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  __ call(label);
+  __ Call(stub_entry);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
   // Marks either the continuation point in unoptimized code or the
@@ -1214,14 +1214,12 @@
     intptr_t token_pos,
     LocationSummary* locs,
     const ICData& ic_data) {
-  StubCode* stub_code = isolate()->stub_code();
-  const uword label_address =
-      stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
-  ExternalLabel target_label(label_address);
+  const StubEntry& stub_entry =
+      *StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(ECX, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &target_label,
+                   stub_entry,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count);
@@ -1234,8 +1232,8 @@
   // overflow; and though we do not reset the counters when we optimize or
   // deoptimize, there is a bound on the number of
   // optimization/deoptimization cycles we will attempt.
-  const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
-  counter.SetAt(0, Smi::Handle(Smi::New(0)));
+  const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
+  counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
   __ Comment("Edge counter");
   __ LoadObject(EAX, counter);
   intptr_t increment_start = assembler_->CodeSize();
@@ -1257,7 +1255,7 @@
 
 
 void FlowGraphCompiler::EmitOptimizedInstanceCall(
-    ExternalLabel* target_label,
+    const StubEntry& stub_entry,
     const ICData& ic_data,
     intptr_t argument_count,
     intptr_t deopt_id,
@@ -1274,14 +1272,14 @@
   __ LoadObject(ECX, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
 }
 
 
-void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
+void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
                                          const ICData& ic_data,
                                          intptr_t argument_count,
                                          intptr_t deopt_id,
@@ -1291,7 +1289,7 @@
   __ LoadObject(ECX, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
@@ -1305,12 +1303,12 @@
     intptr_t token_pos,
     LocationSummary* locs) {
   MegamorphicCacheTable* table = isolate()->megamorphic_cache_table();
-  const String& name = String::Handle(ic_data.target_name());
+  const String& name = String::Handle(zone(), ic_data.target_name());
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ic_data.arguments_descriptor());
+      Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
-  const MegamorphicCache& cache =
-      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
+      table->Lookup(name, arguments_descriptor));
   const Register receiverR = EDI;
   const Register cacheR = EBX;
   const Register targetR = EBX;
@@ -1318,8 +1316,7 @@
   __ LoadObject(cacheR, cache);
 
   if (FLAG_use_megamorphic_stub) {
-    StubCode* stub_code = isolate()->stub_code();
-    __ call(&stub_code->MegamorphicLookupLabel());
+    __ Call(*StubCode::MegamorphicLookup_entry());
   } else  {
     StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
   }
@@ -1349,13 +1346,12 @@
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  StubCode* stub_code = isolate()->stub_code();
   __ LoadObject(EDX, arguments_descriptor);
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &stub_code->CallStaticFunctionLabel(),
+                   *StubCode::CallStaticFunction_entry(),
                    RawPcDescriptors::kOther,
                    locs);
   AddStaticCallTarget(function);
@@ -1378,13 +1374,12 @@
   }
 
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ pushl(reg);
     __ PushObject(obj);
     if (is_optimizing()) {
-      __ call(&stub_code->OptimizedIdenticalWithNumberCheckLabel());
+      __ Call(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
-      __ call(&stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+      __ Call(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1406,13 +1401,12 @@
                                                        bool needs_number_check,
                                                        intptr_t token_pos) {
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ pushl(left);
     __ pushl(right);
     if (is_optimizing()) {
-      __ call(&stub_code->OptimizedIdenticalWithNumberCheckLabel());
+      __ Call(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
-      __ call(&stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+      __ Call(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1519,9 +1513,8 @@
   ASSERT(is_optimizing());
   __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
-                                                 argument_names));
-  StubCode* stub_code = isolate()->stub_code();
+      Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
+                                                         argument_names));
   // Load receiver into EAX.
   __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
   __ LoadObject(EDX, arguments_descriptor);
@@ -1544,10 +1537,10 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
-    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
     AddStaticCallTarget(function);
     __ Drop(argument_count);
     if (kNumChecks > 1) {
@@ -1586,7 +1579,7 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
     const Function& function = *sorted[i].target;
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index b65b62e..a717323 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -62,14 +62,14 @@
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
-  assembler()->set_allow_constant_pool(false);
+  assembler()->set_constant_pool_allowed(false);
 }
 
 
 void FlowGraphCompiler::ExitIntrinsicMode() {
   ASSERT(intrinsic_mode());
   intrinsic_mode_ = false;
-  assembler()->set_allow_constant_pool(true);
+  assembler()->set_constant_pool_allowed(true);
 }
 
 
@@ -94,15 +94,17 @@
   // The real frame starts here.
   builder->MarkFrameStart();
 
+  Zone* zone = compiler->zone();
+
   // Current PP, FP, and PC.
-  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+  builder->AddPp(Function::Handle(zone, current->code().function()), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(Function::Handle(current->code().function()),
+  builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
                             deopt_id(),
                             slot_ix++);
 
   // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
-  builder->AddPcMarker(Function::Handle(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(zone), slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -120,17 +122,19 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+    builder->AddPp(
+        Function::Handle(zone, current->code().function()), slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(Function::Handle(current->code().function()),
-                              Isolate::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
+    builder->AddReturnAddress(
+        Function::Handle(zone, current->code().function()),
+        Isolate::ToDeoptAfter(current->deopt_id()),
+        slot_ix++);
 
     // PC marker.
-    builder->AddPcMarker(Function::Handle(previous->code().function()),
+    builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                          slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
@@ -163,7 +167,7 @@
   builder->AddCallerPc(slot_ix++);
 
   // PC marker.
-  builder->AddPcMarker(Function::Handle(previous->code().function()),
+  builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                        slot_ix++);
 
   // For the outermost environment, set the incoming arguments.
@@ -189,8 +193,7 @@
 
   ASSERT(deopt_env() != NULL);
 
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  __ BranchLink(&stub_code->DeoptimizeLabel());
+  __ BranchLink(*StubCode::Deoptimize_entry());
   set_pc_offset(assem->CodeSize());
 #undef __
 }
@@ -225,20 +228,19 @@
   ASSERT(instance_reg == A0);
   ASSERT(temp_reg == kNoRegister);  // Unused on MIPS.
   const SubtypeTestCache& type_test_cache =
-      SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
-  StubCode* stub_code = isolate()->stub_code();
+      SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
   __ LoadUniqueObject(A2, type_test_cache);
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
     __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null()));
-    __ BranchLink(&stub_code->Subtype1TestCacheLabel());
+    __ BranchLink(*StubCode::Subtype1TestCache_entry());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
     __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null()));
-    __ BranchLink(&stub_code->Subtype2TestCacheLabel());
+    __ BranchLink(*StubCode::Subtype2TestCache_entry());
   } else if (test_kind == kTestTypeThreeArgs) {
     ASSERT(type_arguments_reg == A1);
-    __ BranchLink(&stub_code->Subtype3TestCacheLabel());
+    __ BranchLink(*StubCode::Subtype3TestCache_entry());
   } else {
     UNREACHABLE();
   }
@@ -261,11 +263,11 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::ZoneHandle(type.type_class());
+  const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
   const Register kInstanceReg = A0;
-  Error& malformed_error = Error::Handle();
-  const Type& int_type = Type::Handle(Type::IntType());
+  Error& malformed_error = Error::Handle(zone());
+  const Type& int_type = Type::Handle(zone(), Type::IntType());
   const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
   // Malformed type should have been handled at graph construction time.
   ASSERT(smi_is_ok || malformed_error.IsNull());
@@ -279,7 +281,7 @@
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
   const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(type.arguments());
+      TypeArguments::ZoneHandle(zone(), type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -298,13 +300,13 @@
     }
     // If one type argument only, check if type argument is Object or dynamic.
     if (type_arguments.Length() == 1) {
-      const AbstractType& tp_argument = AbstractType::ZoneHandle(
+      const AbstractType& tp_argument = AbstractType::ZoneHandle(zone(),
           type_arguments.TypeAt(0));
       ASSERT(!tp_argument.IsMalformed());
       if (tp_argument.IsType()) {
         ASSERT(tp_argument.HasResolvedTypeClass());
         // Check if type argument is dynamic or Object.
-        const Type& object_type = Type::Handle(Type::ObjectType());
+        const Type& object_type = Type::Handle(zone(), Type::ObjectType());
         if (object_type.IsSubtypeOf(tp_argument, NULL)) {
           // Instance class test only necessary.
           return GenerateSubtype1TestCacheLookup(
@@ -350,16 +352,16 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::Handle(type.type_class());
+  const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
   const Register kInstanceReg = A0;
   __ andi(T0, A0, Immediate(kSmiTagMask));
   // If instance is Smi, check directly.
-  const Class& smi_class = Class::Handle(Smi::Class());
-  if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
+  const Class& smi_class = Class::Handle(zone(), Smi::Class());
+  if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
                             type_class,
-                            TypeArguments::Handle(),
+                            TypeArguments::Handle(zone()),
                             NULL)) {
     __ beq(T0, ZR, is_instance_lbl);
   } else {
@@ -386,7 +388,7 @@
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
-  if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
+  if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
     GenerateNumberTypeCheck(
         kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
     return false;
@@ -454,15 +456,19 @@
         FieldAddress(A1, TypeArguments::type_at_offset(type_param.index())));
     // R2: concrete type of type.
     // Check if type argument is dynamic.
-    __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl);
-    __ BranchEqual(T2, Type::ZoneHandle(Type::ObjectType()), is_instance_lbl);
+    __ BranchEqual(T2,
+        Type::ZoneHandle(zone(), Type::DynamicType()), is_instance_lbl);
+    __ BranchEqual(T2,
+        Type::ZoneHandle(zone(), Type::ObjectType()), is_instance_lbl);
 
     // For Smi check quickly against int and num interfaces.
     Label not_smi;
     __ andi(CMPRES1, A0, Immediate(kSmiTagMask));
     __ bne(CMPRES1, ZR, &not_smi);  // Value is Smi?
-    __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl);
-    __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl);
+    __ BranchEqual(T2,
+        Type::ZoneHandle(zone(), Type::IntType()), is_instance_lbl);
+    __ BranchEqual(T2,
+        Type::ZoneHandle(zone(), Type::Number()), is_instance_lbl);
     // Smi must be handled in runtime.
     Label fall_through;
     __ b(&fall_through);
@@ -474,7 +480,7 @@
     const Register kTypeArgumentsReg = A1;
     const Register kTempReg = kNoRegister;
     const SubtypeTestCache& type_test_cache =
-        SubtypeTestCache::ZoneHandle(
+        SubtypeTestCache::ZoneHandle(zone(),
             GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
                                         kInstanceReg,
                                         kTypeArgumentsReg,
@@ -525,7 +531,7 @@
     return SubtypeTestCache::null();
   }
   if (type.IsInstantiated()) {
-    const Class& type_class = Class::ZoneHandle(type.type_class());
+    const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
     // A class equality check is only applicable with a dst type of a
     // non-parameterized class, non-signature class, or with a raw dst type of
     // a parameterized class.
@@ -596,7 +602,7 @@
   }
 
   // Generate inline instanceof test.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, type,
                                         &is_instance, &is_not_instance);
 
@@ -707,7 +713,7 @@
   }
 
   // Generate inline type check, linking to runtime call if not assignable.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, dst_type,
                                         &is_assignable, &runtime_call);
 
@@ -874,7 +880,7 @@
 
       __ Bind(&load_default_value);
       // Load T3 with default argument.
-      const Object& value = Object::ZoneHandle(
+      const Object& value = Object::ZoneHandle(zone(),
           parsed_function().default_parameter_values().At(
               param_pos - num_fixed_params));
       __ LoadObject(T3, value);
@@ -908,7 +914,7 @@
       const int param_pos = num_fixed_params + i;
       __ BranchSignedGreater(T2, Immediate(param_pos), &next_parameter);
       // Load T3 with default argument.
-      const Object& value = Object::ZoneHandle(
+      const Object& value = Object::ZoneHandle(zone(),
           parsed_function().default_parameter_values().At(i));
       __ LoadObject(T3, value);
       // Assign T3 to fp[kFirstLocalSlotFromFp - param_pos].
@@ -930,7 +936,7 @@
   __ Bind(&wrong_num_arguments);
   if (function.IsClosureFunction()) {
     __ LeaveDartFrame();  // The arguments are still on the stack.
-    __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+    __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
     // The noSuchMethod call may return to the caller, but not here.
   } else if (check_correct_named_args) {
     __ Stop("Wrong arguments");
@@ -993,7 +999,6 @@
       function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = T0;
-    StubCode* stub_code = isolate()->stub_code();
 
     __ GetNextPC(T2, TMP);
 
@@ -1028,7 +1033,7 @@
         T1, Immediate(GetOptimizationThreshold()), &dont_branch);
 
     ASSERT(function_reg == T0);
-    __ Branch(&stub_code->OptimizeFunctionLabel());
+    __ Branch(*StubCode::OptimizeFunction_entry());
 
     __ Bind(&dont_branch);
 
@@ -1068,7 +1073,6 @@
   const int num_fixed_params = function.num_fixed_parameters();
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
-  StubCode* stub_code = isolate()->stub_code();
 
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
@@ -1096,7 +1100,7 @@
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction()) {
         __ LeaveDartFrame();  // The arguments are still on the stack.
-        __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+        __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
         // The noSuchMethod call may return to the caller, but not here.
       } else {
         __ Stop("Wrong number of arguments");
@@ -1151,20 +1155,20 @@
   // Emit function patching code. This will be swapped with the first 5 bytes
   // at entry point.
   patch_code_pc_offset_ = assembler()->CodeSize();
-  __ BranchPatchable(&stub_code->FixCallersTargetLabel());
+  __ BranchPatchable(*StubCode::FixCallersTarget_entry());
 
   if (is_optimizing()) {
     lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Branch(&stub_code->DeoptimizeLazyLabel());
+    __ Branch(*StubCode::DeoptimizeLazy_entry());
   }
 }
 
 
 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
-                                     const ExternalLabel* label,
+                                     const StubEntry& stub_entry,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ BranchLinkPatchable(label);
+  __ BranchLinkPatchable(stub_entry);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
 }
@@ -1172,10 +1176,10 @@
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          intptr_t token_pos,
-                                         const ExternalLabel* label,
+                                         const StubEntry& stub_entry,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  __ BranchLinkPatchable(label);
+  __ BranchLinkPatchable(stub_entry);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
   // Marks either the continuation point in unoptimized code or the
@@ -1224,8 +1228,8 @@
   // overflow; and though we do not reset the counters when we optimize or
   // deoptimize, there is a bound on the number of
   // optimization/deoptimization cycles we will attempt.
-  const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
-  counter.SetAt(0, Smi::Handle(Smi::New(0)));
+  const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
+  counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
   __ Comment("Edge counter");
   __ LoadUniqueObject(T0, counter);
   __ lw(T1, FieldAddress(T0, Array::element_offset(0)));
@@ -1235,13 +1239,13 @@
 
 
 void FlowGraphCompiler::EmitOptimizedInstanceCall(
-    ExternalLabel* target_label,
+    const StubEntry& stub_entry,
     const ICData& ic_data,
     intptr_t argument_count,
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
   // to inlining in optimized code, that function may not correspond to the
@@ -1253,25 +1257,25 @@
   __ LoadUniqueObject(S5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
 }
 
 
-void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
+void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
                                          const ICData& ic_data,
                                          intptr_t argument_count,
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   __ Comment("InstanceCall");
   __ LoadUniqueObject(S5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Comment("InstanceCall return");
@@ -1286,12 +1290,12 @@
     intptr_t token_pos,
     LocationSummary* locs) {
   MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
-  const String& name = String::Handle(ic_data.target_name());
+  const String& name = String::Handle(zone(), ic_data.target_name());
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ic_data.arguments_descriptor());
+      Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
-  const MegamorphicCache& cache =
-      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
+      zone(), table->Lookup(name, arguments_descriptor));
   __ Comment("MegamorphicInstanceCall");
   const Register receiverR = T0;
   const Register cacheR = T1;
@@ -1300,8 +1304,7 @@
   __ LoadObject(cacheR, cache);
 
   if (FLAG_use_megamorphic_stub) {
-    StubCode* stub_code = isolate()->stub_code();
-    __ BranchLink(&stub_code->MegamorphicLookupLabel());
+    __ BranchLink(*StubCode::MegamorphicLookup_entry());
   } else  {
     StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
   }
@@ -1329,14 +1332,12 @@
     intptr_t token_pos,
     LocationSummary* locs,
     const ICData& ic_data) {
-  StubCode* stub_code = isolate()->stub_code();
-  const uword label_address =
-      stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
-  ExternalLabel target_label(label_address);
+  const StubEntry* stub_entry =
+      StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(S5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &target_label,
+                   *stub_entry,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count);
@@ -1350,14 +1351,13 @@
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  StubCode* stub_code = isolate()->stub_code();
   __ Comment("StaticCall");
   __ LoadObject(S4, arguments_descriptor);
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &stub_code->CallStaticFunctionLabel(),
+                   *StubCode::CallStaticFunction_entry(),
                    RawPcDescriptors::kOther,
                    locs);
   AddStaticCallTarget(function);
@@ -1374,7 +1374,6 @@
   ASSERT(!needs_number_check ||
          (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()));
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
     __ addiu(SP, SP, Immediate(-2 * kWordSize));
     __ sw(reg, Address(SP, 1 * kWordSize));
@@ -1382,10 +1381,10 @@
     __ sw(TMP, Address(SP, 0 * kWordSize));
     if (is_optimizing()) {
       __ BranchLinkPatchable(
-          &stub_code->OptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
       __ BranchLinkPatchable(
-          &stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1411,16 +1410,15 @@
                                                        intptr_t token_pos) {
   __ Comment("EqualityRegRegCompare");
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ addiu(SP, SP, Immediate(-2 * kWordSize));
     __ sw(left, Address(SP, 1 * kWordSize));
     __ sw(right, Address(SP, 0 * kWordSize));
     if (is_optimizing()) {
       __ BranchLinkPatchable(
-          &stub_code->OptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
       __ BranchLinkPatchable(
-          &stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1550,9 +1548,8 @@
   ASSERT(is_optimizing());
   __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
-                                                 argument_names));
-  StubCode* stub_code = isolate()->stub_code();
+      Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
+                                                         argument_names));
 
   // Load receiver into T0.
   __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize);
@@ -1576,10 +1573,10 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
-    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
     AddStaticCallTarget(function);
     __ Drop(argument_count);
     if (kNumChecks > 1) {
@@ -1616,7 +1613,7 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
     const Function& function = *sorted[i].target;
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 3aa6f29..b28c25a 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -67,14 +67,13 @@
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
-  assembler()->set_allow_constant_pool(false);
+  ASSERT(!assembler()->constant_pool_allowed());
 }
 
 
 void FlowGraphCompiler::ExitIntrinsicMode() {
   ASSERT(intrinsic_mode());
   intrinsic_mode_ = false;
-  assembler()->set_allow_constant_pool(true);
 }
 
 
@@ -99,11 +98,13 @@
   // The real frame starts here.
   builder->MarkFrameStart();
 
+  Zone* zone = compiler->zone();
+
   // Current PP, FP, and PC.
-  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
-  builder->AddPcMarker(Function::Handle(), slot_ix++);
+  builder->AddPp(Function::Handle(zone, current->code().function()), slot_ix++);
+  builder->AddPcMarker(Function::Handle(zone), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(Function::Handle(current->code().function()),
+  builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
                             deopt_id(),
                             slot_ix++);
 
@@ -123,16 +124,18 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
-    builder->AddPcMarker(Function::Handle(previous->code().function()),
+    builder->AddPp(Function::Handle(zone, current->code().function()),
+                   slot_ix++);
+    builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                          slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(Function::Handle(current->code().function()),
-                              Isolate::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
+    builder->AddReturnAddress(
+        Function::Handle(zone, current->code().function()),
+        Isolate::ToDeoptAfter(current->deopt_id()),
+        slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
     // we must read them from the previous environment.
@@ -161,7 +164,7 @@
   // For the outermost environment, set caller PC, caller PP, and caller FP.
   builder->AddCallerPp(slot_ix++);
   // PC marker.
-  builder->AddPcMarker(Function::Handle(previous->code().function()),
+  builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
                        slot_ix++);
   builder->AddCallerFp(slot_ix++);
   builder->AddCallerPc(slot_ix++);
@@ -189,8 +192,7 @@
 
   ASSERT(deopt_env() != NULL);
 
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  __ Call(&stub_code->DeoptimizeLabel(), PP);
+  __ Call(*StubCode::Deoptimize_entry());
   set_pc_offset(assem->CodeSize());
   __ int3();
 #undef __
@@ -205,9 +207,9 @@
                                            Label* is_true,
                                            Label* is_false) {
   Label fall_through;
-  __ CompareObject(bool_register, Object::null_object(), PP);
+  __ CompareObject(bool_register, Object::null_object());
   __ j(EQUAL, &fall_through, Assembler::kNearJump);
-  __ CompareObject(bool_register, Bool::True(), PP);
+  __ CompareObject(bool_register, Bool::True());
   __ j(EQUAL, is_true);
   __ jmp(is_false);
   __ Bind(&fall_through);
@@ -223,22 +225,21 @@
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
   const SubtypeTestCache& type_test_cache =
-      SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
-  StubCode* stub_code = isolate()->stub_code();
-  __ LoadUniqueObject(temp_reg, type_test_cache, PP);
+      SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
+  __ LoadUniqueObject(temp_reg, type_test_cache);
   __ pushq(temp_reg);  // Subtype test cache.
   __ pushq(instance_reg);  // Instance.
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
-    __ PushObject(Object::null_object(), PP);
-    __ Call(&stub_code->Subtype1TestCacheLabel(), PP);
+    __ PushObject(Object::null_object());
+    __ Call(*StubCode::Subtype1TestCache_entry());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
-    __ PushObject(Object::null_object(), PP);
-    __ Call(&stub_code->Subtype2TestCacheLabel(), PP);
+    __ PushObject(Object::null_object());
+    __ Call(*StubCode::Subtype2TestCache_entry());
   } else if (test_kind == kTestTypeThreeArgs) {
     __ pushq(type_arguments_reg);
-    __ Call(&stub_code->Subtype3TestCacheLabel(), PP);
+    __ Call(*StubCode::Subtype3TestCache_entry());
   } else {
     UNREACHABLE();
   }
@@ -266,11 +267,11 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::ZoneHandle(type.type_class());
+  const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
   const Register kInstanceReg = RAX;
-  Error& malformed_error = Error::Handle();
-  const Type& int_type = Type::Handle(Type::IntType());
+  Error& malformed_error = Error::Handle(zone());
+  const Type& int_type = Type::Handle(zone(), Type::IntType());
   const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
   // Malformed type should have been handled at graph construction time.
   ASSERT(smi_is_ok || malformed_error.IsNull());
@@ -284,7 +285,7 @@
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
   const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(type.arguments());
+      TypeArguments::ZoneHandle(zone(), type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -304,13 +305,13 @@
     }
     // If one type argument only, check if type argument is Object or dynamic.
     if (type_arguments.Length() == 1) {
-      const AbstractType& tp_argument = AbstractType::ZoneHandle(
+      const AbstractType& tp_argument = AbstractType::ZoneHandle(zone(),
           type_arguments.TypeAt(0));
       ASSERT(!tp_argument.IsMalformed());
       if (tp_argument.IsType()) {
         ASSERT(tp_argument.HasResolvedTypeClass());
         // Check if type argument is dynamic or Object.
-        const Type& object_type = Type::Handle(Type::ObjectType());
+        const Type& object_type = Type::Handle(zone(), Type::ObjectType());
         if (object_type.IsSubtypeOf(tp_argument, NULL)) {
           // Instance class test only necessary.
           return GenerateSubtype1TestCacheLookup(
@@ -355,16 +356,16 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
-  const Class& type_class = Class::Handle(type.type_class());
+  const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
   const Register kInstanceReg = RAX;
   __ testq(kInstanceReg, Immediate(kSmiTagMask));
   // If instance is Smi, check directly.
-  const Class& smi_class = Class::Handle(Smi::Class());
-  if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
+  const Class& smi_class = Class::Handle(zone(), Smi::Class());
+  if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
                             type_class,
-                            TypeArguments::Handle(),
+                            TypeArguments::Handle(zone()),
                             NULL)) {
     __ j(ZERO, is_instance_lbl);
   } else {
@@ -386,14 +387,14 @@
   }
   if (type.IsFunctionType()) {
     // Check if instance is a closure.
-    __ LoadClassById(R13, kClassIdReg, PP);
+    __ LoadClassById(R13, kClassIdReg);
     __ movq(R13, FieldAddress(R13, Class::signature_function_offset()));
-    __ CompareObject(R13, Object::null_object(), PP);
+    __ CompareObject(R13, Object::null_object());
     __ j(NOT_EQUAL, is_instance_lbl);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
-  if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
+  if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
     GenerateNumberTypeCheck(
         kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
     return false;
@@ -421,12 +422,12 @@
     Label* is_not_instance_lbl) {
   __ Comment("Subtype1TestCacheLookup");
   const Register kInstanceReg = RAX;
-  __ LoadClass(R10, kInstanceReg, PP);
+  __ LoadClass(R10, kInstanceReg);
   // R10: instance class.
   // Check immediate superclass equality.
   __ movq(R13, FieldAddress(R10, Class::super_type_offset()));
   __ movq(R13, FieldAddress(R13, Type::type_class_offset()));
-  __ CompareObject(R13, type_class, PP);
+  __ CompareObject(R13, type_class);
   __ j(EQUAL, is_instance_lbl);
 
   const Register kTypeArgumentsReg = kNoRegister;
@@ -457,25 +458,25 @@
     __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
     // RDX: instantiator type arguments.
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
-    __ CompareObject(RDX, Object::null_object(), PP);
+    __ CompareObject(RDX, Object::null_object());
     __ j(EQUAL, is_instance_lbl);
     __ movq(RDI,
         FieldAddress(RDX, TypeArguments::type_at_offset(type_param.index())));
     // RDI: Concrete type of type.
     // Check if type argument is dynamic.
-    __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType()), PP);
+    __ CompareObject(RDI, Type::ZoneHandle(zone(), Type::DynamicType()));
     __ j(EQUAL,  is_instance_lbl);
-    const Type& object_type = Type::ZoneHandle(Type::ObjectType());
-    __ CompareObject(RDI, object_type, PP);
+    const Type& object_type = Type::ZoneHandle(zone(), Type::ObjectType());
+    __ CompareObject(RDI, object_type);
     __ j(EQUAL,  is_instance_lbl);
 
     // For Smi check quickly against int and num interfaces.
     Label not_smi;
     __ testq(RAX, Immediate(kSmiTagMask));  // Value is Smi?
     __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
-    __ CompareObject(RDI, Type::ZoneHandle(Type::IntType()), PP);
+    __ CompareObject(RDI, Type::ZoneHandle(zone(), Type::IntType()));
     __ j(EQUAL,  is_instance_lbl);
-    __ CompareObject(RDI, Type::ZoneHandle(Type::Number()), PP);
+    __ CompareObject(RDI, Type::ZoneHandle(zone(), Type::Number()));
     __ j(EQUAL,  is_instance_lbl);
     // Smi must be handled in runtime.
     Label fall_through;
@@ -488,7 +489,7 @@
     const Register kTypeArgumentsReg = RDX;
     const Register kTempReg = R10;
     const SubtypeTestCache& type_test_cache =
-        SubtypeTestCache::ZoneHandle(
+        SubtypeTestCache::ZoneHandle(zone(),
             GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
                                         kInstanceReg,
                                         kTypeArgumentsReg,
@@ -539,7 +540,7 @@
     return SubtypeTestCache::null();
   }
   if (type.IsInstantiated()) {
-    const Class& type_class = Class::ZoneHandle(type.type_class());
+    const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
     // A class equality check is only applicable with a dst type of a
     // non-parameterized class, non-signature class, or with a raw dst type of
     // a parameterized class.
@@ -603,12 +604,12 @@
     // We can only inline this null check if the type is instantiated at compile
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
-    __ CompareObject(RAX, Object::null_object(), PP);
+    __ CompareObject(RAX, Object::null_object());
     __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance);
   }
 
   // Generate inline instanceof test.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, type,
                                         &is_instance, &is_not_instance);
 
@@ -618,12 +619,12 @@
     // Generate runtime call.
     __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
     __ movq(RCX, Address(RSP, kWordSize));  // Get instantiator.
-    __ PushObject(Object::null_object(), PP);  // Make room for the result.
+    __ PushObject(Object::null_object());  // Make room for the result.
     __ pushq(RAX);  // Push the instance.
-    __ PushObject(type, PP);  // Push the type.
+    __ PushObject(type);  // Push the type.
     __ pushq(RCX);  // TODO(srdjan): Pass instantiator instead of null.
     __ pushq(RDX);  // Instantiator type arguments.
-    __ LoadUniqueObject(RAX, test_cache, PP);
+    __ LoadUniqueObject(RAX, test_cache);
     __ pushq(RAX);
     GenerateRuntimeCall(token_pos,
                         deopt_id,
@@ -635,21 +636,21 @@
     __ Drop(5);
     if (negate_result) {
       __ popq(RDX);
-      __ LoadObject(RAX, Bool::True(), PP);
+      __ LoadObject(RAX, Bool::True());
       __ cmpq(RDX, RAX);
       __ j(NOT_EQUAL, &done, Assembler::kNearJump);
-      __ LoadObject(RAX, Bool::False(), PP);
+      __ LoadObject(RAX, Bool::False());
     } else {
       __ popq(RAX);
     }
     __ jmp(&done, Assembler::kNearJump);
   }
   __ Bind(&is_not_instance);
-  __ LoadObject(RAX, Bool::Get(negate_result), PP);
+  __ LoadObject(RAX, Bool::Get(negate_result));
   __ jmp(&done, Assembler::kNearJump);
 
   __ Bind(&is_instance);
-  __ LoadObject(RAX, Bool::Get(!negate_result), PP);
+  __ LoadObject(RAX, Bool::Get(!negate_result));
   __ Bind(&done);
   __ popq(RDX);  // Remove pushed instantiator type arguments.
   __ popq(RCX);  // Remove pushed instantiator.
@@ -683,15 +684,15 @@
   __ pushq(RDX);  // Store instantiator type arguments.
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
-  __ CompareObject(RAX, Object::null_object(), PP);
+  __ CompareObject(RAX, Object::null_object());
   __ j(EQUAL, &is_assignable);
 
   // Generate throw new TypeError() if the type is malformed or malbounded.
   if (dst_type.IsMalformedOrMalbounded()) {
-    __ PushObject(Object::null_object(), PP);  // Make room for the result.
+    __ PushObject(Object::null_object());  // Make room for the result.
     __ pushq(RAX);  // Push the source object.
-    __ PushObject(dst_name, PP);  // Push the name of the destination.
-    __ PushObject(dst_type, PP);  // Push the type of the destination.
+    __ PushObject(dst_name);  // Push the name of the destination.
+    __ PushObject(dst_type);  // Push the type of the destination.
     GenerateRuntimeCall(token_pos,
                         deopt_id,
                         kBadTypeErrorRuntimeEntry,
@@ -707,20 +708,20 @@
   }
 
   // Generate inline type check, linking to runtime call if not assignable.
-  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache = GenerateInlineInstanceof(token_pos, dst_type,
                                         &is_assignable, &runtime_call);
 
   __ Bind(&runtime_call);
   __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
   __ movq(RCX, Address(RSP, kWordSize));  // Get instantiator.
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
+  __ PushObject(Object::null_object());  // Make room for the result.
   __ pushq(RAX);  // Push the source object.
-  __ PushObject(dst_type, PP);  // Push the type of the destination.
+  __ PushObject(dst_type);  // Push the type of the destination.
   __ pushq(RCX);  // Instantiator.
   __ pushq(RDX);  // Instantiator type arguments.
-  __ PushObject(dst_name, PP);  // Push the name of the destination.
-  __ LoadUniqueObject(RAX, test_cache, PP);
+  __ PushObject(dst_name);  // Push the name of the destination.
+  __ LoadUniqueObject(RAX, test_cache);
   __ pushq(RAX);
   GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
@@ -772,10 +773,10 @@
           FieldAddress(R10, ArgumentsDescriptor::positional_count_offset()));
   // Check that min_num_pos_args <= num_pos_args.
   Label wrong_num_arguments;
-  __ CompareImmediate(RCX, Immediate(Smi::RawValue(min_num_pos_args)), PP);
+  __ CompareImmediate(RCX, Immediate(Smi::RawValue(min_num_pos_args)));
   __ j(LESS, &wrong_num_arguments);
   // Check that num_pos_args <= max_num_pos_args.
-  __ CompareImmediate(RCX, Immediate(Smi::RawValue(max_num_pos_args)), PP);
+  __ CompareImmediate(RCX, Immediate(Smi::RawValue(max_num_pos_args)));
   __ j(GREATER, &wrong_num_arguments);
 
   // Copy positional arguments.
@@ -857,7 +858,7 @@
       // Load RAX with the name of the argument.
       __ movq(RAX, Address(RDI, ArgumentsDescriptor::name_offset()));
       ASSERT(opt_param[i]->name().IsSymbol());
-      __ CompareObject(RAX, opt_param[i]->name(), PP);
+      __ CompareObject(RAX, opt_param[i]->name());
       __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
       // Load RAX with passed-in argument at provided arg_pos, i.e. at
       // fp[kParamEndSlotFromFp + num_args - arg_pos].
@@ -865,17 +866,17 @@
       // RAX is arg_pos as Smi.
       // Point to next named entry.
       __ AddImmediate(
-          RDI, Immediate(ArgumentsDescriptor::named_entry_size()), PP);
+          RDI, Immediate(ArgumentsDescriptor::named_entry_size()));
       __ negq(RAX);
       Address argument_addr(RBX, RAX, TIMES_4, 0);  // RAX is a negative Smi.
       __ movq(RAX, argument_addr);
       __ jmp(&assign_optional_parameter, Assembler::kNearJump);
       __ Bind(&load_default_value);
       // Load RAX with default argument.
-      const Object& value = Object::ZoneHandle(
+      const Object& value = Object::ZoneHandle(zone(),
           parsed_function().default_parameter_values().At(
               param_pos - num_fixed_params));
-      __ LoadObject(RAX, value, PP);
+      __ LoadObject(RAX, value);
       __ Bind(&assign_optional_parameter);
       // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos].
       // We do not use the final allocation index of the variable here, i.e.
@@ -890,7 +891,7 @@
     if (check_correct_named_args) {
       // Check that RDI now points to the null terminator in the arguments
       // descriptor.
-      __ LoadObject(TMP, Object::null_object(), PP);
+      __ LoadObject(TMP, Object::null_object());
       __ cmpq(Address(RDI, 0), TMP);
       __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
     }
@@ -905,12 +906,12 @@
       // arguments have been passed, where k is param_pos, the position of this
       // optional parameter in the formal parameter list.
       const int param_pos = num_fixed_params + i;
-      __ CompareImmediate(RCX, Immediate(param_pos), PP);
+      __ CompareImmediate(RCX, Immediate(param_pos));
       __ j(GREATER, &next_parameter, Assembler::kNearJump);
       // Load RAX with default argument.
-      const Object& value = Object::ZoneHandle(
+      const Object& value = Object::ZoneHandle(zone(),
           parsed_function().default_parameter_values().At(i));
-      __ LoadObject(RAX, value, PP);
+      __ LoadObject(RAX, value);
       // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos].
       // We do not use the final allocation index of the variable here, i.e.
       // scope->VariableAt(i)->index(), because captured variables still need
@@ -931,8 +932,11 @@
 
   __ Bind(&wrong_num_arguments);
   if (function.IsClosureFunction()) {
+    ASSERT(assembler()->constant_pool_allowed());
     __ LeaveDartFrame();  // The arguments are still on the stack.
-    __ jmp(&isolate()->stub_code()->CallClosureNoSuchMethodLabel());
+    ASSERT(!assembler()->constant_pool_allowed());
+    __ jmp(*StubCode::CallClosureNoSuchMethod_entry());
+    __ set_constant_pool_allowed(true);
     // The noSuchMethod call may return to the caller, but not here.
   } else if (check_correct_named_args) {
     __ Stop("Wrong arguments");
@@ -948,7 +952,7 @@
   // R10 : arguments descriptor array.
   __ movq(RCX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
   __ SmiUntag(RCX);
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   Label null_args_loop, null_args_loop_condition;
   __ jmp(&null_args_loop_condition, Assembler::kNearJump);
   const Address original_argument_addr(
@@ -981,7 +985,7 @@
   __ movq(RAX, Address(RSP, 2 * kWordSize));  // Receiver.
   __ movq(RBX, Address(RSP, 1 * kWordSize));  // Value.
   __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX);
-  __ LoadObject(RAX, Object::null_object(), PP);
+  __ LoadObject(RAX, Object::null_object());
   __ ret();
 }
 
@@ -1018,7 +1022,7 @@
         (!is_optimizing() || may_reoptimize())) {
       const Register function_reg = RDI;
       // Load function object using the callee's pool pointer.
-      __ LoadObject(function_reg, function, new_pp);
+      __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
 
       // Patch point is after the eventually inlined function object.
       entry_patch_pc_offset_ = assembler()->CodeSize();
@@ -1033,7 +1037,7 @@
           Immediate(GetOptimizationThreshold()));
       ASSERT(function_reg == RDI);
       __ J(GREATER_EQUAL,
-           &isolate()->stub_code()->OptimizeFunctionLabel(),
+           *StubCode::OptimizeFunction_entry(),
            new_pp);
     } else {
       entry_patch_pc_offset_ = assembler()->CodeSize();
@@ -1051,13 +1055,13 @@
   TryIntrinsify();
 
   EmitFrameEntry();
+  ASSERT(assembler()->constant_pool_allowed());
 
   const Function& function = parsed_function().function();
 
   const int num_fixed_params = function.num_fixed_parameters();
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
-  StubCode* stub_code = isolate()->stub_code();
 
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
@@ -1076,7 +1080,7 @@
       // Check that exactly num_fixed arguments are passed in.
       Label correct_num_arguments, wrong_num_arguments;
       __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-      __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params)), PP);
+      __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params)));
       __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump);
       __ cmpq(RAX,
               FieldAddress(R10,
@@ -1085,8 +1089,11 @@
 
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction()) {
+        ASSERT(assembler()->constant_pool_allowed());
         __ LeaveDartFrame();  // The arguments are still on the stack.
-        __ jmp(&stub_code->CallClosureNoSuchMethodLabel());
+        ASSERT(!assembler()->constant_pool_allowed());
+        __ jmp(*StubCode::CallClosureNoSuchMethod_entry());
+        __ set_constant_pool_allowed(true);
         // The noSuchMethod call may return to the caller, but not here.
       } else {
         __ Stop("Wrong number of arguments");
@@ -1122,7 +1129,7 @@
     const intptr_t context_index =
         parsed_function().current_context_var()->index();
     if (num_locals > 1) {
-      __ LoadObject(RAX, Object::null_object(), PP);
+      __ LoadObject(RAX, Object::null_object());
     }
     for (intptr_t i = 0; i < num_locals; ++i) {
       // Subtract index i (locals lie at lower addresses than RBP).
@@ -1133,7 +1140,7 @@
           const Context& empty_context = Context::ZoneHandle(
               zone(), isolate()->object_store()->empty_context());
           __ StoreObject(
-              Address(RBP, (slot_base - i) * kWordSize), empty_context, PP);
+              Address(RBP, (slot_base - i) * kWordSize), empty_context);
         }
       } else {
         ASSERT(num_locals > 1);
@@ -1146,26 +1153,27 @@
   VisitBlocks();
 
   __ int3();
+  ASSERT(assembler()->constant_pool_allowed());
   GenerateDeferredCode();
   // Emit function patching code. This will be swapped with the first 13 bytes
   // at entry point.
   patch_code_pc_offset_ = assembler()->CodeSize();
   // This is patched up to a point in FrameEntry where the PP for the
   // current function is in R13 instead of PP.
-  __ JmpPatchable(&stub_code->FixCallersTargetLabel(), R13);
+  __ JmpPatchable(*StubCode::FixCallersTarget_entry(), R13);
 
   if (is_optimizing()) {
     lazy_deopt_pc_offset_ = assembler()->CodeSize();
-    __ Jmp(&stub_code->DeoptimizeLazyLabel(), PP);
+    __ Jmp(*StubCode::DeoptimizeLazy_entry(), PP);
   }
 }
 
 
 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
-                                     const ExternalLabel* label,
+                                     const StubEntry& stub_entry,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ Call(label, PP);
+  __ Call(stub_entry);
   AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
   RecordSafepoint(locs);
 }
@@ -1173,10 +1181,10 @@
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          intptr_t token_pos,
-                                         const ExternalLabel* label,
+                                         const StubEntry& stub_entry,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  __ CallPatchable(label);
+  __ CallPatchable(stub_entry);
   AddCurrentDescriptor(kind, deopt_id, token_pos);
   RecordSafepoint(locs);
   // Marks either the continuation point in unoptimized code or the
@@ -1221,14 +1229,12 @@
     intptr_t token_pos,
     LocationSummary* locs,
     const ICData& ic_data) {
-  StubCode* stub_code = isolate()->stub_code();
-  const uword label_address =
-      stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
-  ExternalLabel target_label(label_address);
-  __ LoadObject(RBX, ic_data, PP);
+  const StubEntry* stub_entry =
+      StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
+  __ LoadObject(RBX, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &target_label,
+                   *stub_entry,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count, RCX);
@@ -1241,10 +1247,11 @@
   // overflow; and though we do not reset the counters when we optimize or
   // deoptimize, there is a bound on the number of
   // optimization/deoptimization cycles we will attempt.
-  const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
-  counter.SetAt(0, Smi::Handle(Smi::New(0)));
+  ASSERT(assembler_->constant_pool_allowed());
+  const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
+  counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
   __ Comment("Edge counter");
-  __ LoadUniqueObject(RAX, counter, PP);
+  __ LoadUniqueObject(RAX, counter);
   intptr_t increment_start = assembler_->CodeSize();
   __ IncrementSmiField(FieldAddress(RAX, Array::element_offset(0)), 1);
   int32_t size = assembler_->CodeSize() - increment_start;
@@ -1264,41 +1271,41 @@
 
 
 void FlowGraphCompiler::EmitOptimizedInstanceCall(
-    ExternalLabel* target_label,
+    const StubEntry& stub_entry,
     const ICData& ic_data,
     intptr_t argument_count,
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
   // to inlining in optimized code, that function may not correspond to the
   // top-level function (parsed_function().function()) which could be
   // reoptimized and which counter needs to be incremented.
   // Pass the function explicitly, it is used in IC stub.
-  __ LoadObject(RDI, parsed_function().function(), PP);
-  __ LoadUniqueObject(RBX, ic_data, PP);
+  __ LoadObject(RDI, parsed_function().function());
+  __ LoadUniqueObject(RBX, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count, RCX);
 }
 
 
-void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
+void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
                                          const ICData& ic_data,
                                          intptr_t argument_count,
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
-  __ LoadUniqueObject(RBX, ic_data, PP);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  __ LoadUniqueObject(RBX, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
-                   target_label,
+                   stub_entry,
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count, RCX);
@@ -1312,26 +1319,25 @@
     intptr_t token_pos,
     LocationSummary* locs) {
   MegamorphicCacheTable* table = isolate()->megamorphic_cache_table();
-  const String& name = String::Handle(ic_data.target_name());
+  const String& name = String::Handle(zone(), ic_data.target_name());
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ic_data.arguments_descriptor());
+      Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
-  const MegamorphicCache& cache =
-      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
+      zone(), table->Lookup(name, arguments_descriptor));
   const Register receiverR = RDI;
   const Register cacheR = RBX;
   const Register targetR = RCX;
   __ movq(receiverR, Address(RSP, (argument_count - 1) * kWordSize));
-  __ LoadObject(cacheR, cache, PP);
+  __ LoadObject(cacheR, cache);
 
   if (FLAG_use_megamorphic_stub) {
-    StubCode* stub_code = isolate()->stub_code();
-    __ call(&stub_code->MegamorphicLookupLabel());
+    __ Call(*StubCode::MegamorphicLookup_entry());
   } else  {
     StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
   }
-  __ LoadObject(RBX, ic_data, PP);
-  __ LoadObject(R10, arguments_descriptor, PP);
+  __ LoadObject(RBX, ic_data);
+  __ LoadObject(R10, arguments_descriptor);
   __ call(targetR);
   AddCurrentDescriptor(RawPcDescriptors::kOther,
       Isolate::kNoDeoptId, token_pos);
@@ -1355,13 +1361,12 @@
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  StubCode* stub_code = isolate()->stub_code();
-  __ LoadObject(R10, arguments_descriptor, PP);
+  __ LoadObject(R10, arguments_descriptor);
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateDartCall(deopt_id,
                    token_pos,
-                   &stub_code->CallStaticFunctionLabel(),
+                   *StubCode::CallStaticFunction_entry(),
                    RawPcDescriptors::kOther,
                    locs);
   AddStaticCallTarget(function);
@@ -1384,13 +1389,12 @@
   }
 
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ pushq(reg);
-    __ PushObject(obj, PP);
+    __ PushObject(obj);
     if (is_optimizing()) {
-      __ CallPatchable(&stub_code->OptimizedIdenticalWithNumberCheckLabel());
+      __ CallPatchable(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
-      __ CallPatchable(&stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+      __ CallPatchable(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1401,7 +1405,7 @@
     __ popq(reg);  // Discard constant.
     __ popq(reg);  // Restore 'reg'.
   } else {
-    __ CompareObject(reg, obj, PP);
+    __ CompareObject(reg, obj);
   }
   return EQUAL;
 }
@@ -1412,13 +1416,12 @@
                                                        bool needs_number_check,
                                                        intptr_t token_pos) {
   if (needs_number_check) {
-    StubCode* stub_code = isolate()->stub_code();
     __ pushq(left);
     __ pushq(right);
     if (is_optimizing()) {
-      __ CallPatchable(&stub_code->OptimizedIdenticalWithNumberCheckLabel());
+      __ CallPatchable(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
     } else {
-      __ CallPatchable(&stub_code->UnoptimizedIdenticalWithNumberCheckLabel());
+      __ CallPatchable(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
     }
     if (token_pos != Scanner::kNoSourcePos) {
       AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
@@ -1482,13 +1485,12 @@
 
   __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
-      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
-                                                 argument_names));
-  StubCode* stub_code = isolate()->stub_code();
+      Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
+                                                         argument_names));
   // Load receiver into RAX.
   __ movq(RAX,
       Address(RSP, (argument_count - 1) * kWordSize));
-  __ LoadObject(R10, arguments_descriptor, PP);
+  __ LoadObject(R10, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
   const intptr_t kNumChecks = ic_data.NumberOfChecks();
@@ -1508,10 +1510,10 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
-    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
     AddStaticCallTarget(function);
     __ Drop(argument_count, RCX);
     if (kNumChecks > 1) {
@@ -1549,7 +1551,7 @@
     // that we can record the outgoing edges to other code.
     GenerateDartCall(deopt_id,
                      token_index,
-                     &stub_code->CallStaticFunctionLabel(),
+                     *StubCode::CallStaticFunction_entry(),
                      RawPcDescriptors::kOther,
                      locs);
     const Function& function = *sorted[i].target;
@@ -1626,13 +1628,13 @@
           (source.constant_instruction()->representation() == kUnboxedInt32)) {
         __ movl(destination.reg(), Immediate(Smi::Cast(constant).Value()));
       } else {
-        __ LoadObject(destination.reg(), constant, PP);
+        __ LoadObject(destination.reg(), constant);
       }
     } else if (destination.IsFpuRegister()) {
       if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
         __ xorps(destination.fpu_reg(), destination.fpu_reg());
       } else {
-        __ LoadObject(TMP, constant, PP);
+        __ LoadObject(TMP, constant);
         __ movsd(destination.fpu_reg(),
             FieldAddress(TMP, Double::value_offset()));
       }
@@ -1640,7 +1642,7 @@
       if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
         __ xorps(XMM0, XMM0);
       } else {
-        __ LoadObject(TMP, constant, PP);
+        __ LoadObject(TMP, constant);
         __ movsd(XMM0, FieldAddress(TMP, Double::value_offset()));
       }
       __ movsd(destination.ToStackSlotAddress(), XMM0);
@@ -1745,7 +1747,7 @@
 
 
 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
-  __ StoreObject(dst, obj, PP);
+  __ StoreObject(dst, obj);
 }
 
 
@@ -1785,14 +1787,14 @@
 
 
 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
-  __ AddImmediate(RSP, Immediate(-kFpuRegisterSize), PP);
+  __ AddImmediate(RSP, Immediate(-kFpuRegisterSize));
   __ movups(Address(RSP, 0), reg);
 }
 
 
 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
   __ movups(reg, Address(RSP, 0));
-  __ AddImmediate(RSP, Immediate(kFpuRegisterSize), PP);
+  __ AddImmediate(RSP, Immediate(kFpuRegisterSize));
 }
 
 
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index f22c50f..6fcd874 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -1038,10 +1038,9 @@
   }
 
   const AbstractType* abstract_type = NULL;
-  if (Isolate::Current()->flags().type_checks()) {
-    ASSERT(!type().HasResolvedTypeClass() ||
-           !Field::IsExternalizableCid(Class::Handle(
-                type().type_class()).id()));
+  if (Isolate::Current()->flags().type_checks() &&
+      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 d7e05f1..12ad8c4 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -317,10 +317,9 @@
         // If the code wasn't strongly visited through other references
         // after skipping the function's code pointer, then we disconnect the
         // code from the function.
-        StubCode* stub_code = isolate()->stub_code();
         func->StorePointer(
             &(func->ptr()->instructions_),
-            stub_code->LazyCompile_entry()->code()->ptr()->instructions_);
+            StubCode::LazyCompile_entry()->code()->ptr()->instructions_);
         if (FLAG_log_code_drop) {
           // NOTE: This code runs while GC is in progress and runs within
           // a NoHandleScope block. Hence it is not okay to use a regular Zone
diff --git a/runtime/vm/gc_marker.h b/runtime/vm/gc_marker.h
index 95666b3..978cf3d 100644
--- a/runtime/vm/gc_marker.h
+++ b/runtime/vm/gc_marker.h
@@ -48,7 +48,7 @@
 
 
   Heap* heap_;
-  intptr_t marked_bytes_;
+  uintptr_t marked_bytes_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(GCMarker);
 };
diff --git a/runtime/vm/handles.cc b/runtime/vm/handles.cc
index f636fdd..c053542 100644
--- a/runtime/vm/handles.cc
+++ b/runtime/vm/handles.cc
@@ -76,17 +76,17 @@
 
 
 int VMHandles::ScopedHandleCount() {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate->current_zone() != NULL);
-  VMHandles* handles = isolate->current_zone()->handles();
+  Thread* thread = Thread::Current();
+  ASSERT(thread->zone() != NULL);
+  VMHandles* handles = thread->zone()->handles();
   return handles->CountScopedHandles();
 }
 
 
 int VMHandles::ZoneHandleCount() {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate->current_zone() != NULL);
-  VMHandles* handles = isolate->current_zone()->handles();
+  Thread* thread = Thread::Current();
+  ASSERT(thread->zone() != NULL);
+  VMHandles* handles = thread->zone()->handles();
   return handles->CountZoneHandles();
 }
 
diff --git a/runtime/vm/handles_impl.h b/runtime/vm/handles_impl.h
index 370b34e..ad005bb 100644
--- a/runtime/vm/handles_impl.h
+++ b/runtime/vm/handles_impl.h
@@ -123,18 +123,18 @@
 }
 
 
-// Figure out the current zone using the current Isolate and
+// Figure out the current zone using the current Thread and
 // check if the specified handle has been allocated in this zone.
 template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
 bool Handles<kHandleSizeInWords,
              kHandlesPerChunk,
              kOffsetOfRawPtr>::IsZoneHandle(uword handle) {
-  // TODO(5411412): Accessing the current isolate is a performance problem,
+  // TODO(5411412): Accessing the current thread is a performance problem,
   // consider passing it down as a parameter.
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-  ASSERT(isolate->current_zone() != NULL);
-  Handles* handles = isolate->current_zone()->handles();
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
+  ASSERT(thread->zone() != NULL);
+  Handles* handles = thread->zone()->handles();
   ASSERT(handles != NULL);
   return handles->IsValidZoneHandle(handle);
 }
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 06da6f1..6897af8 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -74,7 +74,9 @@
 
 
 uword Heap::AllocateNew(intptr_t size) {
-  ASSERT(isolate()->no_safepoint_scope_depth() == 0);
+  ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
+  // Currently, only the Dart thread may allocate in new space.
+  isolate()->AssertCurrentThreadIsMutator();
   uword addr = new_space_.TryAllocate(size);
   if (addr == 0) {
     CollectGarbage(kNew);
@@ -88,7 +90,13 @@
 
 
 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) {
-  ASSERT(isolate()->no_safepoint_scope_depth() == 0);
+  ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
+#if defined(DEBUG)
+  // Currently, allocation from non-Dart threads must not trigger GC.
+  if (GrowthControlState()) {
+    isolate()->AssertCurrentThreadIsMutator();
+  }
+#endif
   uword addr = old_space_.TryAllocate(size, type);
   if (addr != 0) {
     return addr;
@@ -149,7 +157,7 @@
 
 
 uword Heap::AllocatePretenured(intptr_t size) {
-  ASSERT(isolate()->no_safepoint_scope_depth() == 0);
+  ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
   uword addr = old_space_.TryAllocateDataBump(size, PageSpace::kControlGrowth);
   if (addr != 0) return addr;
   return AllocateOld(size, HeapPage::kData);
@@ -157,7 +165,7 @@
 
 
 void Heap::AllocateExternal(intptr_t size, Space space) {
-  ASSERT(isolate()->no_safepoint_scope_depth() == 0);
+  ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
   if (space == kNew) {
     new_space_.AllocateExternal(size);
     if (new_space_.ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) {
@@ -216,7 +224,7 @@
 
 
 HeapIterationScope::HeapIterationScope()
-    : StackResource(Thread::Current()->isolate()),
+    : StackResource(Thread::Current()),
       old_space_(isolate()->heap()->old_space()) {
   // It's not yet safe to iterate over a paged space while it's concurrently
   // sweeping, so wait for any such task to complete first.
@@ -444,26 +452,6 @@
 }
 
 
-uword Heap::TopAddress(Heap::Space space) {
-  if (space == kNew) {
-    return reinterpret_cast<uword>(new_space_.TopAddress());
-  } else {
-    ASSERT(space == kPretenured);
-    return reinterpret_cast<uword>(old_space_.TopAddress());
-  }
-}
-
-
-uword Heap::EndAddress(Heap::Space space) {
-  if (space == kNew) {
-    return reinterpret_cast<uword>(new_space_.EndAddress());
-  } else {
-    ASSERT(space == kPretenured);
-    return reinterpret_cast<uword>(old_space_.EndAddress());
-  }
-}
-
-
 Heap::Space Heap::SpaceForAllocation(intptr_t cid) {
   return FLAG_pretenure_all ? kPretenured : kNew;
 }
@@ -759,13 +747,13 @@
 
 
 #if defined(DEBUG)
-NoSafepointScope::NoSafepointScope() : StackResource(Isolate::Current()) {
-  isolate()->IncrementNoSafepointScopeDepth();
+NoSafepointScope::NoSafepointScope() : StackResource(Thread::Current()) {
+  thread()->IncrementNoSafepointScopeDepth();
 }
 
 
 NoSafepointScope::~NoSafepointScope() {
-  isolate()->DecrementNoSafepointScopeDepth();
+  thread()->DecrementNoSafepointScopeDepth();
 }
 #endif  // defined(DEBUG)
 
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 076b283..05e0ef0 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -140,9 +140,7 @@
   }
 
   // Accessors for inlined allocation in generated code.
-  uword TopAddress(Space space);
   static intptr_t TopOffset(Space space);
-  uword EndAddress(Space space);
   static intptr_t EndOffset(Space space);
   static Space SpaceForAllocation(intptr_t class_id);
 
diff --git a/runtime/vm/heap_test.cc b/runtime/vm/heap_test.cc
index 11f2d4f..47cfafe 100644
--- a/runtime/vm/heap_test.cc
+++ b/runtime/vm/heap_test.cc
@@ -213,7 +213,9 @@
  public:
   FindOnly(Isolate* isolate, RawObject* target)
       : FindObjectVisitor(isolate), target_(target) {
-    ASSERT(isolate->no_safepoint_scope_depth() != 0);
+#if defined(DEBUG)
+    EXPECT_GT(Thread::Current()->no_safepoint_scope_depth(), 0);
+#endif
   }
   virtual ~FindOnly() { }
 
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 6a5ce90..9c0a808 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -15,6 +15,8 @@
 DEFINE_FLAG(charp, print_flow_graph_filter, NULL,
     "Print only IR of functions with matching names");
 
+DECLARE_FLAG(bool, trace_inlining_intervals);
+
 void BufferFormatter::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -136,6 +138,9 @@
   }
   if (!instr->IsBlockEntry()) ISL_Print("    ");
   ISL_Print("%s", str);
+  if (FLAG_trace_inlining_intervals) {
+    ISL_Print(" iid: %" Pd "", instr->inlining_id());
+  }
 }
 
 
diff --git a/runtime/vm/instructions_arm64_test.cc b/runtime/vm/instructions_arm64_test.cc
index 263c6a4..924d495 100644
--- a/runtime/vm/instructions_arm64_test.cc
+++ b/runtime/vm/instructions_arm64_test.cc
@@ -16,8 +16,9 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchLinkPatchable(&stub_code->InvokeDartCodeLabel());
+  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
+  __ set_constant_pool_allowed(true);
+  __ BranchLinkPatchable(*StubCode::InvokeDartCode_entry());
   __ ret();
 }
 
@@ -28,18 +29,14 @@
   // before the end of the code buffer.
   CallPattern call(test->entry() + test->code().Size() - Instr::kInstrSize,
                    test->code());
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             call.TargetAddress());
 }
 
 
 ASSEMBLER_TEST_GENERATE(Jump, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->InvokeDartCodeLabel());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchPatchable(&array_label);
+  __ BranchPatchable(*StubCode::InvokeDartCode_entry());
+  __ BranchPatchable(*StubCode::AllocateArray_entry());
 }
 
 
@@ -50,21 +47,21 @@
       VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
                              instrs.size(),
                              VirtualMemory::kReadWrite);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump1.TargetAddress());
   JumpPattern jump2(test->entry() + jump1.pattern_length_in_bytes(),
                     test->code());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
+  const Code& array_stub =
+      Code::Handle(StubCode::AllocateArray_entry()->code());
   EXPECT_EQ(array_stub.EntryPoint(), jump2.TargetAddress());
   uword target1 = jump1.TargetAddress();
   uword target2 = jump2.TargetAddress();
   jump1.SetTargetAddress(target2);
   jump2.SetTargetAddress(target1);
   EXPECT_EQ(array_stub.EntryPoint(), jump1.TargetAddress());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump2.TargetAddress());
 }
 
diff --git a/runtime/vm/instructions_arm_test.cc b/runtime/vm/instructions_arm_test.cc
index dcee850..540fd5f 100644
--- a/runtime/vm/instructions_arm_test.cc
+++ b/runtime/vm/instructions_arm_test.cc
@@ -16,8 +16,9 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchLinkPatchable(&stub_code->InvokeDartCodeLabel());
+  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
+  __ set_constant_pool_allowed(true);
+  __ BranchLinkPatchable(*StubCode::InvokeDartCode_entry());
   __ Ret();
 }
 
@@ -28,18 +29,14 @@
   // before the end of the code buffer.
   CallPattern call(test->entry() + test->code().Size() - Instr::kInstrSize,
                    test->code());
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             call.TargetAddress());
 }
 
 
 ASSEMBLER_TEST_GENERATE(Jump, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->InvokeDartCodeLabel());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchPatchable(&array_label);
+  __ BranchPatchable(*StubCode::InvokeDartCode_entry());
+  __ BranchPatchable(*StubCode::AllocateArray_entry());
 }
 
 
@@ -50,21 +47,21 @@
       VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
                              instrs.size(),
                              VirtualMemory::kReadWrite);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump1.TargetAddress());
   JumpPattern jump2(test->entry() + jump1.pattern_length_in_bytes(),
                     test->code());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
+  const Code& array_stub =
+      Code::Handle(StubCode::AllocateArray_entry()->code());
   EXPECT_EQ(array_stub.EntryPoint(), jump2.TargetAddress());
   uword target1 = jump1.TargetAddress();
   uword target2 = jump2.TargetAddress();
   jump1.SetTargetAddress(target2);
   jump2.SetTargetAddress(target1);
   EXPECT_EQ(array_stub.EntryPoint(), jump1.TargetAddress());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump2.TargetAddress());
 }
 
@@ -72,12 +69,9 @@
 #if defined(USING_SIMULATOR)
 ASSEMBLER_TEST_GENERATE(JumpARMv6, assembler) {
   // ARMv7 is the default.
-  StubCode* stub_code = Isolate::Current()->stub_code();
   HostCPUFeatures::set_arm_version(ARMv6);
-  __ BranchPatchable(&stub_code->InvokeDartCodeLabel());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchPatchable(&array_label);
+  __ BranchPatchable(*StubCode::InvokeDartCode_entry());
+  __ BranchPatchable(*StubCode::AllocateArray_entry());
   HostCPUFeatures::set_arm_version(ARMv7);
 }
 
@@ -90,21 +84,21 @@
       VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
                              instrs.size(),
                              VirtualMemory::kReadWrite);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump1.TargetAddress());
   JumpPattern jump2(test->entry() + jump1.pattern_length_in_bytes(),
                     test->code());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
+  const Code& array_stub =
+      Code::Handle(StubCode::AllocateArray_entry()->code());
   EXPECT_EQ(array_stub.EntryPoint(), jump2.TargetAddress());
   uword target1 = jump1.TargetAddress();
   uword target2 = jump2.TargetAddress();
   jump1.SetTargetAddress(target2);
   jump2.SetTargetAddress(target1);
   EXPECT_EQ(array_stub.EntryPoint(), jump1.TargetAddress());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump2.TargetAddress());
   HostCPUFeatures::set_arm_version(ARMv7);
 }
diff --git a/runtime/vm/instructions_ia32_test.cc b/runtime/vm/instructions_ia32_test.cc
index 27c5277..cace229 100644
--- a/runtime/vm/instructions_ia32_test.cc
+++ b/runtime/vm/instructions_ia32_test.cc
@@ -17,26 +17,22 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ call(&stub_code->InvokeDartCodeLabel());
+  __ Call(*StubCode::InvokeDartCode_entry());
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(Call, test) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
   CallPattern call(test->entry());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->EntryPoint(),
             call.TargetAddress());
 }
 
 
 ASSEMBLER_TEST_GENERATE(Jump, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ jmp(&stub_code->InvokeDartCodeLabel());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ jmp(&array_label);
+  __ Jmp(*StubCode::InvokeDartCode_entry());
+  const ExternalLabel label(StubCode::AllocateArray_entry()->EntryPoint());
+  __ jmp(&label);
   __ ret();
 }
 
@@ -44,18 +40,18 @@
 ASSEMBLER_TEST_RUN(Jump, test) {
   const Code& code = test->code();
   const Instructions& instrs = Instructions::Handle(code.instructions());
-  StubCode* stub_code = Isolate::Current()->stub_code();
   bool status =
       VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
                              instrs.size(),
                              VirtualMemory::kReadWrite);
   EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->EntryPoint(),
             jump1.TargetAddress());
   JumpPattern jump2(test->entry() + jump1.pattern_length_in_bytes(),
                     test->code());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
+  const Code& array_stub =
+      Code::Handle(StubCode::AllocateArray_entry()->code());
   EXPECT_EQ(array_stub.EntryPoint(),
             jump2.TargetAddress());
   uword target1 = jump1.TargetAddress();
@@ -64,7 +60,7 @@
   jump2.SetTargetAddress(target1);
   EXPECT_EQ(array_stub.EntryPoint(),
             jump1.TargetAddress());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->EntryPoint(),
             jump2.TargetAddress());
 }
 
diff --git a/runtime/vm/instructions_mips_test.cc b/runtime/vm/instructions_mips_test.cc
index 6c6fe07..a165485 100644
--- a/runtime/vm/instructions_mips_test.cc
+++ b/runtime/vm/instructions_mips_test.cc
@@ -15,8 +15,7 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchLinkPatchable(&stub_code->InvokeDartCodeLabel());
+  __ BranchLinkPatchable(*StubCode::InvokeDartCode_entry());
   __ Ret();
 }
 
@@ -28,18 +27,14 @@
   // return jump.
   CallPattern call(test->entry() + test->code().Size() - (2*Instr::kInstrSize),
                    test->code());
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             call.TargetAddress());
 }
 
 
 ASSEMBLER_TEST_GENERATE(Jump, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->InvokeDartCodeLabel());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchPatchable(&array_label);
+  __ BranchPatchable(*StubCode::InvokeDartCode_entry());
+  __ BranchPatchable(*StubCode::AllocateArray_entry());
 }
 
 
@@ -50,21 +45,21 @@
       VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
                              instrs.size(),
                              VirtualMemory::kReadWrite);
-  StubCode* stub_code = Isolate::Current()->stub_code();
   EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump1.TargetAddress());
   JumpPattern jump2(test->entry() + jump1.pattern_length_in_bytes(),
                     test->code());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
+  const Code& array_stub =
+      Code::Handle(StubCode::AllocateArray_entry()->code());
   EXPECT_EQ(array_stub.EntryPoint(), jump2.TargetAddress());
   uword target1 = jump1.TargetAddress();
   uword target2 = jump2.TargetAddress();
   jump1.SetTargetAddress(target2);
   jump2.SetTargetAddress(target1);
   EXPECT_EQ(array_stub.EntryPoint(), jump1.TargetAddress());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump2.TargetAddress());
 }
 
diff --git a/runtime/vm/instructions_x64_test.cc b/runtime/vm/instructions_x64_test.cc
index b9e3eb2..0ad8294 100644
--- a/runtime/vm/instructions_x64_test.cc
+++ b/runtime/vm/instructions_x64_test.cc
@@ -15,8 +15,7 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ call(&stub_code->InvokeDartCodeLabel());
+  __ Call(*StubCode::InvokeDartCode_entry());
   __ ret();
 }
 
@@ -27,13 +26,10 @@
 ASSEMBLER_TEST_GENERATE(Jump, assembler) {
   ASSERT(assembler->CodeSize() == 0);
   __ pushq(PP);
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
   prologue_code_size = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ JmpPatchable(&stub_code->InvokeDartCodeLabel(), PP);
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ JmpPatchable(&array_label, PP);
+  __ JmpPatchable(*StubCode::InvokeDartCode_entry(), PP);
+  __ JmpPatchable(*StubCode::AllocateArray_entry(), PP);
   __ popq(PP);
   __ ret();
 }
@@ -43,7 +39,6 @@
   ASSERT(prologue_code_size != -1);
   const Code& code = test->code();
   const Instructions& instrs = Instructions::Handle(code.instructions());
-  StubCode* stub_code = Isolate::Current()->stub_code();
   bool status =
       VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
                              instrs.size(),
@@ -51,19 +46,20 @@
   EXPECT(status);
   JumpPattern jump1(test->entry() + prologue_code_size, test->code());
   jump1.IsValid();
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump1.TargetAddress());
   JumpPattern jump2((test->entry() +
                      jump1.pattern_length_in_bytes() + prologue_code_size),
                     test->code());
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
+  const Code& array_stub =
+      Code::Handle(StubCode::AllocateArray_entry()->code());
   EXPECT_EQ(array_stub.EntryPoint(), jump2.TargetAddress());
   uword target1 = jump1.TargetAddress();
   uword target2 = jump2.TargetAddress();
   jump1.SetTargetAddress(target2);
   jump2.SetTargetAddress(target1);
   EXPECT_EQ(array_stub.EntryPoint(), jump1.TargetAddress());
-  EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
+  EXPECT_EQ(StubCode::InvokeDartCode_entry()->label().address(),
             jump2.TargetAddress());
 }
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index a5e7f5e..b7bacba 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -49,7 +49,19 @@
       ssa_temp_index_(-1),
       input_use_list_(NULL),
       env_use_list_(NULL),
-      constant_value_(Object::ZoneHandle(ConstantPropagator::Unknown())) {
+      constant_value_(NULL) {
+}
+
+
+// A value in the constant propagation lattice.
+//    - non-constant sentinel
+//    - a constant (any non-sentinel value)
+//    - unknown sentinel
+Object& Definition::constant_value() {
+  if (constant_value_ == NULL) {
+    constant_value_ = &Object::ZoneHandle(ConstantPropagator::Unknown());
+  }
+  return *constant_value_;
 }
 
 
@@ -2933,16 +2945,15 @@
 }
 
 
-static uword TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
+static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
   if (!FLAG_two_args_smi_icd) {
     return 0;
   }
-  StubCode* stub_code = Isolate::Current()->stub_code();
   switch (kind) {
-    case Token::kADD: return stub_code->SmiAddInlineCacheEntryPoint();
-    case Token::kSUB: return stub_code->SmiSubInlineCacheEntryPoint();
-    case Token::kEQ:  return stub_code->SmiEqualInlineCacheEntryPoint();
-    default:          return 0;
+    case Token::kADD: return StubCode::SmiAddInlineCache_entry();
+    case Token::kSUB: return StubCode::SmiSubInlineCache_entry();
+    case Token::kEQ:  return StubCode::SmiEqualInlineCache_entry();
+    default:          return NULL;
   }
 }
 
@@ -2983,8 +2994,8 @@
     // Unoptimized code.
     ASSERT(!HasICData());
     bool is_smi_two_args_op = false;
-    const uword label_address = TwoArgsSmiOpInlineCacheEntry(token_kind());
-    if (label_address != 0) {
+    const StubEntry* stub_entry = TwoArgsSmiOpInlineCacheEntry(token_kind());
+    if (stub_entry != NULL) {
       // We have a dedicated inline cache stub for this operation, add an
       // an initial Smi/Smi check with count 0.
       ASSERT(call_ic_data->NumArgsTested() == 2);
@@ -3012,8 +3023,7 @@
     }
     if (is_smi_two_args_op) {
       ASSERT(ArgumentCount() == 2);
-      ExternalLabel target_label(label_address);
-      compiler->EmitInstanceCall(&target_label, *call_ic_data, ArgumentCount(),
+      compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(),
                                  deopt_id(), token_pos(), locs());
     } else if (FLAG_ic_range_profiling &&
                (Token::IsBinaryArithmeticOperator(token_kind()) ||
@@ -3022,11 +3032,10 @@
                  (ArgumentCount() == 1));
       ASSERT(Token::IsBinaryArithmeticOperator(token_kind()) ==
                  (ArgumentCount() == 2));
-      StubCode* stub_code = compiler->isolate()->stub_code();
-      ExternalLabel target_label((ArgumentCount() == 1) ?
-          stub_code->UnaryRangeCollectingInlineCacheEntryPoint() :
-          stub_code->BinaryRangeCollectingInlineCacheEntryPoint());
-      compiler->EmitInstanceCall(&target_label, *call_ic_data, ArgumentCount(),
+      const StubEntry* stub_entry = (ArgumentCount() == 1)
+          ? StubCode::UnaryRangeCollectingInlineCache_entry()
+          : StubCode::BinaryRangeCollectingInlineCache_entry();
+      compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(),
                                  deopt_id(), token_pos(), locs());
     } else {
       compiler->GenerateInstanceCall(deopt_id(),
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index c943680..44919ff 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -1748,7 +1748,7 @@
   //    - non-constant sentinel
   //    - a constant (any non-sentinel value)
   //    - unknown sentinel
-  Object& constant_value() const { return constant_value_; }
+  Object& constant_value();
 
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
@@ -1801,7 +1801,7 @@
   Value* input_use_list_;
   Value* env_use_list_;
 
-  Object& constant_value_;
+  Object* constant_value_;
 
   DISALLOW_COPY_AND_ASSIGN(Definition);
 };
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 6538dec..1db4ad1 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -104,8 +104,12 @@
   __ bkpt(0);
   __ Bind(&stack_ok);
 #endif
-  __ LeaveDartFrame();
+  ASSERT(__ constant_pool_allowed());
+  __ LeaveDartFrame();  // Disallows constant pool use.
   __ Ret();
+  // This ReturnInstr may be emitted out of order by the optimizer. The next
+  // block may be a target expecting a properly set constant pool pointer.
+  __ set_constant_pool_allowed(true);
 }
 
 
@@ -938,10 +942,9 @@
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
   const bool is_leaf_call =
     (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel* stub_entry;
+  const StubEntry* stub_entry = NULL;
   if (is_bootstrap_native() || is_leaf_call) {
-    stub_entry = &stub_code->CallBootstrapCFunctionLabel();
+    stub_entry = StubCode::CallBootstrapCFunction_entry();
 #if defined(USING_SIMULATOR)
     entry = Simulator::RedirectExternalReference(
         entry, Simulator::kBootstrapNativeCall, function().NumParameters());
@@ -950,7 +953,7 @@
     // In the case of non bootstrap native methods the CallNativeCFunction
     // stub generates the redirection address when running under the simulator
     // and hence we do not change 'entry' here.
-    stub_entry = &stub_code->CallNativeCFunctionLabel();
+    stub_entry = StubCode::CallNativeCFunction_entry();
 #if defined(USING_SIMULATOR)
     if (!function().IsNativeAutoSetupScope()) {
       entry = Simulator::RedirectExternalReference(
@@ -961,7 +964,7 @@
   __ LoadImmediate(R5, entry);
   __ LoadImmediate(R1, argc_tag);
   compiler->GenerateCall(token_pos(),
-                         stub_entry,
+                         *stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   __ Pop(result);
@@ -980,6 +983,7 @@
 
 
 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler->is_optimizing());
   const Register char_code = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
   __ LoadImmediate(result,
@@ -1808,7 +1812,6 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     Isolate* isolate = compiler->isolate();
-    StubCode* stub_code = isolate->stub_code();
 
     if (Assembler::EmittingComments()) {
       __ Comment("%s slow path allocation of %s",
@@ -1817,8 +1820,8 @@
     }
     __ Bind(entry_label());
     const Code& stub =
-        Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
-    const ExternalLabel label(stub.EntryPoint());
+        Code::Handle(isolate, StubCode::GetAllocationStubForClass(cls_));
+    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction_->locs();
 
@@ -1826,9 +1829,10 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
+                           stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
+    compiler->AddStubCallTarget(stub);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -2389,15 +2393,10 @@
       return;
     }
   }
-  Isolate* isolate = compiler->isolate();
-  const Code& stub = Code::Handle(
-      isolate, isolate->stub_code()->GetAllocateArrayStub());
-  const ExternalLabel label(stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateArray_entry(),
                          RawPcDescriptors::kOther,
                          locs());
-  compiler->AddStubCallTarget(stub);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
 
@@ -2681,10 +2680,8 @@
     compiler->SaveLiveRegisters(locs);
 
     __ LoadImmediate(R1, instruction_->num_context_variables());
-    StubCode* stub_code = compiler->isolate()->stub_code();
-    const ExternalLabel label(stub_code->AllocateContextEntryPoint());
     compiler->GenerateCall(instruction_->token_pos(),
-                           &label,
+                           *StubCode::AllocateContext_entry(),
                            RawPcDescriptors::kOther,
                            locs);
     ASSERT(instruction_->locs()->out(0).reg() == R0);
@@ -2739,10 +2736,8 @@
   ASSERT(locs()->out(0).reg() == R0);
 
   __ LoadImmediate(R1, num_context_variables());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->AllocateContextEntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateContext_entry(),
                          RawPcDescriptors::kOther,
                          locs());
 }
@@ -2919,8 +2914,13 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
-  __ ldr(IP, Address(IP));
+  if (compiler->is_optimizing()) {
+    __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
+    __ ldr(IP, Address(IP));
+  } else {
+    __ LoadIsolate(IP);
+    __ ldr(IP, Address(IP, Isolate::stack_limit_offset()));
+  }
   __ cmp(SP, Operand(IP));
   __ b(slow_path->entry_label(), LS);
   if (compiler->CanOSRFunction() && in_loop()) {
@@ -6806,12 +6806,11 @@
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Isolate* isolate = compiler->isolate();
-  StubCode* stub_code = isolate->stub_code();
   const Code& stub = Code::Handle(isolate,
-                                  stub_code->GetAllocationStubForClass(cls()));
-  const ExternalLabel label(stub.EntryPoint());
+                                  StubCode::GetAllocationStubForClass(cls()));
+  const StubEntry stub_entry(stub);
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   compiler->AddStubCallTarget(stub);
@@ -6821,9 +6820,8 @@
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
-  compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
+  compiler->GenerateCall(
+      token_pos(), *StubCode::DebugStepCheck_entry(), stub_kind_, locs());
 }
 
 
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 1f12744..9587767 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -56,11 +56,11 @@
     if (value.IsRegister()) {
       __ Push(value.reg());
     } else if (value.IsConstant()) {
-      __ PushObject(value.constant(), PP);
+      __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
       const intptr_t value_offset = value.ToStackSlotOffset();
-      __ LoadFromOffset(TMP, value.base_reg(), value_offset, PP);
+      __ LoadFromOffset(TMP, value.base_reg(), value_offset);
       __ Push(TMP);
     }
   }
@@ -98,13 +98,17 @@
       (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
   ASSERT(fp_sp_dist <= 0);
   __ sub(R2, SP, Operand(FP));
-  __ CompareImmediate(R2, fp_sp_dist, PP);
+  __ CompareImmediate(R2, fp_sp_dist);
   __ b(&stack_ok, EQ);
   __ brk(0);
   __ Bind(&stack_ok);
 #endif
-  __ LeaveDartFrame();
+  ASSERT(__ constant_pool_allowed());
+  __ LeaveDartFrame();  // Disallows constant pool use.
   __ ret();
+  // This ReturnInstr may be emitted out of order by the optimizer. The next
+  // block may be a target expecting a properly set constant pool pointer.
+  __ set_constant_pool_allowed(true);
 }
 
 
@@ -183,9 +187,9 @@
     __ sub(result, result, Operand(1));
     const int64_t val =
         Smi::RawValue(true_value) - Smi::RawValue(false_value);
-    __ AndImmediate(result, result, val, PP);
+    __ AndImmediate(result, result, val);
     if (false_value != 0) {
-      __ AddImmediate(result, result, Smi::RawValue(false_value), PP);
+      __ AddImmediate(result, result, Smi::RawValue(false_value));
     }
   }
 }
@@ -209,17 +213,17 @@
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names()));
-  __ LoadObject(R4, arguments_descriptor, PP);
+  __ LoadObject(R4, arguments_descriptor);
 
   // R4: Arguments descriptor.
   // R0: Function.
   ASSERT(locs()->in(0).reg() == R0);
-  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), PP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset());
 
   // R2: instructions.
   // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
-  __ LoadImmediate(R5, 0, PP);
-  __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
+  __ LoadImmediate(R5, 0);
+  __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ blr(R2);
   compiler->RecordSafepoint(locs());
   // Marks either the continuation point in unoptimized code or the
@@ -249,7 +253,7 @@
 
 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register result = locs()->out(0).reg();
-  __ LoadFromOffset(result, FP, local().index() * kWordSize, PP);
+  __ LoadFromOffset(result, FP, local().index() * kWordSize);
 }
 
 
@@ -266,7 +270,7 @@
   const Register value = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
   ASSERT(result == value);  // Assert that register assignment is correct.
-  __ StoreToOffset(value, FP, local().index() * kWordSize, PP);
+  __ StoreToOffset(value, FP, local().index() * kWordSize);
 }
 
 
@@ -283,7 +287,7 @@
   // The register allocator drops constant definitions that have no uses.
   if (!locs()->out(0).IsInvalid()) {
     const Register result = locs()->out(0).reg();
-    __ LoadObject(result, value(), PP);
+    __ LoadObject(result, value());
   }
 }
 
@@ -309,13 +313,12 @@
           __ veor(dst, dst, dst);
         } else {
           const VRegister dst = locs()->out(0).fpu_reg();
-          __ LoadDImmediate(dst, Double::Cast(value()).value(), PP);
+          __ LoadDImmediate(dst, Double::Cast(value()).value());
         }
         break;
       case kUnboxedInt32:
         __ LoadImmediate(locs()->out(0).reg(),
-                         static_cast<int32_t>(Smi::Cast(value()).Value()),
-                         PP);
+                         static_cast<int32_t>(Smi::Cast(value()).Value()));
         break;
       default:
         UNREACHABLE();
@@ -362,13 +365,13 @@
   Label done;
 
   if (Isolate::Current()->flags().type_checks()) {
-    __ CompareObject(reg, Bool::True(), PP);
+    __ CompareObject(reg, Bool::True());
     __ b(&done, EQ);
-    __ CompareObject(reg, Bool::False(), PP);
+    __ CompareObject(reg, Bool::False());
     __ b(&done, EQ);
   } else {
     ASSERT(Isolate::Current()->flags().asserts());
-    __ CompareObject(reg, Object::null_instance(), PP);
+    __ CompareObject(reg, Object::null_instance());
     __ b(&done, NE);
   }
 
@@ -456,10 +459,10 @@
   Condition true_condition = TokenKindToSmiCondition(kind);
 
   if (left.IsConstant()) {
-    __ CompareObject(right.reg(), left.constant(), PP);
+    __ CompareObject(right.reg(), left.constant());
     true_condition = FlipCondition(true_condition);
   } else if (right.IsConstant()) {
-    __ CompareObject(left.reg(), right.constant(), PP);
+    __ CompareObject(left.reg(), right.constant());
   } else {
     __ CompareRegisters(left.reg(), right.reg());
   }
@@ -551,10 +554,10 @@
   const Register result = locs()->out(0).reg();
   Label done;
   __ Bind(&is_false);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ b(&done);
   __ Bind(&is_true);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -596,7 +599,7 @@
     ASSERT(right.constant().IsSmi());
     const int64_t imm =
         reinterpret_cast<int64_t>(right.constant().raw());
-    __ TestImmediate(left, imm, PP);
+    __ TestImmediate(left, imm);
   } else {
     __ tst(left, Operand(right.reg()));
   }
@@ -647,13 +650,13 @@
   bool result = data[1] == true_result;
   __ tsti(val_reg, Immediate(kSmiTagMask));
   __ b(result ? labels.true_label : labels.false_label, EQ);
-  __ LoadClassId(cid_reg, val_reg, PP);
+  __ LoadClassId(cid_reg, val_reg);
 
   for (intptr_t i = 2; i < data.length(); i += 2) {
     const intptr_t test_cid = data[i];
     ASSERT(test_cid != kSmiCid);
     result = data[i + 1] == true_result;
-    __ CompareImmediate(cid_reg, test_cid, PP);
+    __ CompareImmediate(cid_reg, test_cid);
     __ b(result ? labels.true_label : labels.false_label, EQ);
   }
   // No match found, deoptimize or false.
@@ -686,10 +689,10 @@
   // TODO(zra): instead of branching, use the csel instruction to get
   // True or False into result.
   __ Bind(&is_false);
-  __ LoadObject(result_reg, Bool::False(), PP);
+  __ LoadObject(result_reg, Bool::False());
   __ b(&done);
   __ Bind(&is_true);
-  __ LoadObject(result_reg, Bool::True(), PP);
+  __ LoadObject(result_reg, Bool::True());
   __ Bind(&done);
 }
 
@@ -746,10 +749,10 @@
   const Register result = locs()->out(0).reg();
   Label done;
   __ Bind(&is_false);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ b(&done);
   __ Bind(&is_true);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -777,13 +780,13 @@
   const Register result = locs()->out(0).reg();
 
   // Push the result place holder initialized to NULL.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   // Pass a pointer to the first argument in R2.
   if (!function().HasOptionalParameters()) {
     __ AddImmediate(R2, FP, (kParamEndSlotFromFp +
-                             function().NumParameters()) * kWordSize, PP);
+                             function().NumParameters()) * kWordSize);
   } else {
-    __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize, PP);
+    __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize);
   }
   // Compute the effective address. When running under the simulator,
   // this is a redirection address that forces the simulator to call
@@ -792,10 +795,9 @@
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
   const bool is_leaf_call =
     (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel* stub_entry;
+  const StubEntry* stub_entry = NULL;
   if (is_bootstrap_native() || is_leaf_call) {
-    stub_entry = &stub_code->CallBootstrapCFunctionLabel();
+    stub_entry = StubCode::CallBootstrapCFunction_entry();
 #if defined(USING_SIMULATOR)
     entry = Simulator::RedirectExternalReference(
         entry, Simulator::kBootstrapNativeCall, function().NumParameters());
@@ -804,7 +806,7 @@
     // In the case of non bootstrap native methods the CallNativeCFunction
     // stub generates the redirection address when running under the simulator
     // and hence we do not change 'entry' here.
-    stub_entry = &stub_code->CallNativeCFunctionLabel();
+    stub_entry = StubCode::CallNativeCFunction_entry();
 #if defined(USING_SIMULATOR)
     if (!function().IsNativeAutoSetupScope()) {
       entry = Simulator::RedirectExternalReference(
@@ -812,10 +814,10 @@
     }
 #endif
   }
-  __ LoadImmediate(R5, entry, PP);
-  __ LoadImmediate(R1, argc_tag, PP);
+  __ LoadImmediate(R5, entry);
+  __ LoadImmediate(R1, argc_tag);
   compiler->GenerateCall(token_pos(),
-                         stub_entry,
+                         *stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   __ Pop(result);
@@ -834,12 +836,13 @@
 
 
 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler->is_optimizing());
   const Register char_code = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
   __ LoadImmediate(
-      result, reinterpret_cast<uword>(Symbols::PredefinedAddress()), PP);
+      result, reinterpret_cast<uword>(Symbols::PredefinedAddress()));
   __ AddImmediate(
-      result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize, PP);
+      result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ SmiUntag(TMP, char_code);  // Untag to use scaled adress mode.
   __ ldr(result, Address(result, TMP, UXTX, Address::Scaled));
 }
@@ -859,10 +862,10 @@
   ASSERT(cid_ == kOneByteStringCid);
   const Register str = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ LoadFieldFromOffset(result, str, String::length_offset(), PP);
+  __ LoadFieldFromOffset(result, str, String::length_offset());
   __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte);
-  __ CompareImmediate(result, Smi::RawValue(1), PP);
-  __ LoadImmediate(result, -1, PP);
+  __ CompareImmediate(result, Smi::RawValue(1));
+  __ LoadImmediate(result, -1);
   __ csel(result, TMP, result, EQ);
   __ SmiTag(result);
 }
@@ -910,10 +913,10 @@
   const Register obj = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
   if (object()->definition()->representation() == kUntagged) {
-    __ LoadFromOffset(result, obj, offset(), PP);
+    __ LoadFromOffset(result, obj, offset());
   } else {
     ASSERT(object()->definition()->representation() == kTagged);
-    __ LoadFieldFromOffset(result, obj, offset(), PP);
+    __ LoadFieldFromOffset(result, obj, offset());
   }
 }
 
@@ -934,10 +937,10 @@
   static const intptr_t kSmiCidSource =
       static_cast<intptr_t>(kSmiCid) << RawObject::kClassIdTagPos;
 
-  __ LoadImmediate(TMP, reinterpret_cast<int64_t>(&kSmiCidSource) + 1, PP);
+  __ LoadImmediate(TMP, reinterpret_cast<int64_t>(&kSmiCidSource) + 1);
   __ tsti(object, Immediate(kSmiTagMask));
   __ csel(TMP, TMP, object, EQ);
-  __ LoadClassId(result, TMP, PP);
+  __ LoadClassId(result, TMP);
   __ SmiTag(result);
 }
 
@@ -1311,7 +1314,7 @@
     case kOneByteStringCid: {
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
-        __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()), PP);
+        __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()));
         __ str(TMP, element_address, kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
@@ -1331,11 +1334,11 @@
         } else if (value < 0) {
           value = 0;
         }
-        __ LoadImmediate(TMP, static_cast<int8_t>(value), PP);
+        __ LoadImmediate(TMP, static_cast<int8_t>(value));
         __ str(TMP, element_address, kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
-        __ CompareImmediate(value, 0x1FE, PP);  // Smi value and smi 0xFF.
+        __ CompareImmediate(value, 0x1FE);  // Smi value and smi 0xFF.
         // Clamp to 0x00 or 0xFF respectively.
         __ csetm(TMP, GT);  // TMP = value > 0x1FE ? -1 : 0.
         __ csel(TMP, value, TMP, LS);  // TMP = value in range ? value : TMP.
@@ -1386,7 +1389,7 @@
                          Label* value_is_smi = NULL) {
   Label done;
   if (value_is_smi == NULL) {
-    __ LoadImmediate(value_cid_reg, kSmiCid, PP);
+    __ LoadImmediate(value_cid_reg, kSmiCid);
   }
   __ tsti(value_reg, Immediate(kSmiTagMask));
   if (value_is_smi == NULL) {
@@ -1394,7 +1397,7 @@
   } else {
     __ b(value_is_smi, EQ);
   }
-  __ LoadClassId(value_cid_reg, value_reg, PP);
+  __ LoadClassId(value_cid_reg, value_reg);
   __ Bind(&done);
 }
 
@@ -1469,7 +1472,7 @@
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
   if (emit_full_guard) {
-    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     FieldAddress field_cid_operand(
         field_reg, Field::guarded_cid_offset(), kUnsignedWord);
@@ -1486,11 +1489,11 @@
       __ CompareRegisters(value_cid_reg, TMP);
     } else if (value_cid == kNullCid) {
       __ ldr(value_cid_reg, field_nullability_operand, kUnsignedWord);
-      __ CompareImmediate(value_cid_reg, value_cid, PP);
+      __ CompareImmediate(value_cid_reg, value_cid);
     } else {
       Label skip_length_check;
       __ ldr(value_cid_reg, field_cid_operand, kUnsignedWord);
-      __ CompareImmediate(value_cid_reg, value_cid, PP);
+      __ CompareImmediate(value_cid_reg, value_cid);
     }
     __ b(&ok, EQ);
 
@@ -1504,14 +1507,14 @@
       // Uninitialized field can be handled inline. Check if the
       // field is still unitialized.
       __ ldr(TMP, field_cid_operand, kUnsignedWord);
-      __ CompareImmediate(TMP, kIllegalCid, PP);
+      __ CompareImmediate(TMP, kIllegalCid);
       __ b(fail, NE);
 
       if (value_cid == kDynamicCid) {
         __ str(value_cid_reg, field_cid_operand, kUnsignedWord);
         __ str(value_cid_reg, field_nullability_operand, kUnsignedWord);
       } else {
-        __ LoadImmediate(TMP, value_cid, PP);
+        __ LoadImmediate(TMP, value_cid);
         __ str(TMP, field_cid_operand, kUnsignedWord);
         __ str(TMP, field_nullability_operand, kUnsignedWord);
       }
@@ -1527,8 +1530,8 @@
       __ Bind(fail);
 
       __ LoadFieldFromOffset(
-          TMP, field_reg, Field::guarded_cid_offset(), PP, kUnsignedWord);
-      __ CompareImmediate(TMP, kDynamicCid, PP);
+          TMP, field_reg, Field::guarded_cid_offset(), kUnsignedWord);
+      __ CompareImmediate(TMP, kDynamicCid);
       __ b(&ok, EQ);
 
       __ Push(field_reg);
@@ -1547,13 +1550,13 @@
 
       if (field_cid != kSmiCid) {
         __ b(fail, EQ);
-        __ LoadClassId(value_cid_reg, value_reg, PP);
-        __ CompareImmediate(value_cid_reg, field_cid, PP);
+        __ LoadClassId(value_cid_reg, value_reg);
+        __ CompareImmediate(value_cid_reg, field_cid);
       }
 
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ b(&ok, EQ);
-        __ CompareObject(value_reg, Object::null_object(), PP);
+        __ CompareObject(value_reg, Object::null_object());
       }
 
       __ b(fail, NE);
@@ -1609,7 +1612,7 @@
 
     Label ok;
 
-    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     __ ldr(offset_reg,
            FieldAddress(field_reg,
@@ -1648,7 +1651,7 @@
 
     __ ldr(TMP, FieldAddress(value_reg,
                             field().guarded_list_length_in_object_offset()));
-    __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length()), PP);
+    __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length()));
     __ b(deopt, NE);
   }
 }
@@ -1665,7 +1668,6 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     Isolate* isolate = compiler->isolate();
-    StubCode* stub_code = isolate->stub_code();
 
     if (Assembler::EmittingComments()) {
       __ Comment("%s slow path allocation of %s",
@@ -1674,8 +1676,8 @@
     }
     __ Bind(entry_label());
     const Code& stub =
-        Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
-    const ExternalLabel label(stub.EntryPoint());
+        Code::Handle(isolate, StubCode::GetAllocationStubForClass(cls_));
+    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction_->locs();
 
@@ -1683,9 +1685,10 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
+                           stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
+    compiler->AddStubCallTarget(stub);
     __ mov(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -1697,21 +1700,13 @@
                        Register result,
                        Register temp) {
     if (compiler->intrinsic_mode()) {
-      __ TryAllocate(cls,
-                     compiler->intrinsic_slow_path_label(),
-                     result,
-                     temp,
-                     PP);
+      __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), result, temp);
     } else {
       BoxAllocationSlowPath* slow_path =
           new BoxAllocationSlowPath(instruction, cls, result);
       compiler->AddSlowPathCode(slow_path);
 
-      __ TryAllocate(cls,
-                     slow_path->entry_label(),
-                     result,
-                     temp,
-                     PP);
+      __ TryAllocate(cls, slow_path->entry_label(), result, temp);
       __ Bind(slow_path->exit_label());
     }
   }
@@ -1731,13 +1726,13 @@
                              intptr_t offset,
                              Register temp) {
   Label done;
-  __ LoadFieldFromOffset(box_reg, instance_reg, offset, PP);
-  __ CompareObject(box_reg, Object::null_object(), PP);
+  __ LoadFieldFromOffset(box_reg, instance_reg, offset);
+  __ CompareObject(box_reg, Object::null_object());
   __ b(&done, NE);
   BoxAllocationSlowPath::Allocate(
       compiler, instruction, cls, box_reg, temp);
   __ mov(temp, box_reg);
-  __ StoreIntoObjectOffset(instance_reg, offset, temp, PP);
+  __ StoreIntoObjectOffset(instance_reg, offset, temp);
   __ Bind(&done);
 }
 
@@ -1805,22 +1800,22 @@
 
       BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ mov(temp2, temp);
-      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2, PP);
+      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2);
     } else {
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_, PP);
+      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_);
     }
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
-        __ StoreDFieldToOffset(value, temp, Double::value_offset(), PP);
+        __ StoreDFieldToOffset(value, temp, Double::value_offset());
         break;
       case kFloat32x4Cid:
         __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
-        __ StoreQFieldToOffset(value, temp, Float32x4::value_offset(), PP);
+        __ StoreQFieldToOffset(value, temp, Float32x4::value_offset());
         break;
       case kFloat64x2Cid:
         __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
-        __ StoreQFieldToOffset(value, temp, Float64x2::value_offset(), PP);
+        __ StoreQFieldToOffset(value, temp, Float64x2::value_offset());
         break;
       default:
         UNREACHABLE();
@@ -1845,32 +1840,32 @@
     Label store_float32x4;
     Label store_float64x2;
 
-    __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP);
+    __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
-    __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), PP,
+    __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(),
                            kUnsignedWord);
-    __ CompareImmediate(temp2, kNullCid, PP);
+    __ CompareImmediate(temp2, kNullCid);
     __ b(&store_pointer, EQ);
 
     __ LoadFromOffset(
         temp2, temp, Field::kind_bits_offset() - kHeapObjectTag,
-        PP, kUnsignedByte);
+        kUnsignedByte);
     __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit));
     __ b(&store_pointer, EQ);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP,
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(),
                            kUnsignedWord);
-    __ CompareImmediate(temp2, kDoubleCid, PP);
+    __ CompareImmediate(temp2, kDoubleCid);
     __ b(&store_double, EQ);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP,
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(),
                            kUnsignedWord);
-    __ CompareImmediate(temp2, kFloat32x4Cid, PP);
+    __ CompareImmediate(temp2, kFloat32x4Cid);
     __ b(&store_float32x4, EQ);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP,
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(),
                            kUnsignedWord);
-    __ CompareImmediate(temp2, kFloat64x2Cid, PP);
+    __ CompareImmediate(temp2, kFloat64x2Cid);
     __ b(&store_float64x2, EQ);
 
     // Fall through.
@@ -1890,8 +1885,8 @@
                        instance_reg,
                        offset_in_bytes_,
                        temp2);
-      __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset(), PP);
-      __ StoreDFieldToOffset(VTMP, temp, Double::value_offset(), PP);
+      __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset());
+      __ StoreDFieldToOffset(VTMP, temp, Double::value_offset());
       __ b(&skip_store);
     }
 
@@ -1904,8 +1899,8 @@
                        instance_reg,
                        offset_in_bytes_,
                        temp2);
-      __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset(), PP);
-      __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset(), PP);
+      __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset());
+      __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset());
       __ b(&skip_store);
     }
 
@@ -1918,8 +1913,8 @@
                        instance_reg,
                        offset_in_bytes_,
                        temp2);
-      __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset(), PP);
-      __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset(), PP);
+      __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset());
+      __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset());
       __ b(&skip_store);
     }
 
@@ -1929,21 +1924,15 @@
   if (ShouldEmitStoreBarrier()) {
     const Register value_reg = locs()->in(1).reg();
     __ StoreIntoObjectOffset(
-        instance_reg, offset_in_bytes_, value_reg, PP, CanValueBeSmi());
+        instance_reg, offset_in_bytes_, value_reg, CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreIntoObjectOffsetNoBarrier(
-          instance_reg,
-          offset_in_bytes_,
-          locs()->in(1).constant(),
-          PP);
+          instance_reg, offset_in_bytes_, locs()->in(1).constant());
     } else {
       const Register value_reg = locs()->in(1).reg();
       __ StoreIntoObjectOffsetNoBarrier(
-          instance_reg,
-          offset_in_bytes_,
-          value_reg,
-          PP);
+          instance_reg, offset_in_bytes_, value_reg);
     }
   }
   __ Bind(&skip_store);
@@ -1970,7 +1959,7 @@
 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register field = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ LoadFieldFromOffset(result, field, Field::value_offset(), PP);
+  __ LoadFieldFromOffset(result, field, Field::value_offset());
 }
 
 
@@ -1989,12 +1978,12 @@
   const Register value = locs()->in(0).reg();
   const Register temp = locs()->temp(0).reg();
 
-  __ LoadObject(temp, field(), PP);
+  __ LoadObject(temp, field());
   if (this->value()->NeedsStoreBuffer()) {
     __ StoreIntoObjectOffset(
-        temp, Field::value_offset(), value, PP, CanValueBeSmi());
+        temp, Field::value_offset(), value, CanValueBeSmi());
   } else {
-    __ StoreIntoObjectOffsetNoBarrier(temp, Field::value_offset(), value, PP);
+    __ StoreIntoObjectOffsetNoBarrier(temp, Field::value_offset(), value);
   }
 }
 
@@ -2077,8 +2066,8 @@
   // R6: null
   if (num_elements > 0) {
     const intptr_t array_size = instance_size - sizeof(RawArray);
-    __ LoadObject(R6, Object::null_object(), PP);
-    __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag, PP);
+    __ LoadObject(R6, Object::null_object());
+    __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag);
     if (array_size < (kInlineArraySize * kWordSize)) {
       intptr_t current_offset = 0;
       while (current_offset < array_size) {
@@ -2091,7 +2080,7 @@
       __ CompareRegisters(R8, R3);
       __ b(&end_loop, CS);
       __ str(R6, Address(R8));
-      __ AddImmediate(R8, R8, kWordSize, kNoPP);
+      __ AddImmediate(R8, R8, kWordSize);
       __ b(&init_loop);
       __ Bind(&end_loop);
     }
@@ -2116,7 +2105,7 @@
       Label slow_path, done;
       InlineArrayAllocation(compiler, length, &slow_path, &done);
       __ Bind(&slow_path);
-      __ PushObject(Object::null_object(), PP);  // Make room for the result.
+      __ PushObject(Object::null_object());  // Make room for the result.
       __ Push(kLengthReg);  // length.
       __ Push(kElemTypeReg);
       compiler->GenerateRuntimeCall(token_pos(),
@@ -2130,15 +2119,10 @@
       return;
     }
   }
-  Isolate* isolate = compiler->isolate();
-  const Code& stub = Code::Handle(
-      isolate, isolate->stub_code()->GetAllocateArrayStub());
-  const ExternalLabel label(stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateArray_entry(),
                          RawPcDescriptors::kOther,
                          locs());
-  compiler->AddStubCallTarget(stub);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
 
@@ -2173,18 +2157,18 @@
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     const VRegister result = locs()->out(0).fpu_reg();
     const Register temp = locs()->temp(0).reg();
-    __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
+    __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
     const intptr_t cid = field()->UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleLoadFieldInstr");
-        __ LoadDFieldFromOffset(result, temp, Double::value_offset(), PP);
+        __ LoadDFieldFromOffset(result, temp, Double::value_offset());
         break;
       case kFloat32x4Cid:
-        __ LoadQFieldFromOffset(result, temp, Float32x4::value_offset(), PP);
+        __ LoadQFieldFromOffset(result, temp, Float32x4::value_offset());
         break;
       case kFloat64x2Cid:
-        __ LoadQFieldFromOffset(result, temp, Float64x2::value_offset(), PP);
+        __ LoadQFieldFromOffset(result, temp, Float64x2::value_offset());
         break;
       default:
         UNREACHABLE();
@@ -2202,7 +2186,7 @@
     Label load_float32x4;
     Label load_float64x2;
 
-    __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()), PP);
+    __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()));
 
     FieldAddress field_cid_operand(
         result_reg, Field::guarded_cid_offset(), kUnsignedWord);
@@ -2210,19 +2194,19 @@
         result_reg, Field::is_nullable_offset(), kUnsignedWord);
 
     __ ldr(temp, field_nullability_operand, kUnsignedWord);
-    __ CompareImmediate(temp, kNullCid, PP);
+    __ CompareImmediate(temp, kNullCid);
     __ b(&load_pointer, EQ);
 
     __ ldr(temp, field_cid_operand, kUnsignedWord);
-    __ CompareImmediate(temp, kDoubleCid, PP);
+    __ CompareImmediate(temp, kDoubleCid);
     __ b(&load_double, EQ);
 
     __ ldr(temp, field_cid_operand, kUnsignedWord);
-    __ CompareImmediate(temp, kFloat32x4Cid, PP);
+    __ CompareImmediate(temp, kFloat32x4Cid);
     __ b(&load_float32x4, EQ);
 
     __ ldr(temp, field_cid_operand, kUnsignedWord);
-    __ CompareImmediate(temp, kFloat64x2Cid, PP);
+    __ CompareImmediate(temp, kFloat64x2Cid);
     __ b(&load_float64x2, EQ);
 
     // Fall through.
@@ -2239,9 +2223,9 @@
                                       compiler->double_class(),
                                       result_reg,
                                       temp);
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
-      __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset(), PP);
-      __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset(), PP);
+      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
+      __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset());
+      __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset());
       __ b(&done);
     }
 
@@ -2252,9 +2236,9 @@
                                       compiler->float32x4_class(),
                                       result_reg,
                                       temp);
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
-      __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset(), PP);
-      __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset(), PP);
+      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
+      __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset());
+      __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset());
       __ b(&done);
     }
 
@@ -2265,15 +2249,15 @@
                                       compiler->float64x2_class(),
                                       result_reg,
                                       temp);
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes(), PP);
-      __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset(), PP);
-      __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset(), PP);
+      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
+      __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset());
+      __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset());
       __ b(&done);
     }
 
     __ Bind(&load_pointer);
   }
-  __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes(), PP);
+  __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes());
   __ Bind(&done);
 }
 
@@ -2296,8 +2280,8 @@
 
   // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   // A runtime call to instantiate the type is required.
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
-  __ PushObject(type(), PP);
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ PushObject(type());
   __ Push(instantiator_reg);  // Push instantiator type arguments.
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2339,33 +2323,33 @@
   Label type_arguments_instantiated;
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawInstantiatedRaw(len)) {
-    __ CompareObject(instantiator_reg, Object::null_object(), PP);
+    __ CompareObject(instantiator_reg, Object::null_object());
     __ b(&type_arguments_instantiated, EQ);
   }
 
-  __ LoadObject(R2, type_arguments(), PP);
-  __ LoadFieldFromOffset(R2, R2, TypeArguments::instantiations_offset(), PP);
-  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, PP);
+  __ LoadObject(R2, type_arguments());
+  __ LoadFieldFromOffset(R2, R2, TypeArguments::instantiations_offset());
+  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag);
   // The instantiations cache is initialized with Object::zero_array() and is
   // therefore guaranteed to contain kNoInstantiator. No length check needed.
   Label loop, found, slow_case;
   __ Bind(&loop);
-  __ LoadFromOffset(R1, R2, 0 * kWordSize, PP);  // Cached instantiator.
+  __ LoadFromOffset(R1, R2, 0 * kWordSize);  // Cached instantiator.
   __ CompareRegisters(R1, R0);
   __ b(&found, EQ);
-  __ AddImmediate(R2, R2, 2 * kWordSize, PP);
-  __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator), PP);
+  __ AddImmediate(R2, R2, 2 * kWordSize);
+  __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator));
   __ b(&loop, NE);
   __ b(&slow_case);
   __ Bind(&found);
-  __ LoadFromOffset(R0, R2, 1 * kWordSize, PP);  // Cached instantiated args.
+  __ LoadFromOffset(R0, R2, 1 * kWordSize);  // Cached instantiated args.
   __ b(&type_arguments_instantiated);
 
   __ Bind(&slow_case);
   // Instantiate non-null type arguments.
   // A runtime call to instantiate the type arguments is required.
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
-  __ PushObject(type_arguments(), PP);
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ PushObject(type_arguments());
   __ Push(instantiator_reg);  // Push instantiator type arguments.
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2409,11 +2393,9 @@
 
     compiler->SaveLiveRegisters(locs);
 
-    __ LoadImmediate(R1, instruction_->num_context_variables(), PP);
-    StubCode* stub_code = compiler->isolate()->stub_code();
-    const ExternalLabel label(stub_code->AllocateContextEntryPoint());
+    __ LoadImmediate(R1, instruction_->num_context_variables());
     compiler->GenerateCall(instruction_->token_pos(),
-                           &label,
+                           *StubCode::AllocateContext_entry(),
                            RawPcDescriptors::kOther,
                            locs);
     ASSERT(instruction_->locs()->out(0).reg() == R0);
@@ -2445,7 +2427,7 @@
                       temp2);
 
   // Setup up number of context variables field.
-  __ LoadImmediate(temp0, num_context_variables(), PP);
+  __ LoadImmediate(temp0, num_context_variables());
   __ str(temp0, FieldAddress(result, Context::num_variables_offset()));
 
   __ Bind(slow_path->exit_label());
@@ -2468,11 +2450,9 @@
   ASSERT(locs()->temp(0).reg() == R1);
   ASSERT(locs()->out(0).reg() == R0);
 
-  __ LoadImmediate(R1, num_context_variables(), PP);
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->AllocateContextEntryPoint());
+  __ LoadImmediate(R1, num_context_variables());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateContext_entry(),
                          RawPcDescriptors::kOther,
                          locs());
 }
@@ -2495,14 +2475,14 @@
   Label call_runtime, no_call;
 
   __ ldr(temp, FieldAddress(field, Field::value_offset()));
-  __ CompareObject(temp, Object::sentinel(), PP);
+  __ CompareObject(temp, Object::sentinel());
   __ b(&call_runtime, EQ);
 
-  __ CompareObject(temp, Object::transition_sentinel(), PP);
+  __ CompareObject(temp, Object::transition_sentinel());
   __ b(&no_call, NE);
 
   __ Bind(&call_runtime);
-  __ PushObject(Object::null_object(), PP);  // Make room for (unused) result.
+  __ PushObject(Object::null_object());  // Make room for (unused) result.
   __ Push(field);
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2530,7 +2510,7 @@
   const Register context_value = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
 
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
+  __ PushObject(Object::null_object());  // Make room for the result.
   __ Push(context_value);
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2558,7 +2538,7 @@
                                 needs_stacktrace());
 
   // Restore the pool pointer.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
 
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -2569,14 +2549,14 @@
   const intptr_t fp_sp_dist =
       (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
   ASSERT(fp_sp_dist <= 0);
-  __ AddImmediate(SP, FP, fp_sp_dist, PP);
+  __ AddImmediate(SP, FP, fp_sp_dist);
 
   // Restore stack and initialize the two exception variables:
   // exception and stack trace variables.
   __ StoreToOffset(kExceptionObjectReg,
-                   FP, exception_var().index() * kWordSize, PP);
+                   FP, exception_var().index() * kWordSize);
   __ StoreToOffset(kStackTraceObjectReg,
-                   FP, stacktrace_var().index() * kWordSize, PP);
+                   FP, stacktrace_var().index() * kWordSize);
 }
 
 
@@ -2602,8 +2582,8 @@
       const Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      __ LoadImmediate(TMP, flags_address, PP);
-      __ LoadImmediate(value, Isolate::kOsrRequest, PP);
+      __ LoadImmediate(TMP, flags_address);
+      __ LoadImmediate(value, Isolate::kOsrRequest);
       __ str(value, Address(TMP));
     }
     __ Comment("CheckStackOverflowSlowPath");
@@ -2646,8 +2626,13 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address(), PP);
-  __ ldr(TMP, Address(TMP));
+  if (compiler->is_optimizing()) {
+    __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
+    __ ldr(TMP, Address(TMP));
+  } else {
+    __ LoadIsolate(TMP);
+    __ ldr(TMP, Address(TMP, Isolate::stack_limit_offset()));
+  }
   __ CompareRegisters(SP, TMP);
   __ b(slow_path->entry_label(), LS);
   if (compiler->CanOSRFunction() && in_loop()) {
@@ -2655,12 +2640,12 @@
     // In unoptimized code check the usage counter to trigger OSR at loop
     // stack checks.  Use progressively higher thresholds for more deeply
     // nested loops to attempt to hit outer loops with OSR when possible.
-    __ LoadObject(temp, compiler->parsed_function().function(), PP);
+    __ LoadObject(temp, compiler->parsed_function().function());
     intptr_t threshold =
         FLAG_optimization_counter_threshold * (loop_depth() + 1);
     __ LoadFieldFromOffset(
-        temp, temp, Function::usage_counter_offset(), PP, kWord);
-    __ CompareImmediate(temp, threshold, PP);
+        temp, temp, Function::usage_counter_offset(), kWord);
+    __ CompareImmediate(temp, threshold);
     __ b(slow_path->osr_entry_label(), GE);
   }
   if (compiler->ForceSlowPathForStackOverflow()) {
@@ -2676,7 +2661,7 @@
                                         Register result) {
   if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) {
     ASSERT(overflow != NULL);
-    __ LoadImmediate(TMP, 0x20000000000000LL, PP);
+    __ LoadImmediate(TMP, 0x20000000000000LL);
     __ add(TMP2, result, Operand(TMP));
     __ cmp(TMP2, Operand(TMP, LSL, 1));
     __ b(overflow, HI);
@@ -2733,7 +2718,7 @@
           !RangeUtils::IsWithin(right_range, 0, max_right - 1);
       if (right_needs_check) {
         __ CompareImmediate(right,
-            reinterpret_cast<int64_t>(Smi::New(max_right)), PP);
+            reinterpret_cast<int64_t>(Smi::New(max_right)));
         __ b(deopt, CS);
       }
       __ SmiUntag(TMP, right);
@@ -2758,7 +2743,7 @@
       }
 
       __ CompareImmediate(
-          right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP);
+          right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
       __ csel(result, ZR, result, CS);
       __ SmiUntag(TMP, right);
       __ lslv(TMP, left, TMP);
@@ -2771,7 +2756,7 @@
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
       __ CompareImmediate(
-          right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP);
+          right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
       __ b(deopt, CS);
     }
     // Left is not a constant.
@@ -2850,20 +2835,20 @@
     switch (op_kind()) {
       case Token::kADD: {
         if (deopt == NULL) {
-          __ AddImmediate(result, left, imm, PP);
+          __ AddImmediate(result, left, imm);
         } else {
-          __ AddImmediateSetFlags(result, left, imm, PP);
+          __ AddImmediateSetFlags(result, left, imm);
           __ b(deopt, VS);
         }
         break;
       }
       case Token::kSUB: {
         if (deopt == NULL) {
-          __ AddImmediate(result, left, -imm, PP);
+          __ AddImmediate(result, left, -imm);
         } else {
           // Negating imm and using AddImmediateSetFlags would not detect the
           // overflow when imm == kMinInt64.
-          __ SubImmediateSetFlags(result, left, imm, PP);
+          __ SubImmediateSetFlags(result, left, imm);
           __ b(deopt, VS);
         }
         break;
@@ -2871,7 +2856,7 @@
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
-        __ LoadImmediate(TMP, value, PP);
+        __ LoadImmediate(TMP, value);
         __ mul(result, left, TMP);
         if (deopt != NULL) {
           __ smulh(TMP, left, TMP);
@@ -2901,15 +2886,15 @@
       }
       case Token::kBIT_AND:
         // No overflow check.
-        __ AndImmediate(result, left, imm, PP);
+        __ AndImmediate(result, left, imm);
         break;
       case Token::kBIT_OR:
         // No overflow check.
-        __ OrImmediate(result, left, imm, PP);
+        __ OrImmediate(result, left, imm);
         break;
       case Token::kBIT_XOR:
         // No overflow check.
-        __ XorImmediate(result, left, imm, PP);
+        __ XorImmediate(result, left, imm);
         break;
       case Token::kSHR: {
         // Asr operation masks the count to 6 bits.
@@ -2993,7 +2978,7 @@
 
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
-      __ CompareImmediate(result, 0x4000000000000000LL, kNoPP);
+      __ CompareImmediate(result, 0x4000000000000000LL);
       __ b(deopt, EQ);
       __ SmiTag(result);
       break;
@@ -3042,7 +3027,7 @@
       const intptr_t kCountLimit = 0x3F;
       if ((right_range == NULL) ||
           !right_range->OnlyLessThanOrEqualTo(kCountLimit)) {
-        __ LoadImmediate(TMP2, kCountLimit, PP);
+        __ LoadImmediate(TMP2, kCountLimit);
         __ CompareRegisters(TMP, TMP2);
         __ csel(TMP, TMP2, TMP, GT);
       }
@@ -3137,12 +3122,12 @@
 
   switch (from_representation()) {
     case kUnboxedDouble:
-      __ StoreDFieldToOffset(value, out_reg, ValueOffset(), PP);
+      __ StoreDFieldToOffset(value, out_reg, ValueOffset());
       break;
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
-      __ StoreQFieldToOffset(value, out_reg, ValueOffset(), PP);
+      __ StoreQFieldToOffset(value, out_reg, ValueOffset());
       break;
     default:
       UNREACHABLE();
@@ -3174,7 +3159,7 @@
 
     case kUnboxedDouble: {
       const VRegister result = locs()->out(0).fpu_reg();
-      __ LoadDFieldFromOffset(result, box, ValueOffset(), PP);
+      __ LoadDFieldFromOffset(result, box, ValueOffset());
       break;
     }
 
@@ -3182,7 +3167,7 @@
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4: {
       const VRegister result = locs()->out(0).fpu_reg();
-      __ LoadQFieldFromOffset(result, box, ValueOffset(), PP);
+      __ LoadQFieldFromOffset(result, box, ValueOffset());
       break;
     }
 
@@ -3232,12 +3217,12 @@
 
     if ((value()->Type()->ToNullableCid() == box_cid) &&
         value()->Type()->is_nullable()) {
-      __ CompareObject(box, Object::null_object(), PP);
+      __ CompareObject(box, Object::null_object());
       __ b(deopt, EQ);
     } else {
       __ tsti(box, Immediate(kSmiTagMask));
       __ b(CanConvertSmi() ? &is_smi : deopt, EQ);
-      __ CompareClassId(box, box_cid, PP);
+      __ CompareClassId(box, box_cid);
       __ b(deopt, NE);
     }
 
@@ -3313,7 +3298,7 @@
   if (value_cid == kSmiCid) {
     __ SmiUntag(out, value);
   } else if (value_cid == kMintCid) {
-    __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP);
+    __ LoadFieldFromOffset(out, value, Mint::value_offset());
   } else if (!CanDeoptimize()) {
     // Type information is not conclusive, but range analysis found
     // the value to be in int64 range. Therefore it must be a smi
@@ -3321,18 +3306,18 @@
     ASSERT(is_truncating());
     Label done;
     __ SmiUntag(out, value);
-    __ TestImmediate(value, kSmiTagMask, PP);
+    __ TestImmediate(value, kSmiTagMask);
     __ b(&done, EQ);
-    __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP);
+    __ LoadFieldFromOffset(out, value, Mint::value_offset());
     __ Bind(&done);
   } else {
     Label done;
     __ SmiUntag(out, value);
-    __ TestImmediate(value, kSmiTagMask, PP);
+    __ TestImmediate(value, kSmiTagMask);
     __ b(&done, EQ);
-    __ CompareClassId(value, kMintCid, PP);
+    __ CompareClassId(value, kMintCid);
     __ b(deopt, NE);
-    __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP);
+    __ LoadFieldFromOffset(out, value, Mint::value_offset());
     __ Bind(&done);
   }
 
@@ -4168,25 +4153,25 @@
   const VRegister result = locs()->out(0).fpu_reg();
 
   __ veor(result, result, result);
-  __ LoadImmediate(temp, 0xffffffff, PP);
-  __ LoadObject(TMP2, Bool::True(), PP);
+  __ LoadImmediate(temp, 0xffffffff);
+  __ LoadObject(TMP2, Bool::True());
 
-  // __ CompareObject(v0, Bool::True(), PP);
+  // __ CompareObject(v0, Bool::True());
   __ CompareRegisters(v0, TMP2);
   __ csel(TMP, temp, ZR, EQ);
   __ vinsw(result, 0, TMP);
 
-  // __ CompareObject(v1, Bool::True(), PP);
+  // __ CompareObject(v1, Bool::True());
   __ CompareRegisters(v1, TMP2);
   __ csel(TMP, temp, ZR, EQ);
   __ vinsw(result, 1, TMP);
 
-  // __ CompareObject(v2, Bool::True(), PP);
+  // __ CompareObject(v2, Bool::True());
   __ CompareRegisters(v2, TMP2);
   __ csel(TMP, temp, ZR, EQ);
   __ vinsw(result, 2, TMP);
 
-  // __ CompareObject(v3, Bool::True(), PP);
+  // __ CompareObject(v3, Bool::True());
   __ CompareRegisters(v3, TMP2);
   __ csel(TMP, temp, ZR, EQ);
   __ vinsw(result, 3, TMP);
@@ -4226,8 +4211,8 @@
   }
 
   __ tst(result, Operand(result));
-  __ LoadObject(result, Bool::True(), PP);
-  __ LoadObject(TMP, Bool::False(), PP);
+  __ LoadObject(result, Bool::True());
+  __ LoadObject(TMP, Bool::False());
   __ csel(result, TMP, result, EQ);
 }
 
@@ -4289,8 +4274,8 @@
     __ vmov(result, mask);
   }
 
-  __ CompareObject(flag, Bool::True(), PP);
-  __ LoadImmediate(TMP, 0xffffffff, PP);
+  __ CompareObject(flag, Bool::True());
+  __ LoadImmediate(TMP, 0xffffffff);
   __ csel(TMP, TMP, ZR, EQ);
   switch (op_kind()) {
     case MethodRecognizer::kInt32x4WithFlagX:
@@ -4469,7 +4454,7 @@
     __ b(&done);
 
     __ Bind(&returns_nan);
-    __ LoadDImmediate(result, NAN, PP);
+    __ LoadDImmediate(result, NAN);
     __ b(&done);
 
     __ Bind(&are_equal);
@@ -4480,7 +4465,7 @@
     // - max -> left is negative ? right : left
     // Check the sign bit.
     __ fmovrd(TMP, left);  // Sign bit is in bit 63 of TMP.
-    __ CompareImmediate(TMP, 0, PP);
+    __ CompareImmediate(TMP, 0);
     if (is_min) {
       ASSERT(left == result);
       __ b(&done, LT);
@@ -4633,7 +4618,7 @@
   const Register value_obj = locs()->in(0).reg();
   ASSERT(result == R0);
   ASSERT(result != value_obj);
-  __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset(), PP);
+  __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset());
 
   Label do_call, done;
   // First check for NaN. Checking for minint after the conversion doesn't work
@@ -4645,7 +4630,7 @@
   // Overflow is signaled with minint.
 
   // Check for overflow and that it fits into Smi.
-  __ CompareImmediate(result, 0xC000000000000000, PP);
+  __ CompareImmediate(result, 0xC000000000000000);
   __ b(&do_call, MI);
   __ SmiTag(result);
   if (FLAG_throw_on_javascript_int_overflow) {
@@ -4695,7 +4680,7 @@
 
   __ fcvtzds(result, value);
   // Check for overflow and that it fits into Smi.
-  __ CompareImmediate(result, 0xC000000000000000, PP);
+  __ CompareImmediate(result, 0xC000000000000000);
   __ b(deopt, MI);
   __ SmiTag(result);
   if (FLAG_throw_on_javascript_int_overflow) {
@@ -4803,7 +4788,7 @@
 
   Label skip_call, try_sqrt, check_base, return_nan, do_pow;
   __ fmovdd(saved_base, base);
-  __ LoadDImmediate(result, 1.0, PP);
+  __ LoadDImmediate(result, 1.0);
   // exponent == 0.0 -> return 1.0;
   __ fcmpdz(exp);
   __ b(&check_base, VS);  // NaN -> check base.
@@ -4815,13 +4800,13 @@
   __ b(&return_base, EQ);
 
   // exponent == 2.0 ?
-  __ LoadDImmediate(VTMP, 2.0, PP);
+  __ LoadDImmediate(VTMP, 2.0);
   __ fcmpd(exp, VTMP);
   Label return_base_times_2;
   __ b(&return_base_times_2, EQ);
 
   // exponent == 3.0 ?
-  __ LoadDImmediate(VTMP, 3.0, PP);
+  __ LoadDImmediate(VTMP, 3.0);
   __ fcmpd(exp, VTMP);
   __ b(&check_base, NE);
 
@@ -4849,21 +4834,21 @@
   __ b(&try_sqrt, VC);  // // Neither 'exp' nor 'base' is NaN.
 
   __ Bind(&return_nan);
-  __ LoadDImmediate(result, NAN, PP);
+  __ LoadDImmediate(result, NAN);
   __ b(&skip_call);
 
   Label return_zero;
   __ Bind(&try_sqrt);
 
   // Before calling pow, check if we could use sqrt instead of pow.
-  __ LoadDImmediate(result, kNegInfinity, PP);
+  __ LoadDImmediate(result, kNegInfinity);
 
   // base == -Infinity -> call pow;
   __ fcmpd(saved_base, result);
   __ b(&do_pow, EQ);
 
   // exponent == 0.5 ?
-  __ LoadDImmediate(result, 0.5, PP);
+  __ LoadDImmediate(result, 0.5);
   __ fcmpd(exp, result);
   __ b(&do_pow, NE);
 
@@ -4875,7 +4860,7 @@
   __ b(&skip_call);
 
   __ Bind(&return_zero);
-  __ LoadDImmediate(result, 0.0, PP);
+  __ LoadDImmediate(result, 0.0);
   __ b(&skip_call);
 
   __ Bind(&do_pow);
@@ -4990,7 +4975,7 @@
 
     // Check the corner case of dividing the 'MIN_SMI' with -1, in which
     // case we cannot tag the result.
-    __ CompareImmediate(result_div, 0x4000000000000000, PP);
+    __ CompareImmediate(result_div, 0x4000000000000000);
     __ b(deopt, EQ);
     // result_mod <- left - right * result_div.
     __ msub(result_mod, TMP, result_div, result_mod);
@@ -5069,7 +5054,7 @@
                                         ICData::kDeoptCheckClass,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
   if (IsNullCheck()) {
-    __ CompareObject(locs()->in(0).reg(), Object::null_object(), PP);
+    __ CompareObject(locs()->in(0).reg(), Object::null_object());
     ASSERT(DeoptIfNull() || DeoptIfNotNull());
     Condition cond = DeoptIfNull() ? EQ : NE;
     __ b(deopt, cond);
@@ -5088,12 +5073,12 @@
     __ tsti(value, Immediate(kSmiTagMask));
     __ b(deopt, EQ);
   }
-  __ LoadClassId(temp, value, PP);
+  __ LoadClassId(temp, value);
 
   if (IsDenseSwitch()) {
     ASSERT(cids_[0] < cids_[cids_.length() - 1]);
-    __ AddImmediate(temp, temp, -cids_[0], PP);
-    __ CompareImmediate(temp, cids_[cids_.length() - 1] - cids_[0], PP);
+    __ AddImmediate(temp, temp, -cids_[0]);
+    __ CompareImmediate(temp, cids_[cids_.length() - 1] - cids_[0]);
     __ b(deopt, HI);
 
     intptr_t mask = ComputeCidMask();
@@ -5101,9 +5086,9 @@
       // Only need mask if there are missing numbers in the range.
       ASSERT(cids_.length() > 2);
       Register mask_reg = locs()->temp(1).reg();
-      __ LoadImmediate(mask_reg, 1, PP);
+      __ LoadImmediate(mask_reg, 1);
       __ lslv(mask_reg, mask_reg, temp);
-      __ TestImmediate(mask_reg, mask, PP);
+      __ TestImmediate(mask_reg, mask);
       __ b(deopt, EQ);
     }
 
@@ -5116,7 +5101,7 @@
     for (intptr_t i = 0; i < num_checks; i++) {
       const intptr_t cid = sorted_ic_data[i].cid;
       ASSERT(cid != kSmiCid);
-      __ CompareImmediate(temp, cid, PP);
+      __ CompareImmediate(temp, cid);
       if (i == (num_checks - 1)) {
         __ b(deopt, NE);
       } else {
@@ -5142,7 +5127,7 @@
 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register value = locs()->in(0).reg();
   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
-  __ CompareImmediate(value, Smi::RawValue(cid_), PP);
+  __ CompareImmediate(value, Smi::RawValue(cid_));
   __ b(deopt, NE);
 }
 
@@ -5211,7 +5196,7 @@
   if (index_loc.IsConstant()) {
     const Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
-    __ CompareImmediate(length, reinterpret_cast<int64_t>(index.raw()), PP);
+    __ CompareImmediate(length, reinterpret_cast<int64_t>(index.raw()));
     __ b(deopt, LS);
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
@@ -5220,7 +5205,7 @@
       __ tst(index, Operand(index));
       __ b(deopt, MI);
     } else {
-      __ CompareImmediate(index, reinterpret_cast<int64_t>(length.raw()), PP);
+      __ CompareImmediate(index, reinterpret_cast<int64_t>(length.raw()));
       __ b(deopt, CS);
     }
   } else {
@@ -5536,10 +5521,10 @@
   const Register result = locs()->out(0).reg();
   Label done;
   __ Bind(&is_false);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ b(&done);
   __ Bind(&is_true);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -5567,8 +5552,8 @@
   const Register value = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
 
-  __ LoadObject(result, Bool::True(), PP);
-  __ LoadObject(TMP, Bool::False(), PP);
+  __ LoadObject(result, Bool::True());
+  __ LoadObject(TMP, Bool::False());
   __ CompareRegisters(result, value);
   __ csel(result, TMP, result, EQ);
 }
@@ -5582,12 +5567,11 @@
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Isolate* isolate = compiler->isolate();
-  StubCode* stub_code = isolate->stub_code();
   const Code& stub = Code::Handle(isolate,
-                                  stub_code->GetAllocationStubForClass(cls()));
-  const ExternalLabel label(stub.EntryPoint());
+                                  StubCode::GetAllocationStubForClass(cls()));
+  const StubEntry stub_entry(stub);
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   compiler->AddStubCallTarget(stub);
@@ -5597,9 +5581,8 @@
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
-  compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
+  compiler->GenerateCall(
+      token_pos(), *StubCode::DebugStepCheck_entry(), stub_kind_, locs());
 }
 
 
@@ -5618,7 +5601,7 @@
 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register typed_data = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ Push(typed_data);
   compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
                                 deopt_id(),
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 2865b26..2e02c21 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -818,7 +818,6 @@
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
   const bool is_leaf_call =
       (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
-  StubCode* stub_code = compiler->isolate()->stub_code();
 
   // Push the result place holder initialized to NULL.
   __ PushObject(Object::null_object());
@@ -831,11 +830,11 @@
   }
   __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function())));
   __ movl(EDX, Immediate(argc_tag));
-  const ExternalLabel* stub_entry = (is_bootstrap_native() || is_leaf_call) ?
-      &stub_code->CallBootstrapCFunctionLabel() :
-      &stub_code->CallNativeCFunctionLabel();
+  const StubEntry* stub_entry = (is_bootstrap_native() || is_leaf_call) ?
+      StubCode::CallBootstrapCFunction_entry() :
+      StubCode::CallNativeCFunction_entry();
   compiler->GenerateCall(token_pos(),
-                         stub_entry,
+                         *stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   __ popl(result);
@@ -1650,7 +1649,6 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     Isolate* isolate = compiler->isolate();
-    StubCode* stub_code = isolate->stub_code();
 
     if (Assembler::EmittingComments()) {
       __ Comment("%s slow path allocation of %s",
@@ -1659,8 +1657,8 @@
     }
     __ Bind(entry_label());
     const Code& stub =
-        Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
-    const ExternalLabel label(stub.EntryPoint());
+        Code::Handle(isolate, StubCode::GetAllocationStubForClass(cls_));
+    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction_->locs();
 
@@ -1668,9 +1666,10 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
+                           stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
+    compiler->AddStubCallTarget(stub);
     __ MoveRegister(result_, EAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -2053,7 +2052,8 @@
   // Object end address in EBX.
   __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump,
                       EAX,  // instance
-                      EBX);  // end address
+                      EBX,  // end address
+                      EDI);  // temp
 
   // Store the type argument field.
   __ InitializeFieldNoBarrier(EAX,
@@ -2128,15 +2128,10 @@
   }
 
   __ Bind(&slow_path);
-  Isolate* isolate = compiler->isolate();
-  const Code& stub = Code::Handle(
-      isolate, isolate->stub_code()->GetAllocateArrayStub());
-  const ExternalLabel label(stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateArray_entry(),
                          RawPcDescriptors::kOther,
                          locs());
-  compiler->AddStubCallTarget(stub);
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2379,10 +2374,11 @@
     bool opt) const {
   ASSERT(opt);
   const intptr_t kNumInputs = 0;
-  const intptr_t kNumTemps = 1;
+  const intptr_t kNumTemps = 2;
   LocationSummary* locs = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   locs->set_temp(0, Location::RegisterLocation(ECX));
+  locs->set_temp(1, Location::RegisterLocation(EDI));
   locs->set_out(0, Location::RegisterLocation(EAX));
   return locs;
 }
@@ -2404,10 +2400,8 @@
     compiler->SaveLiveRegisters(locs);
 
     __ movl(EDX, Immediate(instruction_->num_context_variables()));
-    StubCode* stub_code = compiler->isolate()->stub_code();
-    const ExternalLabel label(stub_code->AllocateContextEntryPoint());
     compiler->GenerateCall(instruction_->token_pos(),
-                           &label,
+                           *StubCode::AllocateContext_entry(),
                            RawPcDescriptors::kOther,
                            locs);
     ASSERT(instruction_->locs()->out(0).reg() == EAX);
@@ -2424,6 +2418,7 @@
     FlowGraphCompiler* compiler) {
   ASSERT(compiler->is_optimizing());
   Register temp = locs()->temp(0).reg();
+  Register temp2 = locs()->temp(1).reg();
   Register result = locs()->out(0).reg();
   // Try allocate the object.
   AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this);
@@ -2433,7 +2428,8 @@
   __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(),
                       Assembler::kFarJump,
                       result,  // instance
-                      temp);  // end address
+                      temp,  // end address
+                      temp2);  // temp
 
   // Setup up number of context variables field.
   __ movl(FieldAddress(result, Context::num_variables_offset()),
@@ -2460,10 +2456,8 @@
   ASSERT(locs()->out(0).reg() == EAX);
 
   __ movl(EDX, Immediate(num_context_variables()));
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->AllocateContextEntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateContext_entry(),
                          RawPcDescriptors::kOther,
                          locs());
 }
@@ -2572,11 +2566,14 @@
 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone,
                                                               bool opt) const {
   const intptr_t kNumInputs = 0;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = opt ? 0 : 1;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs,
                           kNumTemps,
                           LocationSummary::kCallOnSlowPath);
+  if (!opt) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
   return summary;
 }
 
@@ -2634,8 +2631,13 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  __ cmpl(ESP,
-          Address::Absolute(Isolate::Current()->stack_limit_address()));
+  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()));
+  }
   __ j(BELOW_EQUAL, slow_path->entry_label());
   if (compiler->CanOSRFunction() && in_loop()) {
     // In unoptimized code check the usage counter to trigger OSR at loop
@@ -3324,10 +3326,11 @@
 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = 1;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_temp(0, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -3342,7 +3345,7 @@
       this,
       compiler->BoxClassFor(from_representation()),
       out_reg,
-      kNoRegister);
+      locs()->temp(0).reg());
 
   switch (from_representation()) {
     case kUnboxedDouble:
@@ -3490,7 +3493,7 @@
 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps,
       ValueFitsSmi() ? LocationSummary::kNoCall
@@ -3499,6 +3502,9 @@
       (from_representation() == kUnboxedUint32);
   summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
                                           : Location::WritableRegister());
+  if (!ValueFitsSmi()) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
   summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
                                      : Location::RequiresRegister());
   return summary;
@@ -3526,7 +3532,7 @@
     // on the slow path.
     locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
     BoxAllocationSlowPath::Allocate(
-        compiler, this, compiler->mint_class(), out, kNoRegister);
+        compiler, this, compiler->mint_class(), out, locs()->temp(0).reg());
     __ movl(FieldAddress(out, Mint::value_offset()), value);
     if (from_representation() == kUnboxedInt32) {
       __ sarl(value, Immediate(31));  // Sign extend.
@@ -3601,7 +3607,7 @@
   __ subl(value_lo, Immediate(0x40000000));
 
   BoxAllocationSlowPath::Allocate(
-      compiler, this, compiler->mint_class(), out_reg, kNoRegister);
+      compiler, this, compiler->mint_class(), out_reg, locs()->temp(0).reg());
   __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
   __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
   __ Bind(&done);
@@ -3708,7 +3714,7 @@
                                                          bool opt) const {
   const bool might_box = (representation() == kTagged) && !can_pack_into_smi();
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = might_box ? 1 : 0;
+  const intptr_t kNumTemps = might_box ? 2 : 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps,
       might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
@@ -3719,6 +3725,7 @@
                                           : Location::RequiresRegister());
   if (might_box) {
     summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
   }
 
   if (representation() == kUnboxedMint) {
@@ -3798,6 +3805,7 @@
     } else {
       // If the value cannot fit in a smi then allocate a mint box for it.
       Register temp = locs()->temp(0).reg();
+      Register temp2 = locs()->temp(1).reg();
       // Temp register needs to be manually preserved on allocation slow-path.
       locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32);
 
@@ -3809,7 +3817,7 @@
       __ testl(temp, Immediate(0xC0000000));
       __ j(ZERO, &done);
       BoxAllocationSlowPath::Allocate(
-          compiler, this, compiler->mint_class(), result, kNoRegister);
+          compiler, this, compiler->mint_class(), result, temp2);
       __ movl(FieldAddress(result, Mint::value_offset()), temp);
       __ movl(FieldAddress(result, Mint::value_offset() + kWordSize),
               Immediate(0));
@@ -6802,12 +6810,11 @@
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Isolate* isolate = compiler->isolate();
-  StubCode* stub_code = isolate->stub_code();
   const Code& stub = Code::Handle(isolate,
-                                  stub_code->GetAllocationStubForClass(cls()));
-  const ExternalLabel label(stub.EntryPoint());
+                                  StubCode::GetAllocationStubForClass(cls()));
+  const StubEntry stub_entry(stub);
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   compiler->AddStubCallTarget(stub);
@@ -6817,9 +6824,10 @@
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
-  compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
+  compiler->GenerateCall(token_pos(),
+                         *StubCode::DebugStepCheck_entry(),
+                         stub_kind_,
+                         locs());
 }
 
 
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 07a8242..df32f00 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -993,10 +993,9 @@
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
   const bool is_leaf_call =
     (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel* stub_entry;
+  const StubEntry* stub_entry = NULL;
   if (is_bootstrap_native() || is_leaf_call) {
-    stub_entry = &stub_code->CallBootstrapCFunctionLabel();
+    stub_entry = StubCode::CallBootstrapCFunction_entry();
 #if defined(USING_SIMULATOR)
     entry = Simulator::RedirectExternalReference(
         entry, Simulator::kBootstrapNativeCall, function().NumParameters());
@@ -1005,7 +1004,7 @@
     // In the case of non bootstrap native methods the CallNativeCFunction
     // stub generates the redirection address when running under the simulator
     // and hence we do not change 'entry' here.
-    stub_entry = &stub_code->CallNativeCFunctionLabel();
+    stub_entry = StubCode::CallNativeCFunction_entry();
 #if defined(USING_SIMULATOR)
     if (!function().IsNativeAutoSetupScope()) {
       entry = Simulator::RedirectExternalReference(
@@ -1016,7 +1015,7 @@
   __ LoadImmediate(T5, entry);
   __ LoadImmediate(A1, argc_tag);
   compiler->GenerateCall(token_pos(),
-                         stub_entry,
+                         *stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   __ Pop(result);
@@ -1035,6 +1034,7 @@
 
 
 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler->is_optimizing());
   Register char_code = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
@@ -1838,7 +1838,6 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     Isolate* isolate = compiler->isolate();
-    StubCode* stub_code = isolate->stub_code();
 
     if (Assembler::EmittingComments()) {
       __ Comment("%s slow path allocation of %s",
@@ -1847,17 +1846,18 @@
     }
     __ Bind(entry_label());
     const Code& stub =
-        Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
-    const ExternalLabel label(stub.EntryPoint());
+        Code::Handle(isolate, StubCode::GetAllocationStubForClass(cls_));
+    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction_->locs();
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
+                           stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
+    compiler->AddStubCallTarget(stub);
     if (result_ != V0) {
       __ mov(result_, V0);
     }
@@ -2246,15 +2246,10 @@
   }
 
   __ Bind(&slow_path);
-  Isolate* isolate = compiler->isolate();
-  const Code& stub = Code::Handle(
-      isolate, isolate->stub_code()->GetAllocateArrayStub());
-  const ExternalLabel label(stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateArray_entry(),
                          RawPcDescriptors::kOther,
                          locs());
-  compiler->AddStubCallTarget(stub);
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2500,10 +2495,8 @@
     compiler->SaveLiveRegisters(locs);
 
     __ LoadImmediate(T1, instruction_->num_context_variables());
-    StubCode* stub_code = compiler->isolate()->stub_code();
-    const ExternalLabel label(stub_code->AllocateContextEntryPoint());
     compiler->GenerateCall(instruction_->token_pos(),
-                           &label,
+                           *StubCode::AllocateContext_entry(),
                            RawPcDescriptors::kOther,
                            locs);
     ASSERT(instruction_->locs()->out(0).reg() == V0);
@@ -2559,10 +2552,8 @@
 
   __ Comment("AllocateContextInstr");
   __ LoadImmediate(T1, num_context_variables());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->AllocateContextEntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateContext_entry(),
                          RawPcDescriptors::kOther,
                          locs());
 }
@@ -2752,8 +2743,13 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
-  __ lw(CMPRES1, Address(TMP));
+  if (compiler->is_optimizing()) {
+    __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
+    __ lw(CMPRES1, Address(TMP));
+  } else {
+    __ LoadIsolate(TMP);
+    __ lw(CMPRES1, Address(TMP, Isolate::stack_limit_offset()));
+  }
   __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label());
   if (compiler->CanOSRFunction() && in_loop()) {
     Register temp = locs()->temp(0).reg();
@@ -5544,12 +5540,11 @@
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Comment("AllocateObjectInstr");
   Isolate* isolate = compiler->isolate();
-  StubCode* stub_code = isolate->stub_code();
   const Code& stub = Code::Handle(isolate,
-                                  stub_code->GetAllocationStubForClass(cls()));
-  const ExternalLabel label(stub.EntryPoint());
+                                  StubCode::GetAllocationStubForClass(cls()));
+  const StubEntry stub_entry(stub);
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   compiler->AddStubCallTarget(stub);
@@ -5559,9 +5554,8 @@
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
-  compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
+  compiler->GenerateCall(
+      token_pos(), *StubCode::DebugStepCheck_entry(), stub_kind_, locs());
 }
 
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index ec0bbc7..84afa6f 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -56,7 +56,7 @@
     if (value.IsRegister()) {
       __ pushq(value.reg());
     } else if (value.IsConstant()) {
-      __ PushObject(value.constant(), PP);
+      __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
       __ pushq(value.ToStackSlotAddress());
@@ -97,13 +97,17 @@
   ASSERT(fp_sp_dist <= 0);
   __ movq(RDI, RSP);
   __ subq(RDI, RBP);
-  __ CompareImmediate(RDI, Immediate(fp_sp_dist), PP);
+  __ CompareImmediate(RDI, Immediate(fp_sp_dist));
   __ j(EQUAL, &done, Assembler::kNearJump);
   __ int3();
   __ Bind(&done);
 #endif
-  __ LeaveDartFrame();
+  ASSERT(__ constant_pool_allowed());
+  __ LeaveDartFrame();  // Disallows constant pool use.
   __ ret();
+  // This ReturnInstr may be emitted out of order by the optimizer. The next
+  // block may be a target expecting a properly set constant pool pointer.
+  __ set_constant_pool_allowed(true);
 }
 
 
@@ -183,9 +187,9 @@
   } else {
     __ decq(RDX);
     __ AndImmediate(RDX,
-        Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value)), PP);
+        Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value)));
     if (false_value != 0) {
-      __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value)), PP);
+      __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value)));
     }
   }
 }
@@ -242,7 +246,7 @@
   // The register allocator drops constant definitions that have no uses.
   if (!locs()->out(0).IsInvalid()) {
     Register result = locs()->out(0).reg();
-    __ LoadObject(result, value(), PP);
+    __ LoadObject(result, value());
   }
 }
 
@@ -277,7 +281,7 @@
         if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
           __ xorps(result, result);
         } else {
-          __ LoadObject(TMP, value(), PP);
+          __ LoadObject(TMP, value());
           __ movsd(result, FieldAddress(TMP, Double::value_offset()));
         }
         break;
@@ -330,13 +334,13 @@
   Label done;
 
   if (Isolate::Current()->flags().type_checks()) {
-    __ CompareObject(reg, Bool::True(), PP);
+    __ CompareObject(reg, Bool::True());
     __ j(EQUAL, &done, Assembler::kNearJump);
-    __ CompareObject(reg, Bool::False(), PP);
+    __ CompareObject(reg, Bool::False());
     __ j(EQUAL, &done, Assembler::kNearJump);
   } else {
     ASSERT(Isolate::Current()->flags().asserts());
-    __ CompareObject(reg, Object::null_instance(), PP);
+    __ CompareObject(reg, Object::null_instance());
     __ j(NOT_EQUAL, &done, Assembler::kNearJump);
   }
 
@@ -422,7 +426,7 @@
                          Label* value_is_smi = NULL) {
   Label done;
   if (value_is_smi == NULL) {
-    __ LoadImmediate(value_cid_reg, Immediate(kSmiCid), PP);
+    __ LoadImmediate(value_cid_reg, Immediate(kSmiCid));
   }
   __ testq(value_reg, Immediate(kSmiTagMask));
   if (value_is_smi == NULL) {
@@ -484,10 +488,10 @@
   Condition true_condition = TokenKindToIntCondition(kind);
 
   if (left.IsConstant()) {
-    __ CompareObject(right.reg(), left.constant(), PP);
+    __ CompareObject(right.reg(), left.constant());
     true_condition = FlipCondition(true_condition);
   } else if (right.IsConstant()) {
-    __ CompareObject(left.reg(), right.constant(), PP);
+    __ CompareObject(left.reg(), right.constant());
   } else if (right.IsStackSlot()) {
     __ cmpq(left.reg(), right.ToStackSlotAddress());
   } else {
@@ -551,10 +555,10 @@
   Register result = locs()->out(0).reg();
   Label done;
   __ Bind(&is_false);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ jmp(&done);
   __ Bind(&is_true);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -591,7 +595,7 @@
     ASSERT(right.constant().IsSmi());
     const int64_t imm =
         reinterpret_cast<int64_t>(right.constant().raw());
-    __ TestImmediate(left_reg, Immediate(imm), PP);
+    __ TestImmediate(left_reg, Immediate(imm));
   } else {
     __ testq(left_reg, right.reg());
   }
@@ -679,10 +683,10 @@
   BranchLabels labels = { &is_true, &is_false, &is_false };
   EmitComparisonCode(compiler, labels);
   __ Bind(&is_false);
-  __ LoadObject(result_reg, Bool::False(), PP);
+  __ LoadObject(result_reg, Bool::False());
   __ jmp(&done, Assembler::kNearJump);
   __ Bind(&is_true);
-  __ LoadObject(result_reg, Bool::True(), PP);
+  __ LoadObject(result_reg, Bool::True());
   __ Bind(&done);
 }
 
@@ -740,10 +744,10 @@
   Register result = locs()->out(0).reg();
   Label done;
   __ Bind(&is_false);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ jmp(&done);
   __ Bind(&is_true);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -767,25 +771,22 @@
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
   const bool is_leaf_call =
     (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0;
-  StubCode* stub_code = compiler->isolate()->stub_code();
 
   // Push the result place holder initialized to NULL.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   // Pass a pointer to the first argument in RAX.
   if (!function().HasOptionalParameters()) {
     __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp +
                                function().NumParameters()) * kWordSize));
   } else {
-    __ leaq(RAX,
-            Address(RBP, kFirstLocalSlotFromFp * kWordSize));
+    __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
   }
   __ LoadImmediate(
-      RBX, Immediate(reinterpret_cast<uword>(native_c_function())), PP);
-  __ LoadImmediate(
-      R10, Immediate(argc_tag), PP);
-  const ExternalLabel* stub_entry = (is_bootstrap_native() || is_leaf_call) ?
-      &stub_code->CallBootstrapCFunctionLabel() :
-      &stub_code->CallNativeCFunctionLabel();
+      RBX, Immediate(reinterpret_cast<uword>(native_c_function())));
+  __ LoadImmediate(R10, Immediate(argc_tag));
+  const StubEntry& stub_entry = (is_bootstrap_native() || is_leaf_call) ?
+      *StubCode::CallBootstrapCFunction_entry() :
+      *StubCode::CallNativeCFunction_entry();
   compiler->GenerateCall(token_pos(),
                          stub_entry,
                          RawPcDescriptors::kOther,
@@ -818,10 +819,11 @@
 
 
 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler->is_optimizing());
   Register char_code = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
   __ LoadImmediate(result,
-      Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())), PP);
+      Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
   __ movq(result, Address(result,
                           char_code,
                           TIMES_HALF_WORD_SIZE,  // Char code is a smi.
@@ -926,7 +928,7 @@
   // branch prediction usually working just fine in this case.
   __ testq(object, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &load, Assembler::kNearJump);
-  __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)), PP);
+  __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)));
   __ jmp(&done);
   __ Bind(&load);
   __ LoadClassId(result, object);
@@ -1319,7 +1321,7 @@
         __ StoreIntoObject(array, element_address, value);
       } else if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
-        __ StoreIntoObjectNoBarrier(array, element_address, constant, PP);
+        __ StoreIntoObjectNoBarrier(array, element_address, constant);
       } else {
         Register value = locs()->in(2).reg();
         __ StoreIntoObjectNoBarrier(array, element_address, value);
@@ -1356,14 +1358,14 @@
         ASSERT(locs()->in(2).reg() == RAX);
         Label store_value, store_0xff;
         __ SmiUntag(RAX);
-        __ CompareImmediate(RAX, Immediate(0xFF), PP);
+        __ CompareImmediate(RAX, Immediate(0xFF));
         __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
         // Clamp to 0x0 or 0xFF respectively.
         __ j(GREATER, &store_0xff);
         __ xorq(RAX, RAX);
         __ jmp(&store_value, Assembler::kNearJump);
         __ Bind(&store_0xff);
-        __ LoadImmediate(RAX, Immediate(0xFF), PP);
+        __ LoadImmediate(RAX, Immediate(0xFF));
         __ Bind(&store_value);
         __ movb(element_address, RAX);
       }
@@ -1472,7 +1474,7 @@
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
   if (emit_full_guard) {
-    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(
@@ -1541,12 +1543,12 @@
       if (field_cid != kSmiCid) {
         __ j(ZERO, fail);
         __ LoadClassId(value_cid_reg, value_reg);
-        __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP);
+        __ CompareImmediate(value_cid_reg, Immediate(field_cid));
       }
 
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ j(EQUAL, &ok);
-        __ CompareObject(value_reg, Object::null_object(), PP);
+        __ CompareObject(value_reg, Object::null_object());
       }
 
       __ j(NOT_EQUAL, fail);
@@ -1602,7 +1604,7 @@
 
     Label ok;
 
-    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     __ movsxb(offset_reg, FieldAddress(field_reg,
         Field::guarded_list_length_in_object_offset_offset()));
@@ -1639,8 +1641,7 @@
     __ CompareImmediate(
             FieldAddress(value_reg,
                          field().guarded_list_length_in_object_offset()),
-            Immediate(Smi::RawValue(field().guarded_list_length())),
-            PP);
+            Immediate(Smi::RawValue(field().guarded_list_length())));
     __ j(NOT_EQUAL, deopt);
   }
 }
@@ -1657,7 +1658,6 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     Isolate* isolate = compiler->isolate();
-    StubCode* stub_code = isolate->stub_code();
 
     if (Assembler::EmittingComments()) {
       __ Comment("%s slow path allocation of %s",
@@ -1666,8 +1666,8 @@
     }
     __ Bind(entry_label());
     const Code& stub =
-        Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_));
-    const ExternalLabel label(stub.EntryPoint());
+        Code::Handle(isolate, StubCode::GetAllocationStubForClass(cls_));
+    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction_->locs();
 
@@ -1675,9 +1675,10 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
+                           stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
+    compiler->AddStubCallTarget(stub);
     __ MoveRegister(result_, RAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -1686,13 +1687,14 @@
   static void Allocate(FlowGraphCompiler* compiler,
                        Instruction* instruction,
                        const Class& cls,
-                       Register result) {
+                       Register result,
+                       Register temp) {
     if (compiler->intrinsic_mode()) {
       __ TryAllocate(cls,
                      compiler->intrinsic_slow_path_label(),
                      Assembler::kFarJump,
                      result,
-                     PP);
+                     temp);
     } else {
       BoxAllocationSlowPath* slow_path =
           new BoxAllocationSlowPath(instruction, cls, result);
@@ -1702,7 +1704,7 @@
                      slow_path->entry_label(),
                      Assembler::kFarJump,
                      result,
-                     PP);
+                     temp);
       __ Bind(slow_path->exit_label());
     }
   }
@@ -1758,9 +1760,9 @@
                              Register temp) {
   Label done;
   __ movq(box_reg, FieldAddress(instance_reg, offset));
-  __ CompareObject(box_reg, Object::null_object(), PP);
+  __ CompareObject(box_reg, Object::null_object());
   __ j(NOT_EQUAL, &done);
-  BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg);
+  BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
   __ movq(temp, box_reg);
   __ StoreIntoObject(instance_reg,
                      FieldAddress(instance_reg, offset),
@@ -1798,7 +1800,7 @@
           UNREACHABLE();
       }
 
-      BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp);
+      BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ movq(temp2, temp);
       __ StoreIntoObject(instance_reg,
                          FieldAddress(instance_reg, offset_in_bytes_),
@@ -1842,7 +1844,7 @@
     Label store_float32x4;
     Label store_float64x2;
 
-    __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP);
+    __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
     __ cmpl(FieldAddress(temp, Field::is_nullable_offset()),
             Immediate(kNullCid));
@@ -1928,7 +1930,6 @@
       __ StoreIntoObjectNoBarrier(instance_reg,
                                   FieldAddress(instance_reg, offset_in_bytes_),
                                   locs()->in(1).constant(),
-                                  PP,
                                   is_object_reference_initialization_ ?
                                       Assembler::kEmptyOrSmiOrNull :
                                       Assembler::kHeapObjectOrSmi);
@@ -1985,7 +1986,7 @@
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
 
-  __ LoadObject(temp, field(), PP);
+  __ LoadObject(temp, field());
   if (this->value()->NeedsStoreBuffer()) {
     __ StoreIntoObject(temp,
         FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi());
@@ -2051,7 +2052,8 @@
 
   __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump,
                       RAX,  // instance
-                      RCX);  // end address
+                      RCX,  // end address
+                      R13);  // temp
 
   // RAX: new object start as a tagged pointer.
   // Store the type argument field.
@@ -2071,7 +2073,7 @@
   // data area to be initialized.
   if (num_elements > 0) {
     const intptr_t array_size = instance_size - sizeof(RawArray);
-    __ LoadObject(R12, Object::null_object(), PP);
+    __ LoadObject(R12, Object::null_object());
     __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray)));
     if (array_size < (kInlineArraySize * kWordSize)) {
       intptr_t current_offset = 0;
@@ -2109,7 +2111,7 @@
       Label slow_path, done;
       InlineArrayAllocation(compiler, length, &slow_path, &done);
       __ Bind(&slow_path);
-      __ PushObject(Object::null_object(), PP);  // Make room for the result.
+      __ PushObject(Object::null_object());  // Make room for the result.
       __ pushq(kLengthReg);
       __ pushq(kElemTypeReg);
       compiler->GenerateRuntimeCall(token_pos(),
@@ -2125,15 +2127,10 @@
   }
 
   __ Bind(&slow_path);
-  Isolate* isolate = compiler->isolate();
-  const Code& stub = Code::Handle(
-      isolate, isolate->stub_code()->GetAllocateArrayStub());
-  const ExternalLabel label(stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateArray_entry(),
                          RawPcDescriptors::kOther,
                          locs());
-  compiler->AddStubCallTarget(stub);
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2203,7 +2200,7 @@
     Label load_float32x4;
     Label load_float64x2;
 
-    __ LoadObject(result, Field::ZoneHandle(field()->raw()), PP);
+    __ LoadObject(result, Field::ZoneHandle(field()->raw()));
 
     __ cmpl(FieldAddress(result, Field::is_nullable_offset()),
             Immediate(kNullCid));
@@ -2231,7 +2228,7 @@
     {
       __ Bind(&load_double);
       BoxAllocationSlowPath::Allocate(
-          compiler, this, compiler->double_class(), result);
+          compiler, this, compiler->double_class(), result, temp);
       __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
       __ movsd(value, FieldAddress(temp, Double::value_offset()));
       __ movsd(FieldAddress(result, Double::value_offset()), value);
@@ -2241,7 +2238,7 @@
     {
       __ Bind(&load_float32x4);
       BoxAllocationSlowPath::Allocate(
-          compiler, this, compiler->float32x4_class(), result);
+          compiler, this, compiler->float32x4_class(), result, temp);
       __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
       __ movups(value, FieldAddress(temp, Float32x4::value_offset()));
       __ movups(FieldAddress(result, Float32x4::value_offset()), value);
@@ -2251,7 +2248,7 @@
     {
       __ Bind(&load_float64x2);
       BoxAllocationSlowPath::Allocate(
-          compiler, this, compiler->float64x2_class(), result);
+          compiler, this, compiler->float64x2_class(), result, temp);
       __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
       __ movups(value, FieldAddress(temp, Float64x2::value_offset()));
       __ movups(FieldAddress(result, Float64x2::value_offset()), value);
@@ -2283,8 +2280,8 @@
 
   // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   // A runtime call to instantiate the type is required.
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
-  __ PushObject(type(), PP);
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ PushObject(type());
   __ pushq(instantiator_reg);  // Push instantiator type arguments.
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2326,14 +2323,14 @@
   Label type_arguments_instantiated;
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawInstantiatedRaw(len)) {
-    __ CompareObject(instantiator_reg, Object::null_object(), PP);
+    __ CompareObject(instantiator_reg, Object::null_object());
     __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
   }
 
   // Lookup cache before calling runtime.
   // TODO(fschneider): Consider moving this into a shared stub to reduce
   // generated code size.
-  __ LoadObject(RDI, type_arguments(), PP);
+  __ LoadObject(RDI, type_arguments());
   __ movq(RDI, FieldAddress(RDI, TypeArguments::instantiations_offset()));
   __ leaq(RDI, FieldAddress(RDI, Array::data_offset()));
   // The instantiations cache is initialized with Object::zero_array() and is
@@ -2354,8 +2351,8 @@
   __ Bind(&slow_case);
   // Instantiate non-null type arguments.
   // A runtime call to instantiate the type arguments is required.
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
-  __ PushObject(type_arguments(), PP);
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ PushObject(type_arguments());
   __ pushq(instantiator_reg);  // Push instantiator type arguments.
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2374,10 +2371,11 @@
     bool opt) const {
   ASSERT(opt);
   const intptr_t kNumInputs = 0;
-  const intptr_t kNumTemps = 1;
+  const intptr_t kNumTemps = 2;
   LocationSummary* locs = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   locs->set_temp(0, Location::RegisterLocation(R10));
+  locs->set_temp(1, Location::RegisterLocation(R13));
   locs->set_out(0, Location::RegisterLocation(RAX));
   return locs;
 }
@@ -2398,11 +2396,9 @@
 
     compiler->SaveLiveRegisters(locs);
 
-    __ LoadImmediate(R10, Immediate(instruction_->num_context_variables()), PP);
-    StubCode* stub_code = compiler->isolate()->stub_code();
-    const ExternalLabel label(stub_code->AllocateContextEntryPoint());
+    __ LoadImmediate(R10, Immediate(instruction_->num_context_variables()));
     compiler->GenerateCall(instruction_->token_pos(),
-                           &label,
+                           *StubCode::AllocateContext_entry(),
                            RawPcDescriptors::kOther,
                            locs);
     ASSERT(instruction_->locs()->out(0).reg() == RAX);
@@ -2428,7 +2424,8 @@
   __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(),
                       Assembler::kFarJump,
                       result,  // instance
-                      temp);  // end address
+                      temp,  // end address
+                      locs()->temp(1).reg());
 
   // Setup up number of context variables field.
   __ movq(FieldAddress(result, Context::num_variables_offset()),
@@ -2453,12 +2450,10 @@
 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->temp(0).reg() == R10);
   ASSERT(locs()->out(0).reg() == RAX);
-  StubCode* stub_code = compiler->isolate()->stub_code();
 
-  __ LoadImmediate(R10, Immediate(num_context_variables()), PP);
-  const ExternalLabel label(stub_code->AllocateContextEntryPoint());
+  __ LoadImmediate(R10, Immediate(num_context_variables()));
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         *StubCode::AllocateContext_entry(),
                          RawPcDescriptors::kOther,
                          locs());
 }
@@ -2483,14 +2478,14 @@
   Label call_runtime, no_call;
 
   __ movq(temp, FieldAddress(field, Field::value_offset()));
-  __ CompareObject(temp, Object::sentinel(), PP);
+  __ CompareObject(temp, Object::sentinel());
   __ j(EQUAL, &call_runtime);
 
-  __ CompareObject(temp, Object::transition_sentinel(), PP);
+  __ CompareObject(temp, Object::transition_sentinel());
   __ j(NOT_EQUAL, &no_call);
 
   __ Bind(&call_runtime);
-  __ PushObject(Object::null_object(), PP);  // Make room for (unused) result.
+  __ PushObject(Object::null_object());  // Make room for (unused) result.
   __ pushq(field);
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2518,7 +2513,7 @@
   Register context_value = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
-  __ PushObject(Object::null_object(), PP);  // Make room for the result.
+  __ PushObject(Object::null_object());  // Make room for the result.
   __ pushq(context_value);
   compiler->GenerateRuntimeCall(token_pos(),
                                 deopt_id(),
@@ -2546,7 +2541,7 @@
                                 needs_stacktrace());
 
   // Restore the pool pointer.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
 
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -2592,7 +2587,7 @@
       Register temp = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      __ LoadImmediate(temp, Immediate(flags_address), PP);
+      __ LoadImmediate(temp, Immediate(flags_address));
       __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
     }
     __ Comment("CheckStackOverflowSlowPath");
@@ -2638,15 +2633,20 @@
 
   Register temp = locs()->temp(0).reg();
   // Generate stack overflow check.
-  __ LoadImmediate(
-      temp, Immediate(Isolate::Current()->stack_limit_address()), PP);
-  __ cmpq(RSP, Address(temp, 0));
+  if (compiler->is_optimizing()) {
+    __ LoadImmediate(
+        temp, Immediate(Isolate::Current()->stack_limit_address()));
+    __ cmpq(RSP, Address(temp, 0));
+  } else {
+    __ LoadIsolate(temp);
+    __ cmpq(RSP, Address(temp, Isolate::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
     // stack checks.  Use progressively higher thresholds for more deeply
     // nested loops to attempt to hit outer loops with OSR when possible.
-    __ LoadObject(temp, compiler->parsed_function().function(), PP);
+    __ LoadObject(temp, compiler->parsed_function().function());
     int32_t threshold =
         FLAG_optimization_counter_threshold * (loop_depth() + 1);
     __ cmpl(FieldAddress(temp, Function::usage_counter_offset()),
@@ -2668,9 +2668,9 @@
     ASSERT(overflow != NULL);
     // TODO(zra): This can be tightened to one compare/branch using:
     // overflow = (result + 2^52) > 2^53 with an unsigned comparison.
-    __ CompareImmediate(result, Immediate(-0x20000000000000LL), PP);
+    __ CompareImmediate(result, Immediate(-0x20000000000000LL));
     __ j(LESS, overflow);
-    __ CompareImmediate(result, Immediate(0x20000000000000LL), PP);
+    __ CompareImmediate(result, Immediate(0x20000000000000LL));
     __ j(GREATER, overflow);
   }
 }
@@ -2719,7 +2719,7 @@
     if (obj.IsSmi()) {
       const intptr_t left_int = Smi::Cast(obj).Value();
       if (left_int == 0) {
-        __ CompareImmediate(right, Immediate(0), PP);
+        __ CompareImmediate(right, Immediate(0));
         __ j(NEGATIVE, deopt);
         return;
       }
@@ -2728,7 +2728,7 @@
           !RangeUtils::IsWithin(right_range, 0, max_right - 1);
       if (right_needs_check) {
         __ CompareImmediate(right,
-            Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))), PP);
+            Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
         __ j(ABOVE_EQUAL, deopt);
       }
       __ SmiUntag(right);
@@ -2749,12 +2749,12 @@
           (right_range == NULL) || !right_range->IsPositive();
       if (right_may_be_negative) {
         ASSERT(shift_left->CanDeoptimize());
-        __ CompareImmediate(right, Immediate(0), PP);
+        __ CompareImmediate(right, Immediate(0));
         __ j(NEGATIVE, deopt);
       }
       Label done, is_not_zero;
       __ CompareImmediate(right,
-          Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP);
+          Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))));
       __ j(BELOW, &is_not_zero, Assembler::kNearJump);
       __ xorq(left, left);
       __ jmp(&done, Assembler::kNearJump);
@@ -2770,7 +2770,7 @@
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
       __ CompareImmediate(right,
-          Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP);
+          Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))));
       __ j(ABOVE_EQUAL, deopt);
     }
     // Left is not a constant.
@@ -2903,19 +2903,19 @@
     const int64_t imm = reinterpret_cast<int64_t>(constant.raw());
     switch (op_kind()) {
       case Token::kADD: {
-        __ AddImmediate(left, Immediate(imm), PP);
+        __ AddImmediate(left, Immediate(imm));
         if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kSUB: {
-        __ SubImmediate(left, Immediate(imm), PP);
+        __ SubImmediate(left, Immediate(imm));
         if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
-        __ MulImmediate(left, Immediate(value), PP);
+        __ MulImmediate(left, Immediate(value));
         if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
@@ -2941,17 +2941,17 @@
       }
       case Token::kBIT_AND: {
         // No overflow check.
-        __ AndImmediate(left, Immediate(imm), PP);
+        __ AndImmediate(left, Immediate(imm));
         break;
       }
       case Token::kBIT_OR: {
         // No overflow check.
-        __ OrImmediate(left, Immediate(imm), PP);
+        __ OrImmediate(left, Immediate(imm));
         break;
       }
       case Token::kBIT_XOR: {
         // No overflow check.
-        __ XorImmediate(left, Immediate(imm), PP);
+        __ XorImmediate(left, Immediate(imm));
         break;
       }
 
@@ -3096,7 +3096,7 @@
       __ idivq(right);  //  RAX: quotient, RDX: remainder.
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
-      __ CompareImmediate(result, Immediate(0x4000000000000000), PP);
+      __ CompareImmediate(result, Immediate(0x4000000000000000));
       __ j(EQUAL, deopt);
       __ Bind(&done);
       __ SmiTag(result);
@@ -3176,7 +3176,7 @@
     }
     case Token::kSHR: {
       if (CanDeoptimize()) {
-        __ CompareImmediate(right, Immediate(0), PP);
+        __ CompareImmediate(right, Immediate(0));
         __ j(LESS, deopt);
       }
       __ SmiUntag(right);
@@ -3184,10 +3184,10 @@
       const intptr_t kCountLimit = 0x3F;
       if ((right_range == NULL) ||
           !right_range->OnlyLessThanOrEqualTo(kCountLimit)) {
-        __ CompareImmediate(right, Immediate(kCountLimit), PP);
+        __ CompareImmediate(right, Immediate(kCountLimit));
         Label count_ok;
         __ j(LESS, &count_ok, Assembler::kNearJump);
-        __ LoadImmediate(right, Immediate(kCountLimit), PP);
+        __ LoadImmediate(right, Immediate(kCountLimit));
         __ Bind(&count_ok);
       }
       ASSERT(right == RCX);  // Count must be in RCX
@@ -3265,10 +3265,11 @@
 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = 1;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_temp(0, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -3276,10 +3277,12 @@
 
 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register out_reg = locs()->out(0).reg();
+  Register temp = locs()->temp(0).reg();
   XmmRegister value = locs()->in(0).fpu_reg();
 
   BoxAllocationSlowPath::Allocate(
-      compiler, this, compiler->BoxClassFor(from_representation()), out_reg);
+      compiler, this, compiler->BoxClassFor(from_representation()), out_reg,
+      temp);
   __ movsd(FieldAddress(out_reg, Double::value_offset()), value);
   switch (from_representation()) {
     case kUnboxedDouble:
@@ -3508,7 +3511,7 @@
 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
                                                     bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
   LocationSummary* summary = new(zone) LocationSummary(
       zone,
       kNumInputs,
@@ -3516,6 +3519,9 @@
       ValueFitsSmi() ? LocationSummary::kNoCall
                      : LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresRegister());
+  if (!ValueFitsSmi()) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -3527,10 +3533,11 @@
   __ MoveRegister(out, value);
   __ SmiTag(out);
   if (!ValueFitsSmi()) {
+    const Register temp = locs()->temp(0).reg();
     Label done;
     __ j(NO_OVERFLOW, &done);
     BoxAllocationSlowPath::Allocate(
-        compiler, this, compiler->mint_class(), out);
+        compiler, this, compiler->mint_class(), out, temp);
     __ movq(FieldAddress(out, Mint::value_offset()), value);
     __ Bind(&done);
   }
@@ -3737,7 +3744,7 @@
   XmmRegister v2 = locs()->in(2).fpu_reg();
   XmmRegister v3 = locs()->in(3).fpu_reg();
   ASSERT(v0 == locs()->out(0).fpu_reg());
-  __ AddImmediate(RSP, Immediate(-16), PP);
+  __ AddImmediate(RSP, Immediate(-16));
   __ cvtsd2ss(v0, v0);
   __ movss(Address(RSP, 0), v0);
   __ movsd(v0, v1);
@@ -3750,7 +3757,7 @@
   __ cvtsd2ss(v0, v0);
   __ movss(Address(RSP, 12), v0);
   __ movups(v0, Address(RSP, 0));
-  __ AddImmediate(RSP, Immediate(16), PP);
+  __ AddImmediate(RSP, Immediate(16));
 }
 
 
@@ -4004,47 +4011,47 @@
   switch (op_kind()) {
     case MethodRecognizer::kFloat32x4WithX:
       __ cvtsd2ss(replacement, replacement);
-      __ AddImmediate(RSP, Immediate(-16), PP);
+      __ AddImmediate(RSP, Immediate(-16));
       // Move value to stack.
       __ movups(Address(RSP, 0), value);
       // Write over X value.
       __ movss(Address(RSP, 0), replacement);
       // Move updated value into output register.
       __ movups(replacement, Address(RSP, 0));
-      __ AddImmediate(RSP, Immediate(16), PP);
+      __ AddImmediate(RSP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithY:
       __ cvtsd2ss(replacement, replacement);
-      __ AddImmediate(RSP, Immediate(-16), PP);
+      __ AddImmediate(RSP, Immediate(-16));
       // Move value to stack.
       __ movups(Address(RSP, 0), value);
       // Write over Y value.
       __ movss(Address(RSP, 4), replacement);
       // Move updated value into output register.
       __ movups(replacement, Address(RSP, 0));
-      __ AddImmediate(RSP, Immediate(16), PP);
+      __ AddImmediate(RSP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithZ:
       __ cvtsd2ss(replacement, replacement);
-      __ AddImmediate(RSP, Immediate(-16), PP);
+      __ AddImmediate(RSP, Immediate(-16));
       // Move value to stack.
       __ movups(Address(RSP, 0), value);
       // Write over Z value.
       __ movss(Address(RSP, 8), replacement);
       // Move updated value into output register.
       __ movups(replacement, Address(RSP, 0));
-      __ AddImmediate(RSP, Immediate(16), PP);
+      __ AddImmediate(RSP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithW:
       __ cvtsd2ss(replacement, replacement);
-      __ AddImmediate(RSP, Immediate(-16), PP);
+      __ AddImmediate(RSP, Immediate(-16));
       // Move value to stack.
       __ movups(Address(RSP, 0), value);
       // Write over W value.
       __ movss(Address(RSP, 12), replacement);
       // Move updated value into output register.
       __ movups(replacement, Address(RSP, 0));
-      __ AddImmediate(RSP, Immediate(16), PP);
+      __ AddImmediate(RSP, Immediate(16));
       break;
     default: UNREACHABLE();
   }
@@ -4309,13 +4316,13 @@
   Register v2 = locs()->in(2).reg();
   Register v3 = locs()->in(3).reg();
   XmmRegister result = locs()->out(0).fpu_reg();
-  __ AddImmediate(RSP, Immediate(-4 * kInt32Size), PP);
+  __ AddImmediate(RSP, Immediate(-4 * kInt32Size));
   __ movl(Address(RSP, 0 * kInt32Size), v0);
   __ movl(Address(RSP, 1 * kInt32Size), v1);
   __ movl(Address(RSP, 2 * kInt32Size), v2);
   __ movl(Address(RSP, 3 * kInt32Size), v3);
   __ movups(result, Address(RSP, 0));
-  __ AddImmediate(RSP, Immediate(4 * kInt32Size), PP);
+  __ AddImmediate(RSP, Immediate(4 * kInt32Size));
 }
 
 
@@ -4346,46 +4353,46 @@
   Label y_false, y_done;
   Label z_false, z_done;
   Label w_false, w_done;
-  __ AddImmediate(RSP, Immediate(-16), PP);
+  __ AddImmediate(RSP, Immediate(-16));
 
-  __ CompareObject(v0, Bool::True(), PP);
+  __ CompareObject(v0, Bool::True());
   __ j(NOT_EQUAL, &x_false);
-  __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+  __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
   __ jmp(&x_done);
   __ Bind(&x_false);
-  __ LoadImmediate(temp, Immediate(0x0), PP);
+  __ LoadImmediate(temp, Immediate(0x0));
   __ Bind(&x_done);
   __ movl(Address(RSP, 0), temp);
 
-  __ CompareObject(v1, Bool::True(), PP);
+  __ CompareObject(v1, Bool::True());
   __ j(NOT_EQUAL, &y_false);
-  __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+  __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
   __ jmp(&y_done);
   __ Bind(&y_false);
-  __ LoadImmediate(temp, Immediate(0x0), PP);
+  __ LoadImmediate(temp, Immediate(0x0));
   __ Bind(&y_done);
   __ movl(Address(RSP, 4), temp);
 
-  __ CompareObject(v2, Bool::True(), PP);
+  __ CompareObject(v2, Bool::True());
   __ j(NOT_EQUAL, &z_false);
-  __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+  __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
   __ jmp(&z_done);
   __ Bind(&z_false);
-  __ LoadImmediate(temp, Immediate(0x0), PP);
+  __ LoadImmediate(temp, Immediate(0x0));
   __ Bind(&z_done);
   __ movl(Address(RSP, 8), temp);
 
-  __ CompareObject(v3, Bool::True(), PP);
+  __ CompareObject(v3, Bool::True());
   __ j(NOT_EQUAL, &w_false);
-  __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+  __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
   __ jmp(&w_done);
   __ Bind(&w_false);
-  __ LoadImmediate(temp, Immediate(0x0), PP);
+  __ LoadImmediate(temp, Immediate(0x0));
   __ Bind(&w_done);
   __ movl(Address(RSP, 12), temp);
 
   __ movups(result, Address(RSP, 0));
-  __ AddImmediate(RSP, Immediate(16), PP);
+  __ AddImmediate(RSP, Immediate(16));
 }
 
 
@@ -4406,7 +4413,7 @@
   Register result = locs()->out(0).reg();
   Label done;
   Label non_zero;
-  __ AddImmediate(RSP, Immediate(-16), PP);
+  __ AddImmediate(RSP, Immediate(-16));
   // Move value to stack.
   __ movups(Address(RSP, 0), value);
   switch (op_kind()) {
@@ -4424,13 +4431,13 @@
       break;
     default: UNREACHABLE();
   }
-  __ AddImmediate(RSP, Immediate(16), PP);
+  __ AddImmediate(RSP, Immediate(16));
   __ testl(result, result);
   __ j(NOT_ZERO, &non_zero, Assembler::kNearJump);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ jmp(&done);
   __ Bind(&non_zero);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -4489,43 +4496,43 @@
   Register flag = locs()->in(1).reg();
   Register temp = locs()->temp(0).reg();
   ASSERT(mask == locs()->out(0).fpu_reg());
-  __ AddImmediate(RSP, Immediate(-16), PP);
+  __ AddImmediate(RSP, Immediate(-16));
   // Copy mask to stack.
   __ movups(Address(RSP, 0), mask);
   Label falsePath, exitPath;
-  __ CompareObject(flag, Bool::True(), PP);
+  __ CompareObject(flag, Bool::True());
   __ j(NOT_EQUAL, &falsePath);
   switch (op_kind()) {
     case MethodRecognizer::kInt32x4WithFlagX:
-      __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+      __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
       __ movl(Address(RSP, 0), temp);
       __ jmp(&exitPath);
       __ Bind(&falsePath);
-      __ LoadImmediate(temp, Immediate(0x0), PP);
+      __ LoadImmediate(temp, Immediate(0x0));
       __ movl(Address(RSP, 0), temp);
     break;
     case MethodRecognizer::kInt32x4WithFlagY:
-      __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+      __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
       __ movl(Address(RSP, 4), temp);
       __ jmp(&exitPath);
       __ Bind(&falsePath);
-      __ LoadImmediate(temp, Immediate(0x0), PP);
+      __ LoadImmediate(temp, Immediate(0x0));
       __ movl(Address(RSP, 4), temp);
     break;
     case MethodRecognizer::kInt32x4WithFlagZ:
-      __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+      __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
       __ movl(Address(RSP, 8), temp);
       __ jmp(&exitPath);
       __ Bind(&falsePath);
-      __ LoadImmediate(temp, Immediate(0x0), PP);
+      __ LoadImmediate(temp, Immediate(0x0));
       __ movl(Address(RSP, 8), temp);
     break;
     case MethodRecognizer::kInt32x4WithFlagW:
-      __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
+      __ LoadImmediate(temp, Immediate(0xFFFFFFFF));
       __ movl(Address(RSP, 12), temp);
       __ jmp(&exitPath);
       __ Bind(&falsePath);
-      __ LoadImmediate(temp, Immediate(0x0), PP);
+      __ LoadImmediate(temp, Immediate(0x0));
       __ movl(Address(RSP, 12), temp);
     break;
     default: UNREACHABLE();
@@ -4533,7 +4540,7 @@
   __ Bind(&exitPath);
   // Copy mask back to register.
   __ movups(mask, Address(RSP, 0));
-  __ AddImmediate(RSP, Immediate(16), PP);
+  __ AddImmediate(RSP, Immediate(16));
 }
 
 
@@ -4708,7 +4715,7 @@
     case Token::kBIT_NOT:
       __ notq(value);
       // Remove inverted smi-tag.
-      __ AndImmediate(value, Immediate(~kSmiTagMask), PP);
+      __ AndImmediate(value, Immediate(~kSmiTagMask));
       break;
     default:
       UNREACHABLE();
@@ -4785,7 +4792,7 @@
 
     __ Bind(&returns_nan);
     static double kNaN = NAN;
-    __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN)), PP);
+    __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN)));
     __ movsd(result, Address(temp, 0));
     __ jmp(&done, Assembler::kNearJump);
 
@@ -5086,7 +5093,7 @@
       locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg();
 
   __ xorps(zero_temp, zero_temp);
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP);
+  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)));
   __ movsd(result, FieldAddress(temp, Double::value_offset()));
 
   Label check_base, skip_call;
@@ -5101,14 +5108,14 @@
   __ j(EQUAL, &return_base, Assembler::kNearJump);
 
   // exponent == 2.0 ?
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0)), PP);
+  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0)));
   __ movsd(XMM0, FieldAddress(temp, Double::value_offset()));
   __ comisd(exp, XMM0);
   Label return_base_times_2;
   __ j(EQUAL, &return_base_times_2, Assembler::kNearJump);
 
   // exponent == 3.0 ?
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0)), PP);
+  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0)));
   __ movsd(XMM0, FieldAddress(temp, Double::value_offset()));
   __ comisd(exp, XMM0);
   __ j(NOT_EQUAL, &check_base);
@@ -5143,7 +5150,7 @@
   __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump);
   // Return NaN.
   __ Bind(&return_nan);
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)), PP);
+  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)));
   __ movsd(result, FieldAddress(temp, Double::value_offset()));
   __ jmp(&skip_call);
 
@@ -5151,14 +5158,14 @@
   __ Bind(&try_sqrt);
   // Before calling pow, check if we could use sqrt instead of pow.
   __ LoadObject(temp,
-      Double::ZoneHandle(Double::NewCanonical(kNegInfinity)), PP);
+      Double::ZoneHandle(Double::NewCanonical(kNegInfinity)));
   __ movsd(result, FieldAddress(temp, Double::value_offset()));
   // base == -Infinity -> call pow;
   __ comisd(base, result);
   __ j(EQUAL, &do_pow, Assembler::kNearJump);
 
   // exponent == 0.5 ?
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)), PP);
+  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)));
   __ movsd(result, FieldAddress(temp, Double::value_offset()));
   __ comisd(exp, result);
   __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump);
@@ -5355,7 +5362,7 @@
     __ idivq(right);  //  RAX: quotient, RDX: remainder.
     // Check the corner case of dividing the 'MIN_SMI' with -1, in which
     // case we cannot tag the result.
-    __ CompareImmediate(RAX, Immediate(0x4000000000000000), PP);
+    __ CompareImmediate(RAX, Immediate(0x4000000000000000));
     __ j(EQUAL, deopt);
     __ Bind(&done);
 
@@ -5479,7 +5486,7 @@
                                         licm_hoisted_ ? ICData::kHoisted : 0);
   if (IsNullCheck()) {
     __ CompareObject(locs()->in(0).reg(),
-                     Object::null_object(), PP);
+                     Object::null_object());
     Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL;
     __ j(cond, deopt);
     return;
@@ -5574,7 +5581,7 @@
 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register value = locs()->in(0).reg();
   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
-  __ CompareImmediate(value, Immediate(Smi::RawValue(cid_)), PP);
+  __ CompareImmediate(value, Immediate(Smi::RawValue(cid_)));
   __ j(NOT_ZERO, deopt);
 }
 
@@ -5616,7 +5623,7 @@
     Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
     __ CompareImmediate(
-        length, Immediate(reinterpret_cast<int64_t>(index.raw())), PP);
+        length, Immediate(reinterpret_cast<int64_t>(index.raw())));
     __ j(BELOW_EQUAL, deopt);
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
@@ -5626,7 +5633,7 @@
       __ j(NEGATIVE, deopt);
     } else {
       __ CompareImmediate(
-          index, Immediate(reinterpret_cast<int64_t>(length.raw())), PP);
+          index, Immediate(reinterpret_cast<int64_t>(length.raw())));
       __ j(ABOVE_EQUAL, deopt);
     }
   } else {
@@ -6283,10 +6290,10 @@
   Register result = locs()->out(0).reg();
   Label done;
   __ Bind(&is_false);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ jmp(&done);
   __ Bind(&is_true);
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ Bind(&done);
 }
 
@@ -6319,7 +6326,7 @@
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names()));
-  __ LoadObject(R10, arguments_descriptor, PP);
+  __ LoadObject(R10, arguments_descriptor);
 
   // Function in RAX.
   ASSERT(locs()->in(0).reg() == RAX);
@@ -6362,10 +6369,10 @@
   Register result = locs()->out(0).reg();
 
   Label done;
-  __ LoadObject(result, Bool::True(), PP);
+  __ LoadObject(result, Bool::True());
   __ CompareRegisters(result, value);
   __ j(NOT_EQUAL, &done, Assembler::kNearJump);
-  __ LoadObject(result, Bool::False(), PP);
+  __ LoadObject(result, Bool::False());
   __ Bind(&done);
 }
 
@@ -6378,12 +6385,11 @@
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Isolate* isolate = compiler->isolate();
-  StubCode* stub_code = isolate->stub_code();
   const Code& stub = Code::Handle(isolate,
-                                  stub_code->GetAllocationStubForClass(cls()));
-  const ExternalLabel label(stub.EntryPoint());
+                                  StubCode::GetAllocationStubForClass(cls()));
+  const StubEntry stub_entry(stub);
   compiler->GenerateCall(token_pos(),
-                         &label,
+                         stub_entry,
                          RawPcDescriptors::kOther,
                          locs());
   compiler->AddStubCallTarget(stub);
@@ -6393,9 +6399,7 @@
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  StubCode* stub_code = compiler->isolate()->stub_code();
-  const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
-  __ CallPatchable(&label);
+  __ CallPatchable(*StubCode::DebugStepCheck_entry());
   compiler->AddCurrentDescriptor(stub_kind_, Isolate::kNoDeoptId, token_pos());
   compiler->RecordSafepoint(locs());
 }
@@ -6416,7 +6420,7 @@
 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register typed_data = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ pushq(typed_data);
   compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
                                 deopt_id(),
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index a5b73df..70ce883 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -189,7 +189,8 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, R2, &fall_through);                             \
+  __ MaybeTraceAllocation(cid, R2, &fall_through,                              \
+                          /* inline_isolate = */ false);                       \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
   /* Check that length is a positive Smi. */                                   \
   /* R2: requested array length argument. */                                   \
@@ -206,10 +207,9 @@
   const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \
   __ AddImmediate(R2, fixed_size);                                             \
   __ bic(R2, R2, Operand(kObjectAlignment - 1));                               \
-  Heap* heap = Isolate::Current()->heap();                                     \
-  Heap::Space space = heap->SpaceForAllocation(cid);                           \
-  __ LoadImmediate(R0, heap->TopAddress(space));                               \
-  __ ldr(R0, Address(R0, 0));                                                  \
+  Heap::Space space = Heap::SpaceForAllocation(cid);                           \
+  __ ldr(R3, Address(THR, Thread::heap_offset()));                             \
+  __ ldr(R0, Address(R3, Heap::TopOffset(space)));                             \
                                                                                \
   /* R2: allocation size. */                                                   \
   __ adds(R1, R0, Operand(R2));                                                \
@@ -219,16 +219,15 @@
   /* R0: potential new object start. */                                        \
   /* R1: potential next object start. */                                       \
   /* R2: allocation size. */                                                   \
-  __ LoadImmediate(R3, heap->EndAddress(space));                               \
-  __ ldr(R3, Address(R3, 0));                                                  \
-  __ cmp(R1, Operand(R3));                                                     \
+  /* R3: heap. */                                                              \
+  __ ldr(IP, Address(R3, Heap::EndOffset(space)));                             \
+  __ cmp(R1, Operand(IP));                                                     \
   __ b(&fall_through, CS);                                                     \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ LoadAllocationStatsAddress(R4, cid);                                      \
-  __ LoadImmediate(R3, heap->TopAddress(space));                               \
-  __ str(R1, Address(R3, 0));                                                  \
+  __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false);        \
+  __ str(R1, Address(R3, Heap::TopOffset(space)));                             \
   __ AddImmediate(R0, kHeapObjectTag);                                         \
   /* Initialize the tags. */                                                   \
   /* R0: new object start as a tagged pointer. */                              \
@@ -1661,8 +1660,14 @@
   __ ldrb(R1, Address(R0, R1));
   __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
   __ b(&fall_through, GE);
-  __ LoadImmediate(R0,
-                   reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  const ExternalLabel symbols_label(
+      reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ Push(PP);
+  __ LoadPoolPointer();
+  assembler->set_constant_pool_allowed(true);
+  __ LoadExternalLabel(R0, &symbols_label, kNotPatchable);
+  assembler->set_constant_pool_allowed(false);
+  __ Pop(PP);
   __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ ldr(R0, Address(R0, R1, LSL, 2));
   __ Ret();
@@ -1675,8 +1680,12 @@
   __ ldrh(R1, Address(R0, R1));
   __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
   __ b(&fall_through, GE);
-  __ LoadImmediate(R0,
-                   reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ Push(PP);
+  __ LoadPoolPointer();
+  assembler->set_constant_pool_allowed(true);
+  __ LoadExternalLabel(R0, &symbols_label, kNotPatchable);
+  assembler->set_constant_pool_allowed(false);
+  __ Pop(PP);
   __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ ldr(R0, Address(R0, R1, LSL, 2));
   __ Ret();
@@ -1771,12 +1780,10 @@
   __ AddImmediate(length_reg, fixed_size);
   __ bic(length_reg, length_reg, Operand(kObjectAlignment - 1));
 
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
   const intptr_t cid = kOneByteStringCid;
-  Heap::Space space = heap->SpaceForAllocation(cid);
-  __ LoadImmediate(R3, heap->TopAddress(space));
-  __ ldr(R0, Address(R3, 0));
+  Heap::Space space = Heap::SpaceForAllocation(cid);
+  __ ldr(R3, Address(THR, Thread::heap_offset()));
+  __ ldr(R0, Address(R3, Heap::TopOffset(space)));
 
   // length_reg: allocation size.
   __ adds(R1, R0, Operand(length_reg));
@@ -1786,16 +1793,15 @@
   // R0: potential new object start.
   // R1: potential next object start.
   // R2: allocation size.
-  // R3: heap->TopAddress(space).
-  __ LoadImmediate(R7, heap->EndAddress(space));
-  __ ldr(R7, Address(R7, 0));
+  // R3: heap.
+  __ ldr(R7, Address(R3, Heap::EndOffset(space)));
   __ cmp(R1, Operand(R7));
   __ b(&fail, CS);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ LoadAllocationStatsAddress(R4, cid);
-  __ str(R1, Address(R3, 0));
+  __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false);
+  __ str(R1, Address(R3, Heap::TopOffset(space)));
   __ AddImmediate(R0, kHeapObjectTag);
 
   // Initialize the tags.
@@ -2030,8 +2036,7 @@
 // On stack: user tag (+0).
 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
   // R1: Isolate.
-  Isolate* isolate = Isolate::Current();
-  __ LoadImmediate(R1, reinterpret_cast<uword>(isolate));
+  __ LoadIsolate(R1);
   // R0: Current user tag.
   __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
   // R2: UserTag.
@@ -2047,21 +2052,15 @@
 
 
 void Intrinsifier::UserTag_defaultTag(Assembler* assembler) {
-  Isolate* isolate = Isolate::Current();
-  // Set return value to default tag address.
-  __ LoadImmediate(R0,
-         reinterpret_cast<uword>(isolate) + Isolate::default_tag_offset());
-  __ ldr(R0, Address(R0, 0));
+  __ LoadIsolate(R0);
+  __ ldr(R0, Address(R0, Isolate::default_tag_offset()));
   __ Ret();
 }
 
 
 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) {
-  // R1: Default tag address.
-  Isolate* isolate = Isolate::Current();
-  __ LoadImmediate(R1, reinterpret_cast<uword>(isolate));
-  // Set return value to Isolate::current_tag_.
-  __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
+  __ LoadIsolate(R0);
+  __ ldr(R0, Address(R0, Isolate::current_tag_offset()));
   __ Ret();
 }
 
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index 8cbb1ba..4d27700 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -58,28 +58,28 @@
     __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
 
     // Null value is valid for any type.
-    __ CompareObject(R2, Object::null_object(), PP);
+    __ CompareObject(R2, Object::null_object());
     __ b(&checked_ok, EQ);
 
     __ ldr(R1, Address(SP, 2 * kWordSize));  // Array.
     __ ldr(R1, FieldAddress(R1, type_args_field_offset));
 
     // R1: Type arguments of array.
-    __ CompareObject(R1, Object::null_object(), PP);
+    __ CompareObject(R1, Object::null_object());
     __ b(&checked_ok, EQ);
 
     // Check if it's dynamic.
     // Get type at index 0.
     __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0)));
-    __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()), PP);
+    __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()));
     __ b(&checked_ok, EQ);
 
     // Check for int and num.
     __ tsti(R2, Immediate(Immediate(kSmiTagMask)));  // Value is Smi?
     __ b(&fall_through, NE);  // Non-smi value.
-    __ CompareObject(R0, Type::ZoneHandle(Type::IntType()), PP);
+    __ CompareObject(R0, Type::ZoneHandle(Type::IntType()));
     __ b(&checked_ok, EQ);
-    __ CompareObject(R0, Type::ZoneHandle(Type::Number()), PP);
+    __ CompareObject(R0, Type::ZoneHandle(Type::Number()));
     __ b(&fall_through, NE);
     __ Bind(&checked_ok);
   }
@@ -119,7 +119,7 @@
   // Try allocating in new space.
   const Class& cls = Class::Handle(
       Isolate::Current()->object_store()->growable_object_array_class());
-  __ TryAllocate(cls, &fall_through, R0, R1, kNoPP);
+  __ TryAllocate(cls, &fall_through, R0, R1);
 
   // Store backing array object in growable array object.
   __ ldr(R1, Address(SP, kArrayOffset));  // Data argument.
@@ -138,7 +138,7 @@
       R1);
 
   // Set the length field in the growable array object to 0.
-  __ LoadImmediate(R1, 0, kNoPP);
+  __ LoadImmediate(R1, 0);
   __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
   __ ret();  // Returns the newly allocated object in R0.
 
@@ -176,7 +176,7 @@
   __ StoreIntoObject(R2,
                      FieldAddress(R1, Array::data_offset()),
                      R0);
-  __ LoadObject(R0, Object::null_object(), PP);
+  __ LoadObject(R0, Object::null_object());
   __ ret();
   __ Bind(&fall_through);
 }
@@ -198,7 +198,8 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, R2, kNoPP, &fall_through);                      \
+  __ MaybeTraceAllocation(cid, R2, &fall_through,                              \
+                          /* inline_isolate = */ false);                       \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
   /* Check that length is a positive Smi. */                                   \
   /* R2: requested array length argument. */                                   \
@@ -209,16 +210,15 @@
   __ SmiUntag(R2);                                                             \
   /* Check for maximum allowed length. */                                      \
   /* R2: untagged array length. */                                             \
-  __ CompareImmediate(R2, max_len, kNoPP);                                     \
+  __ CompareImmediate(R2, max_len);                                            \
   __ b(&fall_through, GT);                                                     \
   __ LslImmediate(R2, R2, scale_shift);                                        \
   const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \
-  __ AddImmediate(R2, R2, fixed_size, kNoPP);                                  \
+  __ AddImmediate(R2, R2, fixed_size);                                         \
   __ andi(R2, R2, Immediate(~(kObjectAlignment - 1)));                         \
-  Heap* heap = Isolate::Current()->heap();                                     \
-  Heap::Space space = heap->SpaceForAllocation(cid);                           \
-  __ LoadImmediate(R0, heap->TopAddress(space), kNoPP);                        \
-  __ ldr(R0, Address(R0, 0));                                                  \
+  Heap::Space space = Heap::SpaceForAllocation(cid);                           \
+  __ ldr(R3, Address(THR, Thread::heap_offset()));                             \
+  __ ldr(R0, Address(R3, Heap::TopOffset(space)));                             \
                                                                                \
   /* R2: allocation size. */                                                   \
   __ adds(R1, R0, Operand(R2));                                                \
@@ -228,28 +228,28 @@
   /* R0: potential new object start. */                                        \
   /* R1: potential next object start. */                                       \
   /* R2: allocation size. */                                                   \
-  __ LoadImmediate(R3, heap->EndAddress(space), kNoPP);                        \
-  __ ldr(R3, Address(R3, 0));                                                  \
-  __ cmp(R1, Operand(R3));                                                     \
+  /* R3: heap. */                                                              \
+  __ ldr(R4, Address(R3, Heap::EndOffset(space)));                             \
+  __ cmp(R1, Operand(R4));                                                     \
   __ b(&fall_through, CS);                                                     \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ LoadImmediate(R3, heap->TopAddress(space), kNoPP);                        \
-  __ str(R1, Address(R3, 0));                                                  \
-  __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP);                              \
-  __ UpdateAllocationStatsWithSize(cid, R2, kNoPP, space);                     \
+  __ str(R1, Address(R3, Heap::TopOffset(space)));                             \
+  __ AddImmediate(R0, R0, kHeapObjectTag);                                     \
+  __ UpdateAllocationStatsWithSize(cid, R2, space,                             \
+                                   /* inline_isolate = */ false);              \
   /* Initialize the tags. */                                                   \
   /* R0: new object start as a tagged pointer. */                              \
   /* R1: new object end address. */                                            \
   /* R2: allocation size. */                                                   \
   {                                                                            \
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP);           \
+    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);                  \
     __ LslImmediate(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2);    \
     __ csel(R2, ZR, R2, HI);                                                   \
                                                                                \
     /* Get the class index and insert it into the tags. */                     \
-    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid), kNoPP);          \
+    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));                 \
     __ orr(R2, R2, Operand(TMP));                                              \
     __ str(R2, FieldAddress(R0, type_name::tags_offset()));  /* Tags. */       \
   }                                                                            \
@@ -267,7 +267,7 @@
   /* R3: scratch register. */                                                  \
   /* data area to be initialized. */                                           \
   __ mov(R3, ZR);                                                              \
-  __ AddImmediate(R2, R0, sizeof(Raw##type_name) - 1, kNoPP);                  \
+  __ AddImmediate(R2, R0, sizeof(Raw##type_name) - 1);                         \
   Label init_loop, done;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmp(R2, Operand(R1));                                                     \
@@ -473,7 +473,7 @@
 
   // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
   // cannot tag the result.
-  __ CompareImmediate(R0, 0x4000000000000000, kNoPP);
+  __ CompareImmediate(R0, 0x4000000000000000);
   __ b(&fall_through, EQ);
   __ SmiTag(R0);  // Not equal. Okay to tag and return.
   __ ret();  // Return.
@@ -547,7 +547,7 @@
 
   TestBothArgumentsSmis(assembler, &fall_through);
   __ CompareImmediate(
-      right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)), PP);
+      right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
   __ b(&fall_through, CS);
 
   // Left is not a constant.
@@ -570,8 +570,8 @@
   TestBothArgumentsSmis(assembler, &fall_through);
   // R0 contains the right argument, R1 the left.
   __ CompareRegisters(R1, R0);
-  __ LoadObject(R0, Bool::False(), PP);
-  __ LoadObject(TMP, Bool::True(), PP);
+  __ LoadObject(R0, Bool::False());
+  __ LoadObject(TMP, Bool::True());
   __ csel(R0, TMP, R0, true_condition);
   __ ret();
   __ Bind(&fall_through);
@@ -618,10 +618,10 @@
   __ b(&check_for_mint, NE);  // If R0 or R1 is not a smi do Mint checks.
 
   // Both arguments are smi, '===' is good enough.
-  __ LoadObject(R0, Bool::False(), PP);
+  __ LoadObject(R0, Bool::False());
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(R0, Bool::True(), PP);
+  __ LoadObject(R0, Bool::True());
   __ ret();
 
   // At least one of the arguments was not Smi.
@@ -635,20 +635,20 @@
   // Note that an instance of Mint or Bigint never contains a value that can be
   // represented by Smi.
 
-  __ CompareClassId(R0, kDoubleCid, kNoPP);
+  __ CompareClassId(R0, kDoubleCid);
   __ b(&fall_through, EQ);
-  __ LoadObject(R0, Bool::False(), PP);  // Smi == Mint -> false.
+  __ LoadObject(R0, Bool::False());  // Smi == Mint -> false.
   __ ret();
 
   __ Bind(&receiver_not_smi);
   // R1: receiver.
 
-  __ CompareClassId(R1, kMintCid, kNoPP);
+  __ CompareClassId(R1, kMintCid);
   __ b(&fall_through, NE);
   // Receiver is Mint, return false if right is Smi.
   __ tsti(R0, Immediate(kSmiTagMask));
   __ b(&fall_through, NE);
-  __ LoadObject(R0, Bool::False(), PP);
+  __ LoadObject(R0, Bool::False());
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
 
@@ -673,7 +673,7 @@
   __ b(&fall_through, LT);
 
   // If shift amount is bigger than 63, set to 63.
-  __ LoadImmediate(TMP, 0x3F, kNoPP);
+  __ LoadImmediate(TMP, 0x3F);
   __ CompareRegisters(R0, TMP);
   __ csel(R0, TMP, R0, GT);
   __ SmiUntag(R1);
@@ -698,7 +698,7 @@
   // XOR with sign bit to complement bits if value is negative.
   __ eor(R0, R0, Operand(R0, ASR, 63));
   __ clz(R0, R0);
-  __ LoadImmediate(R1, 64, kNoPP);
+  __ LoadImmediate(R1, 64);
   __ sub(R0, R1, Operand(R0));
   __ SmiTag(R0);
   __ ret();
@@ -729,9 +729,9 @@
   __ add(R0, R0, Operand(R2));
   __ add(R8, R8, Operand(R0, LSL, 3));
   // R3 = n % (2 * _DIGIT_BITS)
-  __ AndImmediate(R3, R5, 63, kNoPP);
+  __ AndImmediate(R3, R5, 63);
   // R2 = 64 - R3
-  __ LoadImmediate(R2, 64, kNoPP);
+  __ LoadImmediate(R2, 64);
   __ sub(R2, R2, Operand(R3));
   __ mov(R1, ZR);
   Label loop;
@@ -772,9 +772,9 @@
   __ sub(R0, R2, Operand(R0));
   __ add(R6, R8, Operand(R0, LSL, 3));
   // R3 = n % (2*_DIGIT_BITS)
-  __ AndImmediate(R3, R5, 63, kNoPP);
+  __ AndImmediate(R3, R5, 63);
   // R2 = 64 - R3
-  __ LoadImmediate(R2, 64, kNoPP);
+  __ LoadImmediate(R2, 64);
   __ sub(R2, R2, Operand(R3));
   // R1 = x_digits[n ~/ (2*_DIGIT_BITS)] >> (n % (2*_DIGIT_BITS))
   __ ldr(R1, Address(R7, 2 * Bigint::kBytesPerDigit, Address::PostIndex));
@@ -854,7 +854,7 @@
   __ Bind(&last_carry);
   Label done;
   __ b(&done, CC);
-  __ LoadImmediate(R0, 1, kNoPP);
+  __ LoadImmediate(R0, 1);
   __ str(R0, Address(R6, 0));
 
   __ Bind(&done);
@@ -1029,7 +1029,7 @@
   __ b(&propagate_carry_loop, CS);
 
   __ Bind(&done);
-  __ LoadImmediate(R0, Smi::RawValue(2), kNoPP);  // Two digits processed.
+  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
   __ ret();
 }
 
@@ -1144,7 +1144,7 @@
   __ stp(R6, R7, Address(R5, 0, Address::PairOffset));
 
   __ Bind(&x_zero);
-  __ LoadImmediate(R0, Smi::RawValue(2), kNoPP);  // Two digits processed.
+  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
   __ ret();
 }
 
@@ -1318,7 +1318,7 @@
   __ str(R0,
          FieldAddress(R4, TypedData::data_offset() + 2*Bigint::kBytesPerDigit));
 
-  __ LoadImmediate(R0, Smi::RawValue(2), kNoPP);  // Two digits processed.
+  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
   __ ret();
 }
 
@@ -1353,7 +1353,7 @@
   __ str(R0,
          FieldAddress(R4, TypedData::data_offset() + 4*Bigint::kBytesPerDigit));
 
-  __ LoadImmediate(R0, Smi::RawValue(2), kNoPP);  // Two digits processed.
+  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
   __ ret();
 }
 
@@ -1367,7 +1367,7 @@
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ tsti(R0, Immediate(kSmiTagMask));
   __ b(is_smi, EQ);
-  __ CompareClassId(R0, kDoubleCid, kNoPP);
+  __ CompareClassId(R0, kDoubleCid);
   __ b(not_double_smi, NE);
   // Fall through with Double in R0.
 }
@@ -1383,18 +1383,18 @@
   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
   // Both arguments are double, right operand is in R0.
 
-  __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V1, R0, Double::value_offset());
   __ Bind(&double_op);
   __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
 
   __ fcmpd(V0, V1);
-  __ LoadObject(R0, Bool::False(), PP);
+  __ LoadObject(R0, Bool::False());
   // Return false if D0 or D1 was NaN before checking true condition.
   __ b(&not_nan, VC);
   __ ret();
   __ Bind(&not_nan);
-  __ LoadObject(TMP, Bool::True(), PP);
+  __ LoadObject(TMP, Bool::True());
   __ csel(R0, TMP, R0, true_condition);
   __ ret();
 
@@ -1438,9 +1438,9 @@
 
   TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
   // Both arguments are double, right operand is in R0.
-  __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V1, R0, Double::value_offset());
   __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
   switch (kind) {
     case Token::kADD: __ faddd(V0, V0, V1); break;
     case Token::kSUB: __ fsubd(V0, V0, V1); break;
@@ -1450,8 +1450,8 @@
   }
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
-  __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ TryAllocate(double_class, &fall_through, R0, R1);
+  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
   __ ret();
   __ Bind(&fall_through);
 }
@@ -1488,12 +1488,12 @@
   __ SmiUntag(R0);
   __ scvtfdx(V1, R0);
   __ ldr(R0, Address(SP, 1 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
   __ fmuld(V0, V0, V1);
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
-  __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ TryAllocate(double_class, &fall_through, R0, R1);
+  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
   __ ret();
   __ Bind(&fall_through);
 }
@@ -1510,8 +1510,8 @@
   __ scvtfdx(V0, R0);
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
-  __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ TryAllocate(double_class, &fall_through, R0, R1);
+  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
   __ ret();
   __ Bind(&fall_through);
 }
@@ -1520,10 +1520,10 @@
 void Intrinsifier::Double_getIsNaN(Assembler* assembler) {
   Label is_true;
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
   __ fcmpd(V0, V0);
-  __ LoadObject(TMP, Bool::False(), PP);
-  __ LoadObject(R0, Bool::True(), PP);
+  __ LoadObject(TMP, Bool::False());
+  __ LoadObject(R0, Bool::True());
   __ csel(R0, TMP, R0, VC);
   __ ret();
 }
@@ -1535,10 +1535,10 @@
   Label is_false, is_true, is_zero;
 
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
   __ fcmpdz(V0);
-  __ LoadObject(true_reg, Bool::True(), PP);
-  __ LoadObject(false_reg, Bool::False(), PP);
+  __ LoadObject(true_reg, Bool::True());
+  __ LoadObject(false_reg, Bool::False());
   __ b(&is_false, VS);  // NaN -> false.
   __ b(&is_zero, EQ);  // Check for negative zero.
   __ b(&is_false, CS);  // >= 0 -> false.
@@ -1563,7 +1563,7 @@
   Label fall_through;
 
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
 
   // Explicit NaN check, since ARM gives an FPU exception if you try to
   // convert NaN to an int.
@@ -1573,7 +1573,7 @@
   __ fcvtzds(R0, V0);
   // Overflow is signaled with minint.
   // Check for overflow and that it fits into Smi.
-  __ CompareImmediate(R0, 0xC000000000000000, kNoPP);
+  __ CompareImmediate(R0, 0xC000000000000000);
   __ b(&fall_through, MI);
   __ SmiTag(R0);
   __ ret();
@@ -1585,13 +1585,13 @@
   Label fall_through, is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
   // Argument is double and is in R0.
-  __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP);
+  __ LoadDFieldFromOffset(V1, R0, Double::value_offset());
   __ Bind(&double_op);
   __ fsqrtd(V0, V1);
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
-  __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
+  __ TryAllocate(double_class, &fall_through, R0, R1);
+  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(R0);
@@ -1627,13 +1627,13 @@
   const int64_t disp =
       Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag;
 
-  __ LoadImmediate(R0, a_int_value, kNoPP);
-  __ LoadFromOffset(R2, R1, disp, kNoPP);
+  __ LoadImmediate(R0, a_int_value);
+  __ LoadFromOffset(R2, R1, disp);
   __ LsrImmediate(R3, R2, 32);
   __ andi(R2, R2, Immediate(0xffffffff));
   __ mul(R2, R0, R2);
   __ add(R2, R2, Operand(R3));
-  __ StoreToOffset(R2, R1, disp, kNoPP);
+  __ StoreToOffset(R2, R1, disp);
   __ ret();
 }
 
@@ -1642,8 +1642,8 @@
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ ldr(R1, Address(SP, 1 * kWordSize));
   __ cmp(R0, Operand(R1));
-  __ LoadObject(R0, Bool::False(), PP);
-  __ LoadObject(TMP, Bool::True(), PP);
+  __ LoadObject(R0, Bool::False());
+  __ LoadObject(TMP, Bool::True());
   __ csel(R0, TMP, R0, EQ);
   __ ret();
 }
@@ -1654,18 +1654,18 @@
   Label fall_through;
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
-  __ LoadClassById(R2, R1, PP);
+  __ LoadClassById(R2, R1);
   // R2: class of instance (R0).
   __ ldr(R3, FieldAddress(R2, Class::signature_function_offset()));
-  __ CompareObject(R3, Object::null_object(), PP);
+  __ CompareObject(R3, Object::null_object());
   __ b(&fall_through, NE);
 
   __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword);
-  __ CompareImmediate(R3, 0, kNoPP);
+  __ CompareImmediate(R3, 0);
   __ b(&fall_through, NE);
 
   __ ldr(R0, FieldAddress(R2, Class::canonical_types_offset()));
-  __ CompareObject(R0, Object::null_object(), PP);
+  __ CompareObject(R0, Object::null_object());
   __ b(&fall_through, EQ);
   __ ret();
 
@@ -1696,19 +1696,19 @@
   __ ldr(R2, FieldAddress(R0, String::length_offset()));
   __ cmp(R1, Operand(R2));
   __ b(&fall_through, CS);  // Runtime throws exception.
-  __ CompareClassId(R0, kOneByteStringCid, kNoPP);
+  __ CompareClassId(R0, kOneByteStringCid);
   __ b(&try_two_byte_string, NE);
   __ SmiUntag(R1);
-  __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag);
   __ ldr(R0, Address(R0, R1), kUnsignedByte);
   __ SmiTag(R0);
   __ ret();
 
   __ Bind(&try_two_byte_string);
-  __ CompareClassId(R0, kTwoByteStringCid, kNoPP);
+  __ CompareClassId(R0, kTwoByteStringCid);
   __ b(&fall_through, NE);
   ASSERT(kSmiTagShift == 1);
-  __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag);
   __ ldr(R0, Address(R0, R1), kUnsignedHalfword);
   __ SmiTag(R0);
   __ ret();
@@ -1729,32 +1729,38 @@
   __ cmp(R1, Operand(R2));
   __ b(&fall_through, CS);  // Runtime throws exception.
 
-  __ CompareClassId(R0, kOneByteStringCid, kNoPP);
+  __ CompareClassId(R0, kOneByteStringCid);
   __ b(&try_two_byte_string, NE);
   __ SmiUntag(R1);
-  __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag);
   __ ldr(R1, Address(R0, R1), kUnsignedByte);
-  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols, kNoPP);
+  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
   __ b(&fall_through, GE);
-  __ LoadImmediate(
-      R0, reinterpret_cast<uword>(Symbols::PredefinedAddress()), kNoPP);
+  const ExternalLabel symbols_label(
+      reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ TagAndPushPP();
+  __ LoadPoolPointer();
+  __ LoadExternalLabel(R0, &symbols_label);
+  __ PopAndUntagPP();
   __ AddImmediate(
-      R0, R0, Symbols::kNullCharCodeSymbolOffset * kWordSize, kNoPP);
+      R0, R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled));
   __ ret();
 
   __ Bind(&try_two_byte_string);
-  __ CompareClassId(R0, kTwoByteStringCid, kNoPP);
+  __ CompareClassId(R0, kTwoByteStringCid);
   __ b(&fall_through, NE);
   ASSERT(kSmiTagShift == 1);
-  __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag);
   __ ldr(R1, Address(R0, R1), kUnsignedHalfword);
-  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols, kNoPP);
+  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
   __ b(&fall_through, GE);
-  __ LoadImmediate(
-      R0, reinterpret_cast<uword>(Symbols::PredefinedAddress()), kNoPP);
+  __ TagAndPushPP();
+  __ LoadPoolPointer();
+  __ LoadExternalLabel(R0, &symbols_label);
+  __ PopAndUntagPP();
   __ AddImmediate(
-      R0, R0, Symbols::kNullCharCodeSymbolOffset * kWordSize, kNoPP);
+      R0, R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled));
   __ ret();
 
@@ -1766,8 +1772,8 @@
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ ldr(R0, FieldAddress(R0, String::length_offset()));
   __ cmp(R0, Operand(Smi::RawValue(0)));
-  __ LoadObject(R0, Bool::True(), PP);
-  __ LoadObject(TMP, Bool::False(), PP);
+  __ LoadObject(R0, Bool::True());
+  __ LoadObject(TMP, Bool::False());
   __ csel(R0, TMP, R0, NE);
   __ ret();
 }
@@ -1791,7 +1797,7 @@
   __ b(&done, EQ);
 
   __ mov(R3, ZR);
-  __ AddImmediate(R6, R1, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R6, R1, OneByteString::data_offset() - kHeapObjectTag);
   // R1: Instance of OneByteString.
   // R2: String length, untagged integer.
   // R3: Loop counter, untagged integer.
@@ -1823,7 +1829,7 @@
   __ addw(R0, R0, Operand(R0, LSL, 15));
   // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
   __ AndImmediate(
-      R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1, kNoPP);
+      R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1);
   __ CompareRegisters(R0, ZR);
   // return hash_ == 0 ? 1 : hash_;
   __ Bind(&done);
@@ -1843,20 +1849,19 @@
                                      Label* failure) {
   const Register length_reg = R2;
   Label fail;
-  __ MaybeTraceAllocation(kOneByteStringCid, R0, kNoPP, failure);
+  __ MaybeTraceAllocation(kOneByteStringCid, R0, failure,
+                          /* inline_isolate = */ false);
   __ mov(R6, length_reg);  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
   const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1;
-  __ AddImmediate(length_reg, length_reg, fixed_size, kNoPP);
+  __ AddImmediate(length_reg, length_reg, fixed_size);
   __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1)));
 
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
   const intptr_t cid = kOneByteStringCid;
-  Heap::Space space = heap->SpaceForAllocation(cid);
-  __ LoadImmediate(R3, heap->TopAddress(space), kNoPP);
-  __ ldr(R0, Address(R3));
+  Heap::Space space = Heap::SpaceForAllocation(cid);
+  __ ldr(R3, Address(THR, Thread::heap_offset()));
+  __ ldr(R0, Address(R3, Heap::TopOffset(space)));
 
   // length_reg: allocation size.
   __ adds(R1, R0, Operand(length_reg));
@@ -1866,17 +1871,17 @@
   // R0: potential new object start.
   // R1: potential next object start.
   // R2: allocation size.
-  // R3: heap->TopAddress(space).
-  __ LoadImmediate(R7, heap->EndAddress(space), kNoPP);
-  __ ldr(R7, Address(R7));
+  // R3: heap.
+  __ ldr(R7, Address(R3, Heap::EndOffset(space)));
   __ cmp(R1, Operand(R7));
   __ b(&fail, CS);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ str(R1, Address(R3));
-  __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP);
-  __ UpdateAllocationStatsWithSize(cid, R2, kNoPP, space);
+  __ str(R1, Address(R3, Heap::TopOffset(space)));
+  __ AddImmediate(R0, R0, kHeapObjectTag);
+  __ UpdateAllocationStatsWithSize(cid, R2, space,
+                                   /* inline_isolate = */ false);
 
   // Initialize the tags.
   // R0: new object start as a tagged pointer.
@@ -1885,13 +1890,13 @@
   {
     const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
 
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP);
+    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
     __ LslImmediate(R2, R2, shift);
     __ csel(R2, R2, ZR, LS);
 
     // Get the class index and insert it into the tags.
     // R2: size and bit tags.
-    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid), kNoPP);
+    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
     __ orr(R2, R2, Operand(TMP));
     __ str(R2, FieldAddress(R0, String::tags_offset()));  // Store tags.
   }
@@ -1936,7 +1941,7 @@
   __ SmiUntag(R1);
   __ add(R3, R3, Operand(R1));
   // Calculate start address and untag (- 1).
-  __ AddImmediate(R3, R3, OneByteString::data_offset() - 1, kNoPP);
+  __ AddImmediate(R3, R3, OneByteString::data_offset() - 1);
 
   // R3: Start address to copy from (untagged).
   // R1: Untagged start index.
@@ -1957,11 +1962,11 @@
   __ mov(R7, R0);
   __ Bind(&loop);
   __ ldr(R1, Address(R6), kUnsignedByte);
-  __ AddImmediate(R6, R6, 1, kNoPP);
+  __ AddImmediate(R6, R6, 1);
   __ sub(R2, R2, Operand(1));
   __ cmp(R2, Operand(0));
   __ str(R1, FieldAddress(R7, OneByteString::data_offset()), kUnsignedByte);
-  __ AddImmediate(R7, R7, 1, kNoPP);
+  __ AddImmediate(R7, R7, 1);
   __ b(&loop, GT);
 
   __ Bind(&done);
@@ -1976,7 +1981,7 @@
   __ ldr(R0, Address(SP, 2 * kWordSize));  // OneByteString.
   __ SmiUntag(R1);
   __ SmiUntag(R2);
-  __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag);
   __ str(R2, Address(R3, R1), kUnsignedByte);
   __ ret();
 }
@@ -2008,7 +2013,7 @@
   // Is other OneByteString?
   __ tsti(R1, Immediate(kSmiTagMask));
   __ b(&fall_through, EQ);
-  __ CompareClassId(R1, string_cid, kNoPP);
+  __ CompareClassId(R1, string_cid);
   __ b(&fall_through, NE);
 
   // Have same length?
@@ -2023,23 +2028,23 @@
          (string_cid == kTwoByteStringCid));
   const intptr_t offset = (string_cid == kOneByteStringCid) ?
       OneByteString::data_offset() : TwoByteString::data_offset();
-  __ AddImmediate(R0, R0, offset - kHeapObjectTag, kNoPP);
-  __ AddImmediate(R1, R1, offset - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R0, R0, offset - kHeapObjectTag);
+  __ AddImmediate(R1, R1, offset - kHeapObjectTag);
   __ SmiUntag(R2);
   __ Bind(&loop);
-  __ AddImmediate(R2, R2, -1, kNoPP);
+  __ AddImmediate(R2, R2, -1);
   __ CompareRegisters(R2, ZR);
   __ b(&is_true, LT);
   if (string_cid == kOneByteStringCid) {
     __ ldr(R3, Address(R0), kUnsignedByte);
     __ ldr(R4, Address(R1), kUnsignedByte);
-    __ AddImmediate(R0, R0, 1, kNoPP);
-    __ AddImmediate(R1, R1, 1, kNoPP);
+    __ AddImmediate(R0, R0, 1);
+    __ AddImmediate(R1, R1, 1);
   } else if (string_cid == kTwoByteStringCid) {
     __ ldr(R3, Address(R0), kUnsignedHalfword);
     __ ldr(R4, Address(R1), kUnsignedHalfword);
-    __ AddImmediate(R0, R0, 2, kNoPP);
-    __ AddImmediate(R1, R1, 2, kNoPP);
+    __ AddImmediate(R0, R0, 2);
+    __ AddImmediate(R1, R1, 2);
   } else {
     UNIMPLEMENTED();
   }
@@ -2048,11 +2053,11 @@
   __ b(&loop);
 
   __ Bind(&is_true);
-  __ LoadObject(R0, Bool::True(), PP);
+  __ LoadObject(R0, Bool::True());
   __ ret();
 
   __ Bind(&is_false);
-  __ LoadObject(R0, Bool::False(), PP);
+  __ LoadObject(R0, Bool::False());
   __ ret();
 
   __ Bind(&fall_through);
@@ -2085,20 +2090,20 @@
   // string CIDs as well as stored function pointers are in sequence.
   __ ldr(R2, Address(SP, kRegExpParamOffset));
   __ ldr(R1, Address(SP, kStringParamOffset));
-  __ LoadClassId(R1, R1, kNoPP);
-  __ AddImmediate(R1, R1, -kOneByteStringCid, kNoPP);
+  __ LoadClassId(R1, R1);
+  __ AddImmediate(R1, R1, -kOneByteStringCid);
   __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
   __ ldr(R0, FieldAddress(R1, JSRegExp::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.
   static const intptr_t arg_count = RegExpMacroAssembler::kParamCount;
-  __ LoadObject(R4, Array::Handle(ArgumentsDescriptor::New(arg_count)), kNoPP);
+  __ LoadObject(R4, Array::Handle(ArgumentsDescriptor::New(arg_count)));
   __ eor(R5, R5, Operand(R5));
 
   // Tail-call the function.
   __ ldr(R1, FieldAddress(R0, Function::instructions_offset()));
-  __ AddImmediate(R1, R1, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R1, R1, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R1);
 }
 
@@ -2106,8 +2111,7 @@
 // On stack: user tag (+0).
 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
   // R1: Isolate.
-  Isolate* isolate = Isolate::Current();
-  __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP);
+  __ LoadIsolate(R1);
   // R0: Current user tag.
   __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
   // R2: UserTag.
@@ -2123,22 +2127,15 @@
 
 
 void Intrinsifier::UserTag_defaultTag(Assembler* assembler) {
-  Isolate* isolate = Isolate::Current();
-  // Set return value to default tag address.
-  __ LoadImmediate(R0,
-      reinterpret_cast<uword>(isolate) + Isolate::default_tag_offset(),
-      kNoPP);
-  __ ldr(R0, Address(R0));
+  __ LoadIsolate(R0);
+  __ ldr(R0, Address(R0, Isolate::default_tag_offset()));
   __ ret();
 }
 
 
 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) {
-  // R1: Default tag address.
-  Isolate* isolate = Isolate::Current();
-  __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP);
-  // Set return value to Isolate::current_tag_.
-  __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
+  __ LoadIsolate(R0);
+  __ ldr(R0, Address(R0, Isolate::current_tag_offset()));
   __ ret();
 }
 
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index f2bb256..11f93e6 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -186,7 +186,8 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, EDI, &fall_through, false);                     \
+  __ MaybeTraceAllocation(cid, EDI, &fall_through, false,                      \
+                          /* inline_isolate = */ false);                       \
   __ movl(EDI, Address(ESP, kArrayLengthStackOffset));  /* Array length. */    \
   /* Check that length is a positive Smi. */                                   \
   /* EDI: requested array length argument. */                                  \
@@ -209,9 +210,9 @@
   const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \
   __ leal(EDI, Address(EDI, scale_factor, fixed_size));                        \
   __ andl(EDI, Immediate(-kObjectAlignment));                                  \
-  Heap* heap = Isolate::Current()->heap();                                     \
-  Heap::Space space = heap->SpaceForAllocation(cid);                           \
-  __ movl(EAX, Address::Absolute(heap->TopAddress(space)));                    \
+  Heap::Space space = Heap::SpaceForAllocation(cid);                           \
+  __ movl(ECX, Address(THR, Thread::heap_offset()));                           \
+  __ movl(EAX, Address(ECX, Heap::TopOffset(space)));                          \
   __ movl(EBX, EAX);                                                           \
                                                                                \
   /* EDI: allocation size. */                                                  \
@@ -222,14 +223,16 @@
   /* EAX: potential new object start. */                                       \
   /* EBX: potential next object start. */                                      \
   /* EDI: allocation size. */                                                  \
-  __ cmpl(EBX, Address::Absolute(heap->EndAddress(space)));                    \
+  /* ECX: heap. */                                                             \
+  __ cmpl(EBX, Address(ECX, Heap::EndOffset(space)));                          \
   __ j(ABOVE_EQUAL, &fall_through);                                            \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ movl(Address::Absolute(heap->TopAddress(space)), EBX);                    \
+  __ movl(Address(ECX, Heap::TopOffset(space)), EBX);                          \
   __ addl(EAX, Immediate(kHeapObjectTag));                                     \
-  __ UpdateAllocationStatsWithSize(cid, EDI, kNoRegister, space);              \
+  __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space,                       \
+                                   /* inline_isolate = */ false);              \
                                                                                \
   /* Initialize the tags. */                                                   \
   /* EAX: new object start as a tagged pointer. */                             \
@@ -588,7 +591,7 @@
                  &fall_through,
                  Assembler::kNearJump,
                  EAX,  // Result register.
-                 kNoRegister);
+                 ECX);  // temp
   // EBX and EDI are not objects but integer values.
   __ movl(FieldAddress(EAX, Mint::value_offset()), EBX);
   __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI);
@@ -1869,7 +1872,8 @@
                                      Label* ok,
                                      Label* failure,
                                      Register length_reg) {
-  __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false);
+  __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false,
+                          /* inline_isolate = */ false);
   if (length_reg != EDI) {
     __ movl(EDI, length_reg);
   }
@@ -1880,11 +1884,10 @@
   __ leal(EDI, Address(EDI, TIMES_1, fixed_size));  // EDI is untagged.
   __ andl(EDI, Immediate(-kObjectAlignment));
 
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
   const intptr_t cid = kOneByteStringCid;
-  Heap::Space space = heap->SpaceForAllocation(cid);
-  __ movl(EAX, Address::Absolute(heap->TopAddress(space)));
+  Heap::Space space = Heap::SpaceForAllocation(cid);
+  __ movl(ECX, Address(THR, Thread::heap_offset()));
+  __ movl(EAX, Address(ECX, Heap::TopOffset(space)));
   __ movl(EBX, EAX);
 
   // EDI: allocation size.
@@ -1895,15 +1898,17 @@
   // EAX: potential new object start.
   // EBX: potential next object start.
   // EDI: allocation size.
-  __ cmpl(EBX, Address::Absolute(heap->EndAddress(space)));
+  // ECX: heap.
+  __ cmpl(EBX, Address(ECX, Heap::EndOffset(space)));
   __ j(ABOVE_EQUAL, &pop_and_fail);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movl(Address::Absolute(heap->TopAddress(space)), EBX);
+  __ movl(Address(ECX, Heap::TopOffset(space)), EBX);
   __ addl(EAX, Immediate(kHeapObjectTag));
 
-  __ UpdateAllocationStatsWithSize(cid, EDI, kNoRegister, space);
+  __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space,
+                                   /* inline_isolate = */ false);
 
   // Initialize the tags.
   // EAX: new object start as a tagged pointer.
@@ -2116,45 +2121,32 @@
 
 // On stack: user tag (+1), return-address (+0).
 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
-  Isolate* isolate = Isolate::Current();
-  const Address current_tag_addr =
-      Address::Absolute(reinterpret_cast<uword>(isolate) +
-                        Isolate::current_tag_offset());
-  const Address user_tag_addr =
-      Address::Absolute(reinterpret_cast<uword>(isolate) +
-                        Isolate::user_tag_offset());
+  // RDI: Isolate.
+  __ LoadIsolate(EDI);
   // EAX: Current user tag.
-  __ movl(EAX, current_tag_addr);
+  __ movl(EAX, Address(EDI, Isolate::current_tag_offset()));
   // EAX: UserTag.
   __ movl(EBX, Address(ESP, + 1 * kWordSize));
   // Set Isolate::current_tag_.
-  __ movl(current_tag_addr, EBX);
+  __ movl(Address(EDI, Isolate::current_tag_offset()), EBX);
   // EAX: UserTag's tag.
   __ movl(EBX, FieldAddress(EBX, UserTag::tag_offset()));
   // Set Isolate::user_tag_.
-  __ movl(user_tag_addr, EBX);
+  __ movl(Address(EDI, Isolate::user_tag_offset()), EBX);
   __ ret();
 }
 
 
 void Intrinsifier::UserTag_defaultTag(Assembler* assembler) {
-  Isolate* isolate = Isolate::Current();
-  const Address default_tag_addr =
-      Address::Absolute(
-          reinterpret_cast<uword>(isolate) + Isolate::default_tag_offset());
-  // Set return value.
-  __ movl(EAX, default_tag_addr);
+  __ LoadIsolate(EAX);
+  __ movl(EAX, Address(EAX, Isolate::default_tag_offset()));
   __ ret();
 }
 
 
 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) {
-  Isolate* isolate = Isolate::Current();
-  const Address current_tag_addr =
-      Address::Absolute(reinterpret_cast<uword>(isolate) +
-                        Isolate::current_tag_offset());
-  // Set return value to Isolate::current_tag_.
-  __ movl(EAX, current_tag_addr);
+  __ LoadIsolate(EAX);
+  __ movl(EAX, Address(EAX, Isolate::current_tag_offset()));
   __ ret();
 }
 
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 1cbb12f..d66ffb2 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -179,7 +179,8 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, T2, &fall_through);                             \
+  __ MaybeTraceAllocation(cid, T2, &fall_through,                              \
+                          /* inline_isolate = */ false);                       \
   __ lw(T2, Address(SP, kArrayLengthStackOffset));  /* Array length. */        \
   /* Check that length is a positive Smi. */                                   \
   /* T2: requested array length argument. */                                   \
@@ -195,10 +196,9 @@
   __ AddImmediate(T2, fixed_size);                                             \
   __ LoadImmediate(TMP, -kObjectAlignment);                                    \
   __ and_(T2, T2, TMP);                                                        \
-  Heap* heap = Isolate::Current()->heap();                                     \
-  Heap::Space space = heap->SpaceForAllocation(cid);                           \
-  __ LoadImmediate(V0, heap->TopAddress(space));                               \
-  __ lw(V0, Address(V0, 0));                                                   \
+  Heap::Space space = Heap::SpaceForAllocation(cid);                           \
+  __ lw(T3, Address(THR, Thread::heap_offset()));                              \
+  __ lw(V0, Address(T3, Heap::TopOffset(space)));                              \
                                                                                \
   /* T2: allocation size. */                                                   \
   __ addu(T1, V0, T2);                                                         \
@@ -209,16 +209,16 @@
   /* V0: potential new object start. */                                        \
   /* T1: potential next object start. */                                       \
   /* T2: allocation size. */                                                   \
-  __ LoadImmediate(T3, heap->EndAddress(space));                               \
-  __ lw(T3, Address(T3, 0));                                                   \
-  __ BranchUnsignedGreaterEqual(T1, T3, &fall_through);                        \
+  /* T3: heap. */                                                              \
+  __ lw(T4, Address(T3, Heap::EndOffset(space)));                              \
+  __ BranchUnsignedGreaterEqual(T1, T4, &fall_through);                        \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ LoadImmediate(T3, heap->TopAddress(space));                               \
-  __ sw(T1, Address(T3, 0));                                                   \
+  __ sw(T1, Address(T3, Heap::TopOffset(space)));                              \
   __ AddImmediate(V0, kHeapObjectTag);                                         \
-  __ UpdateAllocationStatsWithSize(cid, T2, T4, space);                        \
+  __ UpdateAllocationStatsWithSize(cid, T2, T4, space,                         \
+                                   /* inline_isolate = */ false);              \
   /* Initialize the tags. */                                                   \
   /* V0: new object start as a tagged pointer. */                              \
   /* T1: new object end address. */                                            \
@@ -1767,8 +1767,16 @@
   __ lbu(T2, FieldAddress(T2, OneByteString::data_offset()));
   __ BranchUnsignedGreaterEqual(
       T2, Immediate(Symbols::kNumberOfOneCharCodeSymbols), &fall_through);
-  __ LoadImmediate(
-      V0, reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  const ExternalLabel symbols_label(
+      reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ Push(PP);
+  __ Push(RA);
+  __ LoadPoolPointer();
+  assembler->set_constant_pool_allowed(true);
+  __ LoadExternalLabel(V0, &symbols_label, kNotPatchable);
+  assembler->set_constant_pool_allowed(false);
+  __ Pop(RA);
+  __ Pop(PP);
   __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ sll(T2, T2, 2);
   __ addu(T2, T2, V0);
@@ -1782,8 +1790,14 @@
   __ lhu(T2, FieldAddress(T2, TwoByteString::data_offset()));
   __ BranchUnsignedGreaterEqual(
       T2, Immediate(Symbols::kNumberOfOneCharCodeSymbols), &fall_through);
-  __ LoadImmediate(V0,
-                   reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ Push(PP);
+  __ Push(RA);
+  __ LoadPoolPointer();
+  assembler->set_constant_pool_allowed(true);
+  __ LoadExternalLabel(V0, &symbols_label, kNotPatchable);
+  assembler->set_constant_pool_allowed(false);
+  __ Pop(RA);
+  __ Pop(PP);
   __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
   __ sll(T2, T2, 2);
   __ addu(T2, T2, V0);
@@ -1883,7 +1897,8 @@
                                      Label* ok,
                                      Label* failure) {
   const Register length_reg = T2;
-  __ MaybeTraceAllocation(kOneByteStringCid, V0, failure);
+  __ MaybeTraceAllocation(kOneByteStringCid, V0, failure,
+                          /* inline_isolate = */ false);
   __ mov(T6, length_reg);  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
@@ -1892,12 +1907,10 @@
   __ LoadImmediate(TMP, ~(kObjectAlignment - 1));
   __ and_(length_reg, length_reg, TMP);
 
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
   const intptr_t cid = kOneByteStringCid;
-  Heap::Space space = heap->SpaceForAllocation(cid);
-  __ LoadImmediate(T3, heap->TopAddress(space));
-  __ lw(V0, Address(T3, 0));
+  Heap::Space space = Heap::SpaceForAllocation(cid);
+  __ lw(T3, Address(THR, Thread::heap_offset()));
+  __ lw(V0, Address(T3, Heap::TopOffset(space)));
 
   // length_reg: allocation size.
   __ addu(T1, V0, length_reg);
@@ -1907,17 +1920,17 @@
   // V0: potential new object start.
   // T1: potential next object start.
   // T2: allocation size.
-  // T3: heap->TopAddress(space).
-  __ LoadImmediate(T4, heap->EndAddress(space));
-  __ lw(T4, Address(T4, 0));
+  // T3: heap.
+  __ lw(T4, Address(T3, Heap::EndOffset(space)));
   __ BranchUnsignedGreaterEqual(T1, T4, failure);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ sw(T1, Address(T3, 0));
+  __ sw(T1, Address(T3, Heap::TopOffset(space)));
   __ AddImmediate(V0, kHeapObjectTag);
 
-  __ UpdateAllocationStatsWithSize(cid, T2, T3, space);
+  __ UpdateAllocationStatsWithSize(cid, T2, T3, space,
+                                   /* inline_isolate = */ false);
 
   // Initialize the tags.
   // V0: new object start as a tagged pointer.
@@ -2137,8 +2150,7 @@
 // On stack: user tag (+0).
 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
   // T1: Isolate.
-  Isolate* isolate = Isolate::Current();
-  __ LoadImmediate(T1, reinterpret_cast<uword>(isolate));
+  __ LoadIsolate(T1);
   // V0: Current user tag.
   __ lw(V0, Address(T1, Isolate::current_tag_offset()));
   // T2: UserTag.
@@ -2155,20 +2167,14 @@
 
 
 void Intrinsifier::UserTag_defaultTag(Assembler* assembler) {
-  Isolate* isolate = Isolate::Current();
-  // V0: Address of default tag.
-  __ LoadImmediate(V0,
-      reinterpret_cast<uword>(isolate) + Isolate::default_tag_offset());
+  __ LoadIsolate(V0);
   __ Ret();
-  __ delay_slot()->lw(V0, Address(V0, 0));
+  __ delay_slot()->lw(V0, Address(V0, Isolate::default_tag_offset()));
 }
 
 
 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) {
-  // V0: Isolate.
-  Isolate* isolate = Isolate::Current();
-  __ LoadImmediate(V0, reinterpret_cast<uword>(isolate));
-  // Set return value.
+  __ LoadIsolate(V0);
   __ Ret();
   __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset()));
 }
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 6ed3726..aeea84b 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -72,7 +72,7 @@
   // Try allocating in new space.
   const Class& cls = Class::Handle(
       Isolate::Current()->object_store()->growable_object_array_class());
-  __ TryAllocate(cls, &fall_through, Assembler::kFarJump, RAX, kNoRegister);
+  __ TryAllocate(cls, &fall_through, Assembler::kFarJump, RAX, R13);
 
   // Store backing array object in growable array object.
   __ movq(RCX, Address(RSP, kArrayOffset));  // data argument.
@@ -121,7 +121,7 @@
   __ StoreIntoObject(RDX,
                      FieldAddress(RDX, RCX, TIMES_4, Array::data_offset()),
                      RAX);
-  __ LoadObject(RAX, Object::null_object(), PP);
+  __ LoadObject(RAX, Object::null_object());
   __ ret();
   __ Bind(&fall_through);
 }
@@ -130,7 +130,8 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, &fall_through, false);                          \
+  __ MaybeTraceAllocation(cid, &fall_through, false,                           \
+                          /* inline_isolate = */ false);                       \
   __ movq(RDI, Address(RSP, kArrayLengthStackOffset));  /* Array length. */    \
   /* Check that length is a positive Smi. */                                   \
   /* RDI: requested array length argument. */                                  \
@@ -153,10 +154,9 @@
   const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \
   __ leaq(RDI, Address(RDI, scale_factor, fixed_size));                        \
   __ andq(RDI, Immediate(-kObjectAlignment));                                  \
-  Heap* heap = Isolate::Current()->heap();                                     \
-  Heap::Space space = heap->SpaceForAllocation(cid);                           \
-  __ movq(RAX, Immediate(heap->TopAddress(space)));                            \
-  __ movq(RAX, Address(RAX, 0));                                               \
+  Heap::Space space = Heap::SpaceForAllocation(cid);                           \
+  __ movq(R13, Address(THR, Thread::heap_offset()));                           \
+  __ movq(RAX, Address(R13, Heap::TopOffset(space)));                          \
   __ movq(RCX, RAX);                                                           \
                                                                                \
   /* RDI: allocation size. */                                                  \
@@ -167,17 +167,16 @@
   /* RAX: potential new object start. */                                       \
   /* RCX: potential next object start. */                                      \
   /* RDI: allocation size. */                                                  \
-  /* R13: scratch register. */                                                 \
-  __ movq(R13, Immediate(heap->EndAddress(space)));                            \
-  __ cmpq(RCX, Address(R13, 0));                                               \
+  /* R13: heap. */                                                             \
+  __ cmpq(RCX, Address(R13, Heap::EndOffset(space)));                          \
   __ j(ABOVE_EQUAL, &fall_through);                                            \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ movq(R13, Immediate(heap->TopAddress(space)));                            \
-  __ movq(Address(R13, 0), RCX);                                               \
+  __ movq(Address(R13, Heap::TopOffset(space)), RCX);                          \
   __ addq(RAX, Immediate(kHeapObjectTag));                                     \
-  __ UpdateAllocationStatsWithSize(cid, RDI, space);                           \
+  __ UpdateAllocationStatsWithSize(cid, RDI, space,                            \
+                                   /* inline_isolate = */ false);              \
   /* Initialize the tags. */                                                   \
   /* RAX: new object start as a tagged pointer. */                             \
   /* RCX: new object end address. */                                           \
@@ -583,10 +582,10 @@
   // RAX contains the right argument.
   __ cmpq(Address(RSP, + 2 * kWordSize), RAX);
   __ j(true_condition, &true_label, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
   __ Bind(&fall_through);
 }
@@ -633,10 +632,10 @@
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
   // Both arguments are smi, '===' is good enough.
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
 
   // At least one of the arguments was not Smi.
@@ -652,7 +651,7 @@
   __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize));
   __ CompareClassId(RAX, kDoubleCid);
   __ j(EQUAL, &fall_through);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
 
   __ Bind(&receiver_not_smi);
@@ -664,7 +663,7 @@
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
   // Smi == Mint -> false.
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
 
@@ -1262,10 +1261,10 @@
   __ j(true_condition, &is_true, Assembler::kNearJump);
   // Fall through false.
   __ Bind(&is_false);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(RAX);
@@ -1322,7 +1321,7 @@
                  &fall_through,
                  Assembler::kFarJump,
                  RAX,  // Result register.
-                 kNoRegister);  // Pool pointer might not be loaded.
+                 R13);
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&fall_through);
@@ -1367,7 +1366,7 @@
                  &fall_through,
                  Assembler::kFarJump,
                  RAX,  // Result register.
-                 kNoRegister);  // Pool pointer might not be loaded.
+                 R13);
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&fall_through);
@@ -1389,7 +1388,7 @@
                  &fall_through,
                  Assembler::kFarJump,
                  RAX,  // Result register.
-                 kNoRegister);  // Pool pointer might not be loaded.
+                 R13);
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&fall_through);
@@ -1402,10 +1401,10 @@
   __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
   __ comisd(XMM0, XMM0);
   __ j(PARITY_EVEN, &is_true, Assembler::kNearJump);  // NaN -> true;
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
 }
 
@@ -1420,10 +1419,10 @@
   __ j(EQUAL, &is_zero, Assembler::kNearJump);  // Check for negative zero.
   __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump);  // >= 0 -> false.
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
   __ Bind(&is_false);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&is_zero);
   // Check for negative zero (get the sign bit).
@@ -1463,7 +1462,7 @@
                  &fall_through,
                  Assembler::kFarJump,
                  RAX,  // Result register.
-                 kNoRegister);  // Pool pointer might not be loaded.
+                 R13);
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
@@ -1519,10 +1518,10 @@
   __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize));
   __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize));
   __ j(EQUAL, &is_true, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
 }
 
@@ -1534,17 +1533,17 @@
   __ LoadClassIdMayBeSmi(RCX, RAX);
 
   // RCX: untagged cid of instance (RAX).
-  __ LoadClassById(RDI, RCX, PP);
+  __ LoadClassById(RDI, RCX);
   // RDI: class of instance (RAX).
   __ movq(RCX, FieldAddress(RDI, Class::signature_function_offset()));
-  __ CompareObject(RCX, Object::null_object(), PP);
+  __ CompareObject(RCX, Object::null_object());
   __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
 
   __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset()));
   __ cmpq(RCX, Immediate(0));
   __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
   __ movq(RAX, FieldAddress(RDI, Class::canonical_types_offset()));
-  __ CompareObject(RAX, Object::null_object(), PP);
+  __ CompareObject(RAX, Object::null_object());
   __ j(EQUAL, &fall_through, Assembler::kNearJump);  // Not yet set.
   __ ret();
 
@@ -1609,8 +1608,14 @@
   __ movzxb(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
   __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols));
   __ j(GREATER_EQUAL, &fall_through);
-  __ movq(RAX,
-          Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
+  const ExternalLabel symbols_label(
+      reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ pushq(PP);
+  __ LoadPoolPointer();
+  assembler->set_constant_pool_allowed(true);
+  __ LoadExternalLabel(RAX, &symbols_label, kNotPatchable);
+  assembler->set_constant_pool_allowed(false);
+  __ popq(PP);
   __ movq(RAX, Address(RAX,
                        RCX,
                        TIMES_8,
@@ -1624,8 +1629,12 @@
   __ movzxw(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
   __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols));
   __ j(GREATER_EQUAL, &fall_through);
-  __ movq(RAX,
-          Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
+  __ pushq(PP);
+  __ LoadPoolPointer();
+  assembler->set_constant_pool_allowed(true);
+  __ LoadExternalLabel(RAX, &symbols_label, kNotPatchable);
+  assembler->set_constant_pool_allowed(false);
+  __ popq(PP);
   __ movq(RAX, Address(RAX,
                        RCX,
                        TIMES_8,
@@ -1643,10 +1652,10 @@
   __ movq(RAX, FieldAddress(RAX, String::length_offset()));
   __ cmpq(RAX, Immediate(Smi::RawValue(0)));
   __ j(EQUAL, &is_true, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
 }
 
@@ -1727,7 +1736,8 @@
                                      Label* ok,
                                      Label* failure,
                                      Register length_reg) {
-  __ MaybeTraceAllocation(kOneByteStringCid, failure, false);
+  __ MaybeTraceAllocation(kOneByteStringCid, failure, false,
+                          /* inline_isolate = */ false);
   if (length_reg != RDI) {
     __ movq(RDI, length_reg);
   }
@@ -1738,12 +1748,10 @@
   __ leaq(RDI, Address(RDI, TIMES_1, fixed_size));  // RDI is a Smi.
   __ andq(RDI, Immediate(-kObjectAlignment));
 
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
   const intptr_t cid = kOneByteStringCid;
-  Heap::Space space = heap->SpaceForAllocation(cid);
-  __ movq(RAX, Immediate(heap->TopAddress(space)));
-  __ movq(RAX, Address(RAX, 0));
+  Heap::Space space = Heap::SpaceForAllocation(cid);
+  __ movq(R13, Address(THR, Thread::heap_offset()));
+  __ movq(RAX, Address(R13, Heap::TopOffset(space)));
 
   // RDI: allocation size.
   __ movq(RCX, RAX);
@@ -1754,16 +1762,16 @@
   // RAX: potential new object start.
   // RCX: potential next object start.
   // RDI: allocation size.
-  __ movq(R13, Immediate(heap->EndAddress(space)));
-  __ cmpq(RCX, Address(R13, 0));
+  // R13: heap.
+  __ cmpq(RCX, Address(R13, Heap::EndOffset(space)));
   __ j(ABOVE_EQUAL, &pop_and_fail);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movq(R13, Immediate(heap->TopAddress(space)));
-  __ movq(Address(R13, 0), RCX);
+  __ movq(Address(R13, Heap::TopOffset(space)), RCX);
   __ addq(RAX, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, RDI, space);
+  __ UpdateAllocationStatsWithSize(cid, RDI, space,
+                                   /* inline_isolate = */ false);
 
   // Initialize the tags.
   // RAX: new object start as a tagged pointer.
@@ -1918,11 +1926,11 @@
   __ jmp(&loop, Assembler::kNearJump);
 
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True(), PP);
+  __ LoadObject(RAX, Bool::True());
   __ ret();
 
   __ Bind(&is_false);
-  __ LoadObject(RAX, Bool::False(), PP);
+  __ LoadObject(RAX, Bool::False());
   __ ret();
 
   __ Bind(&fall_through);
@@ -1956,7 +1964,7 @@
   __ movq(RBX, Address(RSP, kRegExpParamOffset));
   __ movq(RDI, Address(RSP, kStringParamOffset));
   __ LoadClassId(RDI, RDI);
-  __ SubImmediate(RDI, Immediate(kOneByteStringCid), PP);
+  __ SubImmediate(RDI, Immediate(kOneByteStringCid));
   __ movq(RAX, FieldAddress(RBX, RDI, TIMES_8,
                             JSRegExp::function_offset(kOneByteStringCid)));
 
@@ -1964,7 +1972,7 @@
   // in RAX, the argument descriptor in R10, and IC-Data in RCX.
   static const intptr_t arg_count = RegExpMacroAssembler::kParamCount;
   __ LoadObject(R10,
-      Array::ZoneHandle(ArgumentsDescriptor::New(arg_count)), PP);
+      Array::ZoneHandle(ArgumentsDescriptor::New(arg_count)));
   __ xorq(RCX, RCX);
 
   // Tail-call the function.
@@ -1977,10 +1985,7 @@
 // On stack: user tag (+1), return-address (+0).
 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
   // RBX: Isolate.
-  Isolate* isolate = Isolate::Current();
-  const Immediate& isolate_address =
-      Immediate(reinterpret_cast<int64_t>(isolate));
-  __ movq(RBX, isolate_address);
+  __ LoadIsolate(RBX);
   // RAX: Current user tag.
   __ movq(RAX, Address(RBX, Isolate::current_tag_offset()));
   // R10: UserTag.
@@ -1996,26 +2001,15 @@
 
 
 void Intrinsifier::UserTag_defaultTag(Assembler* assembler) {
-  // RBX: Address of default tag.
-  Isolate* isolate = Isolate::Current();
-  const Immediate& default_tag_addr =
-      Immediate(reinterpret_cast<int64_t>(isolate) +
-                Isolate::default_tag_offset());
-  __ movq(RBX, default_tag_addr);
-  // Set return value.
-  __ movq(RAX, Address(RBX, 0));
+  __ LoadIsolate(RAX);
+  __ movq(RAX, Address(RAX, Isolate::default_tag_offset()));
   __ ret();
 }
 
 
 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) {
-  // RBX: Isolate.
-  Isolate* isolate = Isolate::Current();
-  const Immediate& isolate_address =
-      Immediate(reinterpret_cast<int64_t>(isolate));
-  __ movq(RBX, isolate_address);
-  // Set return value to Isolate::current_tag_.
-  __ movq(RAX, Address(RBX, Isolate::current_tag_offset()));
+  __ LoadIsolate(RAX);
+  __ movq(RAX, Address(RAX, Isolate::current_tag_offset()));
   __ ret();
 }
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 6c8d73f..764d21a 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -60,6 +60,14 @@
 DEFINE_FLAG(charp, timeline_trace_dir, NULL,
             "Enable all timeline trace streams and output traces "
             "into specified directory.");
+DEFINE_FLAG(int, new_gen_semi_max_size, (kWordSize <= 4) ? 16 : 32,
+            "Max size of new gen semi space in MB");
+DEFINE_FLAG(int, old_gen_heap_size, 0,
+            "Max size of old gen heap size in MB, or 0 for unlimited,"
+            "e.g: --old_gen_heap_size=1024 allows up to 1024MB old gen heap");
+DEFINE_FLAG(int, external_max_size, (kWordSize <= 4) ? 512 : 1024,
+            "Max total size of external allocations in MB, or 0 for unlimited,"
+            "e.g: --external_max_size=1024 allows up to 1024MB of externals");
 
 // TODO(iposva): Make these isolate specific flags inaccessible using the
 // regular FLAG_xyz pattern.
@@ -608,7 +616,7 @@
 
 void BaseIsolate::AssertCurrentThreadIsMutator() const {
   ASSERT(Isolate::Current() == this);
-  ASSERT(Isolate::Current()->mutator_thread() == Thread::Current());
+  ASSERT(Isolate::Current()->MutatorThreadIsCurrentThread());
 }
 #endif  // defined(DEBUG)
 
@@ -642,7 +650,6 @@
       environment_callback_(NULL),
       library_tag_handler_(NULL),
       api_state_(NULL),
-      stub_code_(NULL),
       debugger_(NULL),
       single_step_(false),
       resume_request_(false),
@@ -682,8 +689,10 @@
       tag_table_(GrowableObjectArray::null()),
       current_tag_(UserTag::null()),
       default_tag_(UserTag::null()),
+      collected_closures_(GrowableObjectArray::null()),
       deoptimized_code_array_(GrowableObjectArray::null()),
       metrics_list_head_(NULL),
+      compilation_allowed_(true),
       cha_(NULL),
       next_(NULL),
       pause_loop_monitor_(NULL),
@@ -705,7 +714,6 @@
   delete heap_;
   delete object_store_;
   delete api_state_;
-  delete stub_code_;
   delete debugger_;
 #if defined(USING_SIMULATOR)
   delete simulator_;
@@ -765,6 +773,12 @@
   ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
 #undef ISOLATE_TIMELINE_STREAM_INIT
 
+  Heap::Init(result,
+             is_vm_isolate
+                 ? 0  // New gen size 0; VM isolate should only allocate in old.
+                 : FLAG_new_gen_semi_max_size * MBInWords,
+             FLAG_old_gen_heap_size * MBInWords,
+             FLAG_external_max_size * MBInWords);
 
   // TODO(5411455): For now just set the recently created isolate as
   // the current isolate.
@@ -830,8 +844,8 @@
 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::GetStackPointerEntryPoint());
+  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)
@@ -1607,6 +1621,9 @@
   // Visit the tag table which is stored in the isolate.
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&tag_table_));
 
+  // Visit array of closures pending precompilation.
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&collected_closures_));
+
   // Visit the deoptimized code array which is stored in the isolate.
   visitor->VisitPointer(
       reinterpret_cast<RawObject**>(&deoptimized_code_array_));
@@ -1807,6 +1824,11 @@
 }
 
 
+void Isolate::set_collected_closures(const GrowableObjectArray& value) {
+  collected_closures_ = value.raw();
+}
+
+
 void Isolate::set_deoptimized_code_array(const GrowableObjectArray& value) {
   deoptimized_code_array_ = value.raw();
 }
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index a7aa4fc..c43a3fa 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -122,12 +122,6 @@
     return thread == NULL ? NULL : thread->isolate();
   }
 
-  static void InitOnce();
-  static Isolate* Init(const char* name_prefix,
-                       const Dart_IsolateFlags& api_flags,
-                       bool is_vm_isolate = false);
-  void Shutdown();
-
   // Register a newly introduced class.
   void RegisterClass(const Class& cls);
   void RegisterClassAt(intptr_t index, const Class& cls);
@@ -163,16 +157,15 @@
     message_notify_callback_ = value;
   }
 
-  // A thread that operates on this isolate and may execute Dart code.
-  // No other threads operating on this isolate may execute Dart code.
-  // TODO(koda): Remove after pivoting to thread in NativeArguments.
-  Thread* mutator_thread() {
-    DEBUG_ASSERT(mutator_thread_ == NULL || IsIsolateOf(mutator_thread_));
-    return mutator_thread_;
+  // Limited public access to BaseIsolate::mutator_thread_ for code that
+  // must treat the mutator as the default or a special case. Prefer code
+  // that works uniformly across all threads.
+  bool HasMutatorThread() {
+    return mutator_thread_ != NULL;
   }
-#if defined(DEBUG)
-  bool IsIsolateOf(Thread* thread);
-#endif  // DEBUG
+  bool MutatorThreadIsCurrentThread() {
+    return mutator_thread_ == Thread::Current();
+  }
 
   const char* name() const { return name_; }
   const char* debugger_name() const { return debugger_name_; }
@@ -244,9 +237,6 @@
   ApiState* api_state() const { return api_state_; }
   void set_api_state(ApiState* value) { api_state_ = value; }
 
-  StubCode* stub_code() const { return stub_code_; }
-  void set_stub_code(StubCode* value) { stub_code_ = value; }
-
   LongJumpScope* long_jump_base() const { return long_jump_base_; }
   void set_long_jump_base(LongJumpScope* value) { long_jump_base_ = value; }
 
@@ -327,12 +317,12 @@
   enum {
     kApiInterrupt = 0x1,      // An interrupt from Dart_InterruptIsolate.
     kMessageInterrupt = 0x2,  // An interrupt to process an out of band message.
-    kStoreBufferInterrupt = 0x4,  // An interrupt to process the store buffer.
+    kVMInterrupt = 0x4,  // Internal VM checks: safepoints, store buffers, etc.
 
     kInterruptsMask =
         kApiInterrupt |
         kMessageInterrupt |
-        kStoreBufferInterrupt,
+        kVMInterrupt,
   };
 
   void ScheduleInterrupts(uword interrupt_bits);
@@ -696,6 +686,11 @@
   RawUserTag* default_tag() const { return default_tag_; }
   void set_default_tag(const UserTag& tag);
 
+  RawGrowableObjectArray* collected_closures() const {
+    return collected_closures_;
+  }
+  void set_collected_closures(const GrowableObjectArray& value);
+
   Metric* metrics_list_head() {
     return metrics_list_head_;
   }
@@ -710,6 +705,11 @@
   void set_deoptimized_code_array(const GrowableObjectArray& value);
   void TrackDeoptimizedCode(const Code& code);
 
+  bool compilation_allowed() const { return compilation_allowed_; }
+  void set_compilation_allowed(bool allowed) {
+    compilation_allowed_ = allowed;
+  }
+
 #if defined(DEBUG)
 #define REUSABLE_HANDLE_SCOPE_ACCESSORS(object)                                \
   void set_reusable_##object##_handle_scope_active(bool value) {               \
@@ -748,8 +748,16 @@
   }
 
  private:
+  friend class Dart;  // Init, InitOnce, Shutdown.
+
   explicit Isolate(const Dart_IsolateFlags& api_flags);
 
+  static void InitOnce();
+  static Isolate* Init(const char* name_prefix,
+                       const Dart_IsolateFlags& api_flags,
+                       bool is_vm_isolate = false);
+  void Shutdown();
+
   void BuildName(const char* name_prefix);
   void PrintInvokedFunctions();
 
@@ -765,9 +773,17 @@
     user_tag_ = tag;
   }
 
-  void set_mutator_thread(Thread* thread) {
+  void ClearMutatorThread() {
+    mutator_thread_ = NULL;
+  }
+  void MakeCurrentThreadMutator(Thread* thread) {
+    ASSERT(thread == Thread::Current());
+    DEBUG_ASSERT(IsIsolateOf(thread));
     mutator_thread_ = thread;
   }
+#if defined(DEBUG)
+  bool IsIsolateOf(Thread* thread);
+#endif  // DEBUG
 
   template<class T> T* AllocateReusableHandle();
 
@@ -792,7 +808,6 @@
   Dart_EnvironmentCallback environment_callback_;
   Dart_LibraryTagHandler library_tag_handler_;
   ApiState* api_state_;
-  StubCode* stub_code_;
   Debugger* debugger_;
   bool single_step_;
   bool resume_request_;
@@ -850,12 +865,16 @@
   RawGrowableObjectArray* tag_table_;
   RawUserTag* current_tag_;
   RawUserTag* default_tag_;
+
+  RawGrowableObjectArray* collected_closures_;
   RawGrowableObjectArray* deoptimized_code_array_;
 
   Metric* metrics_list_head_;
 
   Counters counters_;
 
+  bool compilation_allowed_;
+
   // TODO(23153): Move this out of Isolate/Thread.
   CHA* cha_;
 
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 99c8354..f5f0506 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "include/dart_api.h"
 #include "platform/assert.h"
 #include "vm/globals.h"
 #include "vm/isolate.h"
@@ -10,14 +11,11 @@
 namespace dart {
 
 UNIT_TEST_CASE(IsolateCurrent) {
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT_EQ(isolate, Isolate::Current());
-  isolate->Shutdown();
-  EXPECT_EQ(reinterpret_cast<Isolate*>(NULL), Isolate::Current());
-  delete isolate;
+  Dart_Isolate isolate = Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  EXPECT_EQ(isolate, Dart_CurrentIsolate());
+  Dart_ShutdownIsolate();
+  EXPECT_EQ(reinterpret_cast<Dart_Isolate>(NULL), Dart_CurrentIsolate());
 }
 
 
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 5b10ab0..6fc9e92 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -27,7 +27,7 @@
                        ObjectIdRing::kAllocateId),
       id_zone_(&default_id_zone_),
       reply_port_(ILLEGAL_PORT),
-      seq_(""),
+      seq_(Instance::Handle(Instance::null())),
       method_(""),
       param_keys_(NULL),
       param_values_(NULL),
@@ -41,12 +41,12 @@
 
 void JSONStream::Setup(Zone* zone,
                        Dart_Port reply_port,
-                       const String& seq,
+                       const Instance& seq,
                        const String& method,
                        const Array& param_keys,
                        const Array& param_values) {
   set_reply_port(reply_port);
-  seq_ = seq.ToCString();
+  seq_ ^= seq.raw();
   method_ = method.ToCString();
 
   String& string_iterator = String::Handle();
@@ -74,13 +74,13 @@
               isolate_name, method_);
     setup_time_micros_ = OS::GetCurrentTimeMicros();
   }
-  buffer_.Printf("{\"json-rpc\":\"2.0\", \"result\":");
+  buffer_.Printf("{\"jsonrpc\":\"2.0\", \"result\":");
 }
 
 
 void JSONStream::SetupError() {
   buffer_.Clear();
-  buffer_.Printf("{\"json-rpc\":\"2.0\", \"error\":");
+  buffer_.Printf("{\"jsonrpc\":\"2.0\", \"error\":");
 }
 
 
@@ -162,8 +162,22 @@
   if (FLAG_trace_service) {
     process_delta_micros = OS::GetCurrentTimeMicros() - setup_time_micros_;
   }
-  // TODO(turnidge): Handle non-string sequence numbers.
-  buffer_.Printf(", \"id\":\"%s\"}", seq());
+
+  if (seq_.IsString()) {
+    const String& str = String::Cast(seq_);
+    PrintProperty("id", str.ToCString());
+  } else if (seq_.IsInteger()) {
+    const Integer& integer = Integer::Cast(seq_);
+    PrintProperty64("id", integer.AsInt64Value());
+  } else if (seq_.IsDouble()) {
+    const Double& dbl = Double::Cast(seq_);
+    PrintProperty("id", dbl.value());
+  } else if (seq_.IsNull()) {
+    // JSON-RPC 2.0 says that a request with a null ID shouldn't get a reply.
+    return;
+  }
+  buffer_.AddChar('}');
+
   const String& reply = String::Handle(String::New(ToCString()));
   ASSERT(!reply.IsNull());
 
@@ -270,6 +284,11 @@
 }
 
 
+void JSONStream::PrintValueTimeMillis(int64_t millis) {
+  PrintValue(static_cast<double>(millis));
+}
+
+
 void JSONStream::PrintValue(double d) {
   PrintCommaIfNeeded();
   buffer_.Printf("%f", d);
@@ -422,6 +441,11 @@
 }
 
 
+void JSONStream::PrintPropertyTimeMillis(const char* name, int64_t millis) {
+  PrintProperty(name, static_cast<double>(millis));
+}
+
+
 void JSONStream::PrintProperty(const char* name, double d) {
   PrintPropertyName(name);
   PrintValue(d);
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 4ada4e7..e581560 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -57,7 +57,7 @@
 
   void Setup(Zone* zone,
              Dart_Port reply_port,
-             const String& seq,
+             const Instance& seq,
              const String& method,
              const Array& param_keys,
              const Array& param_values);
@@ -100,7 +100,6 @@
   // otherwise.
   bool ParamIs(const char* key, const char* value) const;
 
-  const char* seq() const { return seq_; }
   const char* method() const { return method_; }
   const char** param_keys() const { return param_keys_; }
   const char** param_values() const { return param_values_; }
@@ -117,6 +116,7 @@
   void PrintValueBool(bool b);
   void PrintValue(intptr_t i);
   void PrintValue64(int64_t i);
+  void PrintValueTimeMillis(int64_t millis);
   void PrintValue(double d);
   void PrintValueBase64(const uint8_t* bytes, intptr_t length);
   void PrintValue(const char* s);
@@ -136,6 +136,7 @@
   void PrintPropertyBool(const char* name, bool b);
   void PrintProperty(const char* name, intptr_t i);
   void PrintProperty64(const char* name, int64_t i);
+  void PrintPropertyTimeMillis(const char* name, int64_t millis);
   void PrintProperty(const char* name, double d);
   void PrintPropertyBase64(const char* name,
                            const uint8_t* bytes,
@@ -169,7 +170,7 @@
   RingServiceIdZone default_id_zone_;
   ServiceIdZone* id_zone_;
   Dart_Port reply_port_;
-  const char* seq_;
+  Instance& seq_;
   const char* method_;
   const char** param_keys_;
   const char** param_values_;
@@ -214,6 +215,9 @@
   void AddProperty64(const char* name, int64_t i) const {
     stream_->PrintProperty64(name, i);
   }
+  void AddPropertyTimeMillis(const char* name, int64_t millis) const {
+    stream_->PrintPropertyTimeMillis(name, millis);
+  }
   void AddProperty(const char* name, double d) const {
     stream_->PrintProperty(name, d);
   }
@@ -285,6 +289,9 @@
   void AddValue(bool b) const { stream_->PrintValueBool(b); }
   void AddValue(intptr_t i) const { stream_->PrintValue(i); }
   void AddValue64(int64_t i) const { stream_->PrintValue64(i); }
+  void AddValueTimeMillis(int64_t millis) const {
+    stream_->PrintValueTimeMillis(millis);
+  }
   void AddValue(double d) const { stream_->PrintValue(d); }
   void AddValue(const char* s) const { stream_->PrintValue(s); }
   void AddValue(const Object& obj, bool ref = true) const {
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index c62d8e5..5bb9842 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -118,7 +118,7 @@
 
 
 LogBlock::LogBlock(Thread* thread, Log* log)
-    : StackResource(thread->isolate()),
+    : StackResource(thread),
       log_(log), cursor_(log->cursor()) {
   CommonConstructor();
 }
@@ -132,7 +132,7 @@
 
 
 LogBlock::LogBlock(Thread* thread)
-    : StackResource(thread->isolate()),
+    : StackResource(thread),
       log_(thread->isolate()->Log()),
       cursor_(thread->isolate()->Log()->cursor()) {
   CommonConstructor();
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index 3ca64b3..66de5af 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -42,7 +42,8 @@
   ASSERT(value != 0);
   ASSERT(IsSafeToJump());
 
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
 
 #if defined(DEBUG)
 #define CHECK_REUSABLE_HANDLE(name)                                            \
@@ -55,7 +56,7 @@
   isolate->object_store()->set_sticky_error(error);
 
   // Destruct all the active StackResource objects.
-  StackResource::UnwindAbove(isolate, top_);
+  StackResource::UnwindAbove(thread, top_);
   longjmp(environment_, value);
   UNREACHABLE();
 }
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index 364c946..9082739 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -14,20 +14,20 @@
 namespace dart {
 
 UNIT_TEST_CASE(Metric_Simple) {
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT_EQ(isolate, Isolate::Current());
-  Metric metric;
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  {
+    Metric metric;
 
-  // Initialize metric.
-  metric.Init(Isolate::Current(), "a.b.c", "foobar", Metric::kCounter);
-  EXPECT_EQ(0, metric.value());
-  metric.increment();
-  EXPECT_EQ(1, metric.value());
-  metric.set_value(44);
-  EXPECT_EQ(44, metric.value());
+    // Initialize metric.
+    metric.Init(Isolate::Current(), "a.b.c", "foobar", Metric::kCounter);
+    EXPECT_EQ(0, metric.value());
+    metric.increment();
+    EXPECT_EQ(1, metric.value());
+    metric.set_value(44);
+    EXPECT_EQ(44, metric.value());
+  }
+  Dart_ShutdownIsolate();
 }
 
 class MyMetric : public Metric {
@@ -43,27 +43,30 @@
 };
 
 UNIT_TEST_CASE(Metric_OnDemand) {
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT_EQ(isolate, Isolate::Current());
-  MyMetric metric;
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    MyMetric metric;
 
-  metric.Init(Isolate::Current(), "a.b.c", "foobar", Metric::kByte);
-  // value is still the default value.
-  EXPECT_EQ(0, metric.value());
-  // Call LeakyValue to confirm that Value returns constant 99.
-  EXPECT_EQ(99, metric.LeakyValue());
+    metric.Init(Isolate::Current(), "a.b.c", "foobar", Metric::kByte);
+    // value is still the default value.
+    EXPECT_EQ(0, metric.value());
+    // Call LeakyValue to confirm that Value returns constant 99.
+    EXPECT_EQ(99, metric.LeakyValue());
 
-  // Serialize to JSON.
-  JSONStream js;
-  metric.PrintJSON(&js);
-  const char* json = js.ToCString();
-  EXPECT_STREQ("{\"type\":\"Counter\",\"name\":\"a.b.c\",\"description\":"
-               "\"foobar\",\"unit\":\"byte\","
-               "\"fixedId\":true,\"id\":\"metrics\\/native\\/a.b.c\""
-               ",\"value\":99.000000}", json);
+    // Serialize to JSON.
+    JSONStream js;
+    metric.PrintJSON(&js);
+    const char* json = js.ToCString();
+    EXPECT_STREQ("{\"type\":\"Counter\",\"name\":\"a.b.c\",\"description\":"
+                 "\"foobar\",\"unit\":\"byte\","
+                 "\"fixedId\":true,\"id\":\"metrics\\/native\\/a.b.c\""
+                 ",\"value\":99.000000}", json);
+  }
+  Dart_ShutdownIsolate();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index a3cd5c1..a668897 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -11,6 +11,7 @@
 #include "vm/message.h"
 #include "vm/native_message_handler.h"
 #include "vm/port.h"
+#include "vm/precompiler.h"
 
 namespace dart {
 
@@ -79,6 +80,16 @@
   }
 }
 
+static void Precompile(Isolate* isolate, Dart_Handle* result) {
+  ASSERT(isolate != NULL);
+  const Error& error = Error::Handle(isolate, Precompiler::CompileAll());
+  if (error.IsNull()) {
+    *result = Api::Success();
+  } else {
+    *result = Api::NewHandle(isolate, error.raw());
+  }
+}
+
 
 DART_EXPORT Dart_Handle Dart_CompileAll() {
   Isolate* isolate = Isolate::Current();
@@ -92,4 +103,17 @@
   return result;
 }
 
+
+DART_EXPORT Dart_Handle Dart_Precompile() {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  Dart_Handle result = Api::CheckAndFinalizePendingClasses(isolate);
+  if (::Dart_IsError(result)) {
+    return result;
+  }
+  CHECK_CALLBACK_STATE(isolate);
+  Precompile(isolate, &result);
+  return result;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 8f64388..3fb2f74 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -37,8 +37,8 @@
 #define CHECK_STACK_ALIGNMENT { }
 #else
 #define CHECK_STACK_ALIGNMENT {                                                \
-  uword (*func)() =                                                            \
-      reinterpret_cast<uword (*)()>(StubCode::GetStackPointerEntryPoint());    \
+  uword (*func)() = reinterpret_cast<uword (*)()>(                             \
+      StubCode::GetStackPointer_entry()->EntryPoint());                        \
   uword current_sp = func();                                                   \
   ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()));        \
 }
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 39d9dcc..0180c09 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -88,7 +88,8 @@
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   /* Tell MemorySanitizer 'arguments' is initialized by generated code. */
   MSAN_UNPOISON(arguments, sizeof(*arguments));
-  Isolate* isolate = arguments->thread()->isolate();
+  Thread* thread = arguments->thread();
+  Isolate* isolate = thread->isolate();
 
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
@@ -97,12 +98,12 @@
   TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
   if (scope == NULL) {
     scope = new ApiLocalScope(current_top_scope,
-                              isolate->top_exit_frame_info());
+                              thread->top_exit_frame_info());
     ASSERT(scope != NULL);
   } else {
-    scope->Reinit(isolate,
+    scope->Reinit(thread,
                   current_top_scope,
-                  isolate->top_exit_frame_info());
+                  thread->top_exit_frame_info());
     state->set_reusable_scope(NULL);
   }
   state->set_top_scope(scope);  // New scope is now the top scope.
@@ -112,7 +113,7 @@
   ASSERT(current_top_scope == scope->previous());
   state->set_top_scope(current_top_scope);  // Reset top scope to previous.
   if (state->reusable_scope() == NULL) {
-    scope->Reset(isolate);  // Reset the old scope which we just exited.
+    scope->Reset(thread);  // Reset the old scope which we just exited.
     state->set_reusable_scope(scope);
   } else {
     ASSERT(state->reusable_scope() != scope);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f674cd4..83e45e9 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -635,7 +635,7 @@
   // Allocate and initialize the empty_array instance.
   {
     uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld);
-    InitializeObject(address, kArrayCid, Array::InstanceSize(0));
+    InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0));
     Array::initializeHandle(
         empty_array_,
         reinterpret_cast<RawArray*>(address + kHeapObjectTag));
@@ -646,7 +646,7 @@
   // Allocate and initialize the zero_array instance.
   {
     uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld);
-    InitializeObject(address, kArrayCid, Array::InstanceSize(1));
+    InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1));
     Array::initializeHandle(
         zero_array_,
         reinterpret_cast<RawArray*>(address + kHeapObjectTag));
@@ -899,7 +899,7 @@
 void Object::MakeUnusedSpaceTraversable(const Object& obj,
                                         intptr_t original_size,
                                         intptr_t used_size) {
-  ASSERT(Isolate::Current()->no_safepoint_scope_depth() > 0);
+  ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
   ASSERT(!obj.IsNull());
   ASSERT(original_size >= used_size);
   if (original_size > used_size) {
@@ -3475,6 +3475,11 @@
 }
 
 
+void Class::set_is_allocated() const {
+  set_state_bits(IsAllocatedBit::update(true, raw_ptr()->state_bits_));
+}
+
+
 void Class::set_is_finalized() const {
   ASSERT(!is_finalized());
   set_state_bits(ClassFinalizedBits::update(RawClass::kFinalized,
@@ -5177,18 +5182,16 @@
 
 bool Function::HasCode() const {
   ASSERT(raw_ptr()->instructions_ != Instructions::null());
-  StubCode* stub_code = Isolate::Current()->stub_code();
   return raw_ptr()->instructions_ !=
-      stub_code->LazyCompile_entry()->code()->ptr()->instructions_;
+      StubCode::LazyCompile_entry()->code()->ptr()->instructions_;
 }
 
 
 void Function::ClearCode() const {
   ASSERT(ic_data_array() == Array::null());
   StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
-  StubCode* stub_code = Isolate::Current()->stub_code();
   StorePointer(&raw_ptr()->instructions_,
-      Code::Handle(stub_code->LazyCompile_entry()->code()).instructions());
+      Code::Handle(StubCode::LazyCompile_entry()->code()).instructions());
 }
 
 
@@ -6198,6 +6201,12 @@
 }
 
 
+bool Function::IsConstructorClosureFunction() const {
+  return IsClosureFunction() &&
+      String::Handle(name()).StartsWith(Symbols::ConstructorClosurePrefix());
+}
+
+
 RawFunction* Function::New() {
   ASSERT(Object::function_class() != Class::null());
   RawObject* raw = Object::Allocate(Function::kClassId,
@@ -6251,8 +6260,7 @@
   result.set_is_inlinable(true);
   result.set_allows_hoisting_check_class(true);
   result.set_allows_bounds_check_generalization(true);
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  result.SetInstructions(Code::Handle(stub_code->LazyCompile_entry()->code()));
+  result.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
   if (kind == RawFunction::kClosureFunction) {
     const ClosureData& data = ClosureData::Handle(ClosureData::New());
     result.set_data(data);
@@ -6506,8 +6514,8 @@
   if (implicit_static_closure() == Instance::null()) {
     Isolate* isolate = Isolate::Current();
     ObjectStore* object_store = isolate->object_store();
-    const Context& context = Context::Handle(isolate,
-                                             object_store->empty_context());
+    const Context& context =
+        Context::Handle(isolate, object_store->empty_context());
     Instance& closure =
         Instance::Handle(isolate, Closure::New(*this, context, Heap::kOld));
     const char* error_str = NULL;
@@ -6846,6 +6854,7 @@
   return raw_ptr()->ic_data_array_;
 }
 
+
 void Function::ClearICDataArray() const {
   set_ic_data_array(Array::null_array());
 }
@@ -7223,6 +7232,7 @@
   result.set_owner(owner);
   result.set_token_pos(token_pos);
   result.set_has_initializer(false);
+  result.set_initializer(Function::Handle());
   result.set_is_unboxing_candidate(true);
   result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid);
   result.set_is_nullable(FLAG_use_field_guards ? false : true);
@@ -7386,6 +7396,73 @@
   }
 }
 
+// Build a closure object that gets (or sets) the contents of a static
+// field f and cache the closure in a newly created static field
+// named #f (or #f= in case of a setter).
+RawInstance* Field::AccessorClosure(bool make_setter) const {
+  ASSERT(is_static());
+  const Class& field_owner = Class::Handle(owner());
+
+  String& closure_name = String::Handle(this->name());
+  closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name);
+  if (make_setter) {
+    closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name);
+  }
+
+  Field& closure_field = Field::Handle();
+  closure_field = field_owner.LookupStaticField(closure_name);
+  if (!closure_field.IsNull()) {
+    ASSERT(closure_field.is_static());
+    const Instance& closure = Instance::Handle(closure_field.value());
+    ASSERT(!closure.IsNull());
+    ASSERT(closure.IsClosure());
+    return closure.raw();
+  }
+
+  // This is the first time a closure for this field is requested.
+  // Create the closure and a new static field in which it is stored.
+  const char* field_name = String::Handle(name()).ToCString();
+  String& expr_src = String::Handle();
+  if (make_setter) {
+    expr_src =
+        String::NewFormatted("(%s_) { return %s = %s_; }",
+                             field_name, field_name, field_name);
+  } else {
+    expr_src = String::NewFormatted("() { return %s; }", field_name);
+  }
+  Object& result =
+      Object::Handle(field_owner.Evaluate(expr_src,
+                                          Object::empty_array(),
+                                          Object::empty_array()));
+  ASSERT(result.IsInstance());
+  // The caller may expect the closure to be allocated in old space. Copy
+  // the result here, since Object::Clone() is a private method.
+  result = Object::Clone(result, Heap::kOld);
+
+  closure_field = Field::New(closure_name,
+                             true,  // is_static
+                             true,  // is_final
+                             true,  // is_const
+                             true,  // is_synthetic
+                             field_owner,
+                             this->token_pos());
+  closure_field.set_value(Instance::Cast(result));
+  closure_field.set_type(Type::Handle(Type::DynamicType()));
+  field_owner.AddField(closure_field);
+
+  return Instance::RawCast(result.raw());
+}
+
+
+RawInstance* Field::GetterClosure() const {
+  return AccessorClosure(false);
+}
+
+
+RawInstance* Field::SetterClosure() const {
+  return AccessorClosure(true);
+}
+
 
 RawArray* Field::dependent_code() const {
   return raw_ptr()->dependent_code_;
@@ -7452,6 +7529,11 @@
 }
 
 
+void Field::set_initializer(const Function& initializer) const {
+  StorePointer(&raw_ptr()->initializer_, initializer.raw());
+}
+
+
 void Field::EvaluateInitializer() const {
   ASSERT(is_static());
   if (value() == Object::sentinel().raw()) {
@@ -7632,6 +7714,10 @@
 
 
 void Field::RecordStore(const Object& value) const {
+  if (!FLAG_use_field_guards) {
+    return;
+  }
+
   if (FLAG_trace_field_guards) {
     OS::Print("Store %s %s <- %s\n",
               ToCString(),
@@ -10831,11 +10917,6 @@
 }
 
 
-void ObjectPool::SetInfoAt(intptr_t index, EntryType info) const {
-  const TypedData& array = TypedData::Handle(info_array());
-  array.SetInt8(index, static_cast<int8_t>(info));
-}
-
 const char* ObjectPool::ToCString() const {
   return "ObjectPool";
 }
@@ -12746,6 +12827,29 @@
 }
 
 
+RawArray* Code::GetInlinedCallerIdMap() const {
+  const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_);
+  if (metadata.IsNull()) {
+    return metadata.raw();
+  }
+  return reinterpret_cast<RawArray*>(
+      metadata.At(RawCode::kInlinedCallerIdMapIndex));
+}
+
+
+void Code::SetInlinedCallerIdMap(const Array& value) const {
+  if (raw_ptr()->inlined_metadata_ == Array::null()) {
+    StorePointer(&raw_ptr()->inlined_metadata_,
+                 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld));
+  }
+  const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_);
+  ASSERT(!metadata.IsNull());
+  ASSERT(metadata.IsOld());
+  ASSERT(value.IsOld());
+  metadata.SetAt(RawCode::kInlinedCallerIdMapIndex, value);
+}
+
+
 RawCode* Code::New(intptr_t pointer_offsets_length) {
   if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) {
     // This should be caught before we reach here.
@@ -12776,6 +12880,11 @@
 RawCode* Code::FinalizeCode(const char* name,
                             Assembler* assembler,
                             bool optimized) {
+  Isolate* isolate = Isolate::Current();
+  if (!isolate->compilation_allowed()) {
+    FATAL1("Precompilation missed code %s\n", name);
+  }
+
   ASSERT(assembler != NULL);
   const ObjectPool& object_pool =
       ObjectPool::Handle(assembler->object_pool_wrapper().MakeObjectPool());
@@ -12787,8 +12896,8 @@
   Code& code = Code::ZoneHandle(Code::New(pointer_offset_count));
   Instructions& instrs =
       Instructions::ZoneHandle(Instructions::New(assembler->CodeSize()));
-  INC_STAT(Isolate::Current(), total_instr_size, assembler->CodeSize());
-  INC_STAT(Isolate::Current(), total_code_size, assembler->CodeSize());
+  INC_STAT(isolate, total_instr_size, assembler->CodeSize());
+  INC_STAT(isolate, total_code_size, assembler->CodeSize());
 
   // Copy the instructions into the instruction area and apply all fixups.
   // Embedded pointers are still in handles at this point.
@@ -12828,7 +12937,7 @@
     code.set_is_alive(true);
 
     // Set object pool in Instructions object.
-    INC_STAT(Isolate::Current(),
+    INC_STAT(isolate,
              total_code_size, object_pool.Length() * sizeof(uintptr_t));
     instrs.set_object_pool(object_pool.raw());
 
@@ -12849,7 +12958,7 @@
     // pushed onto the stack.
     code.SetPrologueOffset(assembler->CodeSize());
   }
-  INC_STAT(Isolate::Current(),
+  INC_STAT(isolate,
            total_code_size, code.comments().comments_.Length());
   return code.raw();
 }
@@ -13114,8 +13223,7 @@
       temp_smi ^= intervals.At(i + Code::kInlIntInliningId);
       intptr_t inlining_id = temp_smi.Value();
       ASSERT(inlining_id >= 0);
-      temp_smi ^= intervals.At(i + Code::kInlIntCallerId);
-      intptr_t caller_id = temp_smi.Value();
+      intptr_t caller_id = GetCallerId(inlining_id);
       while (inlining_id >= 0) {
         inline_interval.AddValue(inlining_id);
         inlining_id = caller_id;
@@ -13171,19 +13279,16 @@
 
 
 intptr_t Code::GetCallerId(intptr_t inlined_id) const {
-  if (inlined_id < 0) return -1;
-  const Array& intervals = Array::Handle(GetInlinedIntervals());
-  if (intervals.IsNull() || (intervals.Length() == 0)) return -1;
-  Smi& temp_smi = Smi::Handle();
-  for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries;
-       i += Code::kInlIntNumEntries) {
-    temp_smi ^= intervals.At(i + Code::kInlIntInliningId);
-    if (temp_smi.Value() == inlined_id) {
-      temp_smi ^= intervals.At(i + Code::kInlIntCallerId);
-      return temp_smi.Value();
-    }
+  if (inlined_id < 0) {
+    return -1;
   }
-  return -1;
+  const Array& map = Array::Handle(GetInlinedCallerIdMap());
+  if (map.IsNull() || (map.Length() == 0)) {
+    return -1;
+  }
+  Smi& smi = Smi::Handle();
+  smi ^= map.At(inlined_id);
+  return smi.Value();
 }
 
 
@@ -13218,8 +13323,7 @@
   temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntInliningId);
   intptr_t inlining_id = temp_smi.Value();
   ASSERT(inlining_id >= 0);
-  temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntCallerId);
-  intptr_t caller_id = temp_smi.Value();
+  intptr_t caller_id = GetCallerId(inlining_id);
   while (inlining_id >= 0) {
     Function& function = Function::ZoneHandle();
     function  ^= id_map.At(inlining_id);
@@ -13231,30 +13335,52 @@
 
 
 void Code::DumpInlinedIntervals() const {
-  OS::Print("Inlined intervals:\n");
+  LogBlock lb(Isolate::Current());
+  ISL_Print("Inlined intervals:\n");
   const Array& intervals = Array::Handle(GetInlinedIntervals());
   if (intervals.IsNull() || (intervals.Length() == 0)) return;
   Smi& start = Smi::Handle();
   Smi& inlining_id = Smi::Handle();
-  Smi& caller_id = Smi::Handle();
+  GrowableArray<Function*> inlined_functions;
+  const Function& inliner = Function::Handle(function());
   for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) {
     start ^= intervals.At(i + Code::kInlIntStart);
     ASSERT(!start.IsNull());
     if (start.IsNull()) continue;
     inlining_id ^= intervals.At(i + Code::kInlIntInliningId);
-    caller_id ^= intervals.At(i + Code::kInlIntCallerId);
-    OS::Print("  %" Px " id: %" Pd " caller-id: %" Pd " \n",
-        start.Value(), inlining_id.Value(), caller_id.Value());
+    ISL_Print("  %" Px " iid: %" Pd " ; ", start.Value(), inlining_id.Value());
+    inlined_functions.Clear();
+
+    ISL_Print("inlined: ");
+    GetInlinedFunctionsAt(start.Value(), &inlined_functions);
+
+    for (intptr_t j = 0; j < inlined_functions.length(); j++) {
+      const char* name = inlined_functions[j]->ToQualifiedCString();
+      ISL_Print("  %s <-", name);
+    }
+    if (inlined_functions[inlined_functions.length() - 1]->raw() !=
+           inliner.raw()) {
+      ISL_Print(" (ERROR, missing inliner)\n");
+    } else {
+      ISL_Print("\n");
+    }
   }
-  OS::Print("Inlined ids:\n");
+  ISL_Print("Inlined ids:\n");
   const Array& id_map = Array::Handle(GetInlinedIdToFunction());
   Function& function = Function::Handle();
   for (intptr_t i = 0; i < id_map.Length(); i++) {
     function ^= id_map.At(i);
     if (!function.IsNull()) {
-      OS::Print("  %" Pd ": %s\n", i, function.ToQualifiedCString());
+      ISL_Print("  %" Pd ": %s\n", i, function.ToQualifiedCString());
     }
   }
+  ISL_Print("Caller Inlining Ids:\n");
+  const Array& caller_map = Array::Handle(GetInlinedCallerIdMap());
+  Smi& smi = Smi::Handle();
+  for (intptr_t i = 0; i < caller_map.Length(); i++) {
+    smi ^= caller_map.At(i);
+    ISL_Print("  iid: %" Pd " caller iid: %" Pd "\n", i, smi.Value());
+  }
 }
 
 
@@ -14301,7 +14427,7 @@
 
 
 intptr_t* Instance::NativeFieldsDataAddr() const {
-  ASSERT(Isolate::Current()->no_safepoint_scope_depth() > 0);
+  ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
   RawTypedData* native_fields =
       reinterpret_cast<RawTypedData*>(*NativeFieldsAddr());
   if (native_fields == TypedData::null()) {
@@ -14450,7 +14576,7 @@
     return "unknown_constant";
   } else if (raw() == Object::non_constant().raw()) {
     return "non_constant";
-  } else if (Isolate::Current()->no_safepoint_scope_depth() > 0) {
+  } else if (Thread::Current()->no_safepoint_scope_depth() > 0) {
     // Can occur when running disassembler.
     return "Instance";
   } else {
@@ -15529,7 +15655,9 @@
   if ((index == 0) && cls.IsCanonicalSignatureClass()) {
     // Verify that the first canonical type is the signature type by checking
     // that the type argument vector of the canonical type ends with the
-    // uninstantiated type parameters of the signature class.
+    // uninstantiated type parameters of the signature class. Note that these
+    // type parameters may be bounded if the super class of the owner class
+    // declares bounds.
     // The signature type is finalized during class finalization, before the
     // optimizer may canonicalize instantiated function types of the same
     // signature class.
@@ -15540,10 +15668,13 @@
       TypeArguments::Handle(isolate, cls.type_parameters());
     const intptr_t num_type_params = cls.NumTypeParameters();
     const intptr_t num_type_args = cls.NumTypeArguments();
-    TypeParameter& type_arg = TypeParameter::Handle(isolate);
+    AbstractType& type_arg = AbstractType::Handle(isolate);
     TypeParameter& type_param = TypeParameter::Handle(isolate);
     for (intptr_t i = 0; i < num_type_params; i++) {
-      type_arg ^= type_args.TypeAt(num_type_args - num_type_params + i);
+      type_arg = type_args.TypeAt(num_type_args - num_type_params + i);
+      while (type_arg.IsBoundedType()) {
+        type_arg = BoundedType::Cast(type_arg).type();
+      }
       type_param ^= type_params.TypeAt(i);
       ASSERT(type_arg.Equals(type_param));
     }
@@ -19669,6 +19800,7 @@
 
 
 void Array::MakeImmutable() const {
+  if (IsImmutable()) return;
   NoSafepointScope no_safepoint;
   uword tags = raw_ptr()->tags_;
   uword old_tags;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b259aac..5bfc041 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -274,6 +274,10 @@
     ASSERT(!IsNull());
     raw()->SetCanonical();
   }
+  void ClearCanonical() const {
+    ASSERT(!IsNull());
+    raw()->ClearCanonical();
+  }
   intptr_t GetClassId() const {
     return !raw()->IsHeapObject() ?
         static_cast<intptr_t>(kSmiCid) : raw()->GetClassId();
@@ -684,7 +688,7 @@
     ASSERT(Contains(reinterpret_cast<uword>(addr) - 1) &&
            Contains(reinterpret_cast<uword>(addr) - kWordSize));
     // At least check that there is a NoSafepointScope and hope it's big enough.
-    ASSERT(Isolate::Current()->no_safepoint_scope_depth() > 0);
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
     return const_cast<FieldType*>(addr);
   }
 
@@ -1278,6 +1282,11 @@
   }
   void set_is_cycle_free() const;
 
+  bool is_allocated() const {
+    return IsAllocatedBit::decode(raw_ptr()->state_bits_);
+  }
+  void set_is_allocated() const;
+
   uint16_t num_native_fields() const {
     return raw_ptr()->num_native_fields_;
   }
@@ -1395,6 +1404,7 @@
     kCycleFreeBit = 12,
     kEnumBit = 13,
     kTraceAllocationBit = 14,
+    kIsAllocatedBit = 15,
   };
   class ConstBit : public BitField<bool, kConstBit, 1> {};
   class ImplementedBit : public BitField<bool, kImplementedBit, 1> {};
@@ -1412,6 +1422,7 @@
   class CycleFreeBit : public BitField<bool, kCycleFreeBit, 1> {};
   class EnumBit : public BitField<bool, kEnumBit, 1> {};
   class TraceAllocationBit : public BitField<bool, kTraceAllocationBit, 1> {};
+  class IsAllocatedBit : public BitField<bool, kIsAllocatedBit, 1> {};
 
   void set_name(const String& value) const;
   void set_pretty_name(const String& value) const;
@@ -2481,6 +2492,8 @@
     return !is_static() && IsImplicitClosureFunction();
   }
 
+  bool IsConstructorClosureFunction() const;
+
   // Returns true if this function represents a local function.
   bool IsLocalFunction() const {
     return parent_function() != Function::null();
@@ -2944,6 +2957,17 @@
 
   void EvaluateInitializer() const;
 
+  RawFunction* initializer() const {
+    return raw_ptr()->initializer_;
+  }
+  void set_initializer(const Function& initializer) const;
+
+  // For static fields only. Constructs a closure that gets/sets the
+  // field value.
+  RawInstance* GetterClosure() const;
+  RawInstance* SetterClosure() const;
+  RawInstance* AccessorClosure(bool make_setter) const;
+
   // Constructs getter and setter names for fields and vice versa.
   static RawString* GetterName(const String& field_name);
   static RawString* GetterSymbol(const String& field_name);
@@ -3563,7 +3587,6 @@
   }
 
   EntryType InfoAt(intptr_t index) const;
-  void SetInfoAt(intptr_t index, EntryType info) const;
 
   RawObject* ObjectAt(intptr_t index) const {
     ASSERT(InfoAt(index) == kTaggedObject);
@@ -4136,8 +4159,7 @@
   enum InlinedIntervalEntries {
     kInlIntStart = 0,
     kInlIntInliningId = 1,
-    kInlIntCallerId = 2,
-    kInlIntNumEntries = 3,
+    kInlIntNumEntries = 2,
   };
 
   RawArray* GetInlinedIntervals() const;
@@ -4146,6 +4168,9 @@
   RawArray* GetInlinedIdToFunction() const;
   void SetInlinedIdToFunction(const Array& value) const;
 
+  RawArray* GetInlinedCallerIdMap() const;
+  void SetInlinedCallerIdMap(const Array& value) const;
+
   void GetInlinedFunctionsAt(
       intptr_t offset, GrowableArray<Function*>* fs) const;
 
diff --git a/runtime/vm/object_arm64_test.cc b/runtime/vm/object_arm64_test.cc
index 44dec3b..9383cc2 100644
--- a/runtime/vm/object_arm64_test.cc
+++ b/runtime/vm/object_arm64_test.cc
@@ -37,8 +37,9 @@
       String::ZoneHandle(String::New(str, Heap::kOld));
   __ mov(SP, CSP);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadObject(R0, string_object, PP);
+  __ LoadPoolPointer();
+  __ LoadObject(R0, string_object);
+  __ set_constant_pool_allowed(false);
   __ PopAndUntagPP();  // Restore caller's pool pointer.
   __ ret();
 }
@@ -49,7 +50,7 @@
 void GenerateEmbedSmiInCode(Assembler* assembler, intptr_t value) {
   const Smi& smi_object = Smi::ZoneHandle(Smi::New(value));
   const int64_t val = reinterpret_cast<int64_t>(smi_object.raw());
-  __ LoadImmediate(R0, val, kNoRegister);
+  __ LoadImmediate(R0, val);
   __ ret();
 }
 
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 2e30f25..ad6f861 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -256,14 +256,30 @@
   // We cannot use a GrowableObjectArray, since we must not trigger GC.
   RetainingPathVisitor(RawObject* obj, const Array& path)
       : obj_(obj), path_(path), length_(0) {
-    ASSERT(Isolate::Current()->no_safepoint_scope_depth() != 0);
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
   }
 
   intptr_t length() const { return length_; }
 
+  bool ShouldSkip(RawObject* obj) {
+    // A retaining path through ICData is never the only retaining path,
+    // and it is less informative than its alternatives.
+    intptr_t cid = obj->GetClassId();
+    switch (cid) {
+    case kICDataCid:
+      return true;
+    default:
+      return false;
+    }
+  }
+
   virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
     if (it->Get() != obj_) {
-      return kProceed;
+      if (ShouldSkip(it->Get())) {
+        return kBacktrack;
+      } else {
+        return kProceed;
+      }
     } else {
       HANDLESCOPE(Isolate::Current());
       Object& current = Object::Handle();
@@ -313,7 +329,7 @@
                            Object* scratch)
     : ObjectVisitor(isolate), ObjectPointerVisitor(isolate), source_(NULL),
       target_(target), references_(references), scratch_(scratch), length_(0) {
-    ASSERT(Isolate::Current()->no_safepoint_scope_depth() != 0);
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
   }
 
   intptr_t length() const { return length_; }
diff --git a/runtime/vm/object_x64_test.cc b/runtime/vm/object_x64_test.cc
index b8914e0..639d8d0 100644
--- a/runtime/vm/object_x64_test.cc
+++ b/runtime/vm/object_x64_test.cc
@@ -35,8 +35,8 @@
   const String& string_object =
       String::ZoneHandle(String::New(str, Heap::kOld));
   __ pushq(PP);  // Save caller's pool pointer and load a new one here.
-  __ LoadPoolPointer(PP);
-  __ LoadObject(RAX, string_object, PP);
+  __ LoadPoolPointer();
+  __ LoadObject(RAX, string_object);
   __ popq(PP);  // Restore caller's pool pointer.
   __ ret();
 }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 80e45ed..0179633 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -48,6 +48,7 @@
 
 DECLARE_FLAG(bool, lazy_dispatchers);
 DECLARE_FLAG(bool, load_deferred_eagerly);
+DECLARE_FLAG(bool, profile_vm);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 
@@ -318,6 +319,7 @@
 // For parsing a compilation unit.
 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos)
     : isolate_(Thread::Current()->isolate()),
+      thread_(Thread::Current()),
       script_(Script::Handle(zone(), script.raw())),
       tokens_iterator_(TokenStream::Handle(zone(), script.tokens()),
                        token_pos),
@@ -347,6 +349,7 @@
                ParsedFunction* parsed_function,
                intptr_t token_position)
     : isolate_(Thread::Current()->isolate()),
+      thread_(Thread::Current()),
       script_(Script::Handle(zone(), script.raw())),
       tokens_iterator_(TokenStream::Handle(zone(), script.tokens()),
                        token_position),
@@ -554,6 +557,13 @@
     AddFinalParameter(token_pos, &Symbols::This(), receiver_type);
   }
 
+  void EraseParameterTypes() {
+    const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
+    const int num_parameters = parameters->length();
+    for (int i = 0; i < num_parameters; i++) {
+      (*parameters)[i].type = &dynamic_type;
+    }
+  }
 
   // Make the parameter variables visible/invisible.
   // Field initializer parameters are always invisible.
@@ -829,11 +839,46 @@
 }
 
 
+bool Parser::ParseFormalParameters(const Function& func, ParamList* params) {
+  ASSERT(!func.IsNull());
+  // This is currently only used for constructors. To handle all kinds
+  // of functions, special cases for getters and possibly other kinds
+  // need to be added.
+  ASSERT(func.kind() == RawFunction::kConstructor);
+  ASSERT(!func.IsRedirectingFactory());
+  // Implicit constructors have no source, no user-defined formal parameters.
+  if (func.IsImplicitConstructor()) {
+    return true;
+  }
+  LongJumpScope jump;
+  if (setjmp(*jump.Set()) == 0) {
+    const Script& script = Script::Handle(func.script());
+    const Class& owner = Class::Handle(func.Owner());
+    ASSERT(!owner.IsNull());
+    ParsedFunction* parsed_function =
+        new ParsedFunction(Thread::Current(), Function::ZoneHandle(func.raw()));
+    Parser parser(script, parsed_function, func.token_pos());
+    parser.SkipFunctionPreamble();
+    parser.ParseFormalParameterList(true, true, params);
+    return true;
+  } else {
+    Thread::Current()->isolate()->object_store()->clear_sticky_error();
+    params->Clear();
+    return false;
+  }
+  UNREACHABLE();
+  return false;
+}
+
+
 void Parser::ParseFunction(ParsedFunction* parsed_function) {
   Isolate* isolate = parsed_function->isolate();
   Zone* zone = parsed_function->zone();
   CSTAT_TIMER_SCOPE(isolate, parser_timer);
   INC_STAT(isolate, num_functions_compiled, 1);
+  VMTagScope tagScope(isolate, VMTag::kCompileParseFunctionTagId,
+                      FLAG_profile_vm);
+
   ASSERT(isolate->long_jump_base()->IsSafeToJump());
   ASSERT(parsed_function != NULL);
   const Function& func = parsed_function->function();
@@ -844,11 +889,15 @@
   switch (func.kind()) {
     case RawFunction::kClosureFunction:
       if (func.IsImplicitClosureFunction()) {
-        parser.SkipFunctionPreamble();
         node_sequence =
             parser.ParseImplicitClosure(func, &default_parameter_values);
         break;
       }
+      if (func.IsConstructorClosureFunction()) {
+        node_sequence =
+            parser.ParseConstructorClosure(func, &default_parameter_values);
+        break;
+      }
       // Fall-through: Handle non-implicit closures.
     case RawFunction::kRegularFunction:
     case RawFunction::kGetterFunction:
@@ -1058,7 +1107,6 @@
 
 ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) {
   ASSERT(field.is_static());
-  ASSERT(field.value() == Object::transition_sentinel().raw());
   Thread* thread = Thread::Current();
   // TODO(koda): Should there be a StackZone here?
   Zone* zone = thread->zone();
@@ -1282,29 +1330,93 @@
 }
 
 
+SequenceNode* Parser::ParseConstructorClosure(const Function& func,
+                                              Array* default_values) {
+  TRACE_PARSER("ParseConstructorClosure");
+  const intptr_t token_pos = func.token_pos();
+
+  Function& constructor = Function::ZoneHandle(Z);
+  TypeArguments& type_args = TypeArguments::ZoneHandle(Z);
+  ParseConstructorClosurization(&constructor, &type_args);
+  ASSERT(!constructor.IsNull());
+
+  ParamList params;
+  // The first parameter of the closure function is the implicit closure
+  // argument.
+  params.AddFinalParameter(token_pos,
+                           &Symbols::ClosureParameter(),
+                           &Type::ZoneHandle(Z, Type::DynamicType()));
+  bool params_ok = ParseFormalParameters(constructor, &params);
+  USE(params_ok);
+  ASSERT(params_ok);
+  // Per language spec, the type of the closure parameters is dynamic.
+  // Replace the types parsed from the constructor.
+  params.EraseParameterTypes();
+
+  SetupDefaultsForOptionalParams(&params, default_values);
+  ASSERT(func.num_fixed_parameters() == params.num_fixed_parameters);
+  ASSERT(func.NumOptionalParameters() == params.num_optional_parameters);
+
+  OpenFunctionBlock(func);
+  LocalScope* scope = current_block_->scope;
+  AddFormalParamsToScope(&params, scope);
+
+  ArgumentListNode* ctor_args = new ArgumentListNode(token_pos);
+  // Skip implicit closure parameter at 0.
+  for (intptr_t i = 1; i < func.NumParameters(); i++) {
+    ctor_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i)));
+  }
+
+  if (func.HasOptionalNamedParameters()) {
+    const Array& arg_names =
+        Array::ZoneHandle(Array::New(func.NumOptionalParameters()));
+    for (intptr_t i = 0; i < arg_names.Length(); i++) {
+      intptr_t index = func.num_fixed_parameters() + i;
+      arg_names.SetAt(i, String::Handle(func.ParameterNameAt(index)));
+    }
+    ctor_args->set_names(arg_names);
+  }
+
+  AstNode* new_object =
+      CreateConstructorCallNode(token_pos, type_args, constructor, ctor_args);
+  ReturnNode* return_node = new ReturnNode(token_pos, new_object);
+  current_block_->statements->Add(return_node);
+  return CloseBlock();
+}
+
+
 SequenceNode* Parser::ParseImplicitClosure(const Function& func,
                                            Array* default_values) {
   TRACE_PARSER("ParseImplicitClosure");
-
   intptr_t token_pos = func.token_pos();
 
   OpenFunctionBlock(func);
 
   ParamList params;
-
   params.AddFinalParameter(
       token_pos,
       &Symbols::ClosureParameter(),
       &Type::ZoneHandle(Type::DynamicType()));
 
-  const bool allow_explicit_default_values = true;
-  ParseFormalParameterList(allow_explicit_default_values, false, &params);
-  SetupDefaultsForOptionalParams(&params, default_values);
-
-  // Getters can't be closurized. If supported, they need special
-  // handling of the parameters as in ParseFunc.
   const Function& parent = Function::ZoneHandle(func.parent_function());
-  ASSERT(!parent.IsGetterFunction());
+  if (parent.IsImplicitSetterFunction()) {
+    const intptr_t ident_pos = func.token_pos();
+    ASSERT(IsIdentifier());
+    const String& field_name = *CurrentLiteral();
+    const Class& field_class = Class::ZoneHandle(Z, parent.Owner());
+    const Field& field =
+        Field::ZoneHandle(Z, field_class.LookupInstanceField(field_name));
+    const AbstractType& field_type = AbstractType::ZoneHandle(Z, field.type());
+    params.AddFinalParameter(ident_pos,
+                             &Symbols::Value(),
+                             &field_type);
+    ASSERT(func.num_fixed_parameters() == 2);  // closure, value.
+  } else if (!parent.IsGetterFunction() && !parent.IsImplicitGetterFunction()) {
+    const bool allow_explicit_default_values = true;
+    SkipFunctionPreamble();
+    ParseFormalParameterList(allow_explicit_default_values, false, &params);
+    SetupDefaultsForOptionalParams(&params, default_values);
+  }
 
   // Populate function scope with the formal parameters.
   LocalScope* scope = current_block_->scope;
@@ -3429,8 +3541,9 @@
 RawLibraryPrefix* Parser::ParsePrefix() {
   ASSERT(IsIdentifier());
   // A library prefix can never stand by itself. It must be followed by
-  // a period.
-  if (LookaheadToken(1) != Token::kPERIOD) {
+  // a period or a hash mark (for closurization).
+  Token::Kind next_token = LookaheadToken(1);
+  if ((next_token != Token::kPERIOD) && (next_token != Token::kHASH)) {
     return LibraryPrefix::null();
   }
   const String& ident = *CurrentLiteral();
@@ -3457,10 +3570,8 @@
     return LibraryPrefix::null();
   }
 
-  // We have a name that is not shadowed, followed by a period.
-  // Consume the identifier and the period.
-  ConsumeToken();
-  ASSERT(CurrentToken() == Token::kPERIOD);  // We checked above.
+  // We have a name that is not shadowed, followed by a period or #.
+  // Consume the identifier, let the caller consume the . or #.
   ConsumeToken();
   return prefix.raw();
 }
@@ -5300,6 +5411,8 @@
       }
       SkipExpr();
       field.set_value(field_value);
+      field.set_has_initializer(true);
+
       if (!has_simple_literal) {
         // Create a static final getter.
         String& getter_name = String::Handle(Z, Field::GetterSymbol(var_name));
@@ -5815,7 +5928,7 @@
                       prefix.ToCString());
         }
         if (is_deferred_import) {
-          ReportError(prefix_pos, "prefix of deferred import must be uniqe");
+          ReportError(prefix_pos, "prefix of deferred import must be unique");
         }
         library_prefix.AddImport(ns);
       } else {
@@ -7472,10 +7585,10 @@
 
   // Since the signature type is cached by the signature class, it may have
   // been finalized already.
-  Type& signature_type = Type::Handle(Z,
-                                      signature_class.SignatureType());
-  TypeArguments& signature_type_arguments = TypeArguments::Handle(Z,
-      signature_type.arguments());
+  Type& signature_type =
+      Type::Handle(Z, signature_class.SignatureType());
+  TypeArguments& signature_type_arguments =
+      TypeArguments::Handle(Z, signature_type.arguments());
 
   if (!signature_type.IsFinalized()) {
     signature_type ^= ClassFinalizer::FinalizeType(
@@ -11316,13 +11429,156 @@
 }
 
 
+// Closurization e#m of getter, setter, method or operator.
+AstNode* Parser::ParseClosurization(AstNode* primary) {
+  ExpectToken(Token::kHASH);
+  intptr_t property_pos = TokenPos();
+  bool is_setter_name = false;
+
+  String& extractor_name = String::ZoneHandle(Z);
+  if (IsIdentifier()) {
+    extractor_name = CurrentLiteral()->raw();
+    ConsumeToken();
+    if (CurrentToken() == Token::kASSIGN) {
+      ConsumeToken();
+      is_setter_name = true;
+    }
+  } else if (Token::CanBeOverloaded(CurrentToken())) {
+    extractor_name = String::New(Token::Str(CurrentToken()));
+    ConsumeToken();
+  } else {
+    ReportError("identifier or operator expected");
+  }
+
+  if (primary->IsPrimaryNode() && primary->AsPrimaryNode()->IsSuper()) {
+    // TODO(hausner): implement super#m
+    ReportError("closurization of super method not yet supported");
+  }
+
+  // Handle closurization of top-level names from library prefixes, P#m
+  if (primary->IsLiteralNode() &&
+      primary->AsLiteralNode()->literal().IsLibraryPrefix()) {
+    const LibraryPrefix& prefix =
+        LibraryPrefix::Cast(primary->AsLiteralNode()->literal());
+    Object& obj = Object::Handle(Z);
+    const bool is_private_name =
+        (extractor_name.CharAt(0) == Library::kPrivateIdentifierStart);
+    if (!is_private_name) {
+      // Private names are not exported by libraries. The name mangling
+      // of private names with a library-specific suffix usually ensures
+      // that _x in library A is not found when looked up from library B.
+      // In the pathological case where a library imports itself with
+      // a prefix, the name mangling does not help in hiding the private
+      // name, so we explicitly prevent lookup of private names here.
+      obj = prefix.LookupObject(extractor_name);
+    }
+    if (!prefix.is_loaded() && (parsed_function() != NULL)) {
+      // Remember that this function depends on an import prefix of an
+      // unloaded deferred library.
+      parsed_function()->AddDeferredPrefix(prefix);
+    }
+
+    if (obj.IsFunction()) {
+      const Function& func = Function::Cast(obj);
+      if (!func.IsSetterFunction() || is_setter_name) {
+        return CreateImplicitClosureNode(func, property_pos, NULL);
+      }
+    } else if (obj.IsField()) {
+      const Field& field = Field::Cast(obj);
+      if (is_setter_name && !field.is_final()) {
+        Instance& setter_closure = Instance::ZoneHandle(field.SetterClosure());
+        return new(Z) LiteralNode(property_pos, setter_closure);
+      }
+      if (!is_setter_name) {
+        Instance& getter_closure = Instance::ZoneHandle(field.GetterClosure());
+        return new(Z) LiteralNode(property_pos, getter_closure);
+      }
+    }
+    return ThrowNoSuchMethodError(property_pos,
+                                  current_class(),
+                                  extractor_name,
+                                  NULL,  // No arguments.
+                                  InvocationMirror::kTopLevel,
+                                  is_setter_name
+                                      ? InvocationMirror::kSetter
+                                      : InvocationMirror::kMethod,
+                                  NULL);  // No existing function.
+  }
+
+  // Handle closurization of static properties of classes, C#n.
+  if (primary->IsPrimaryNode() &&
+      primary->AsPrimaryNode()->primary().IsClass()) {
+    const Class& cls = Class::Cast(primary->AsPrimaryNode()->primary());
+    const Field& field =
+        Field::Handle(Z, cls.LookupStaticField(extractor_name));
+    if (!field.IsNull()) {
+      if (is_setter_name) {
+        extractor_name = Field::SetterName(extractor_name);
+        if (!field.is_final()) {
+          const Instance& setter_closure =
+              Instance::ZoneHandle(Z, field.SetterClosure());
+          ASSERT(setter_closure.IsClosure());
+          // Note: the created closure is cached after it's created
+          // once. If eager compilation is desired, the compiler can
+          // be invoked here. The same applies for getters below.
+          return new(Z) LiteralNode(property_pos, setter_closure);
+        }
+      } else {
+        const Instance& getter_closure =
+            Instance::ZoneHandle(Z, field.GetterClosure());
+        ASSERT(getter_closure.IsClosure());
+        return new(Z) LiteralNode(property_pos, getter_closure);
+      }
+    } else {
+      Function& func = Function::Handle(Z);
+      if (is_setter_name) {
+        extractor_name = Field::SetterName(extractor_name);
+        func = cls.LookupStaticFunction(extractor_name);
+      } else {
+        func = cls.LookupStaticFunction(extractor_name);
+        if (func.IsNull()) {
+          const String& getter_name =
+              String::Handle(Z, Field::GetterName(extractor_name));
+          func = cls.LookupStaticFunction(getter_name);
+        }
+      }
+      if (!func.IsNull()) {
+        return CreateImplicitClosureNode(func, property_pos, NULL);
+      }
+    }
+    return ThrowNoSuchMethodError(property_pos,
+                                  cls,
+                                  extractor_name,
+                                  NULL,  // No arguments.
+                                  InvocationMirror::kStatic,
+                                  is_setter_name
+                                      ? InvocationMirror::kSetter
+                                      : InvocationMirror::kMethod,
+                                  NULL);  // No existing function.
+  }
+
+  // Closurization of instance getter, setter, method or operator.
+  if (is_setter_name) {
+    extractor_name = String::Concat(Symbols::SetterPrefix(), extractor_name);
+  }
+  extractor_name = String::Concat(Symbols::HashMark(), extractor_name);
+  extractor_name = Symbols::New(extractor_name);
+  return new(Z) InstanceGetterNode(property_pos, primary, extractor_name);
+}
+
+
 AstNode* Parser::ParsePostfixExpr() {
   TRACE_PARSER("ParsePostfixExpr");
   String* expr_ident =
       Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
   const intptr_t expr_pos = TokenPos();
   AstNode* expr = ParsePrimary();
-  expr = ParseSelectors(expr, false);
+  if (CurrentToken() == Token::kHASH) {
+    expr = LoadFieldIfUnresolved(expr);
+    expr = ParseClosurization(expr);
+  } else {
+    expr = ParseSelectors(expr, false);
+  }
   if (IsIncrementOperator(CurrentToken())) {
     TRACE_PARSER("IncrementOperator");
     if (!IsLegalAssignableSyntax(expr, TokenPos())) {
@@ -12004,6 +12260,9 @@
     SkipQualIdent();
   } else {
     *prefix = ParsePrefix();
+    if (!prefix->IsNull()) {
+      ExpectToken(Token::kPERIOD);
+    }
     type_name = CurrentLiteral()->raw();
     ConsumeToken();
 
@@ -12603,6 +12862,50 @@
 }
 
 
+RawFunction* Parser::BuildConstructorClosureFunction(const Function& ctr,
+                                                     intptr_t token_pos) {
+  ASSERT(ctr.kind() == RawFunction::kConstructor);
+  String& closure_name = String::Handle(Z, ctr.name());
+  closure_name = Symbols::FromConcat(Symbols::ConstructorClosurePrefix(),
+                                     closure_name);
+  ParamList params;
+  params.AddFinalParameter(token_pos,
+                           &Symbols::ClosureParameter(),
+                           &Type::ZoneHandle(Z, Type::DynamicType()));
+
+  ParseFormalParameters(ctr, &params);
+  // Per language spec, the type of the closure parameters is dynamic.
+  // Replace the types parsed from the constructor.
+  params.EraseParameterTypes();
+
+  Function& closure = Function::Handle(Z);
+  closure = Function::NewClosureFunction(closure_name,
+                                         innermost_function(),
+                                         token_pos);
+  closure.set_is_generated_body(true);
+  closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
+  AddFormalParamsToFunction(&params, closure);
+
+  // Create and set the signature class of the closure.
+  const String& sig = String::Handle(Z, closure.Signature());
+  Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
+  if (sig_cls.IsNull()) {
+    sig_cls = Class::NewSignatureClass(sig, closure, script_, token_pos);
+    library_.AddClass(sig_cls);
+  }
+  closure.set_signature_class(sig_cls);
+  const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
+  if (!sig_type.IsFinalized()) {
+    // Finalization would be premature when top-level parsing.
+    ASSERT(!is_top_level_);
+    ClassFinalizer::FinalizeType(sig_cls,
+                                 sig_type,
+                                 ClassFinalizer::kCanonicalize);
+  }
+  return closure.raw();
+}
+
+
 static String& BuildConstructorName(const String& type_class_name,
                                     const String* named_constructor) {
   // By convention, the static function implementing a named constructor 'C'
@@ -12618,6 +12921,61 @@
 }
 
 
+// Parse a primary expression of the form new T# or new T#m.
+// Current token position is after the keyword new. Extracts the
+// anonymous or named constructor and type arguments.
+// Note that type type T has already been parsed before
+// (by ParseNewOperator()) and is guaranteed to be well-formed,
+// and the constructor is known to exist.
+void Parser::ParseConstructorClosurization(Function* constructor,
+                                           TypeArguments* type_arguments) {
+  *constructor = Function::null();
+  *type_arguments = TypeArguments::null();
+  const Token::Kind la3 = LookaheadToken(3);
+  const bool consume_unresolved_prefix =
+      (la3 == Token::kLT) || (la3 == Token::kPERIOD) || (la3 == Token::kHASH);
+  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z);
+  AbstractType& type = AbstractType::Handle(Z,
+      ParseType(ClassFinalizer::kCanonicalizeWellFormed,
+      true,  // allow deferred type
+      consume_unresolved_prefix,
+      &prefix));
+  // A constructor tear-off closure can only have been created for a
+  // type that is loaded.
+  ASSERT(prefix.IsNull() || prefix.is_loaded());
+  ASSERT(!type.IsMalformed() && !type.IsTypeParameter());
+  ExpectToken(Token::kHASH);
+  String* named_constructor = NULL;
+  if (IsIdentifier()) {
+    named_constructor = CurrentLiteral();
+    ConsumeToken();
+  }
+  // Resolve the type and optional identifier to a constructor or factory.
+  Class& type_class = Class::Handle(Z, type.type_class());
+  String& type_class_name = String::Handle(Z, type_class.Name());
+  *type_arguments = type.arguments();
+  String& constructor_name =
+      BuildConstructorName(type_class_name, named_constructor);
+  *constructor = type_class.LookupConstructor(constructor_name);
+  if (constructor->IsNull()) {
+    *constructor = type_class.LookupFactory(constructor_name);
+    ASSERT(!constructor->IsNull());
+    if (constructor->IsRedirectingFactory()) {
+      ClassFinalizer::ResolveRedirectingFactory(type_class, *constructor);
+      type = constructor->RedirectionType();
+      ASSERT(!type.IsMalformedOrMalbounded());
+      if (!type.IsInstantiated()) {
+        Error& error = Error::Handle(Z);
+        type ^= type.InstantiateFrom(*type_arguments, &error);
+        ASSERT(error.IsNull());
+      }
+      *type_arguments = type.arguments();
+      *constructor = constructor->RedirectionTarget();
+    }
+  }
+}
+
+
 AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
   TRACE_PARSER("ParseNewOperator");
   const intptr_t new_pos = TokenPos();
@@ -12629,14 +12987,17 @@
   intptr_t type_pos = TokenPos();
   // Can't allocate const objects of a deferred type.
   const bool allow_deferred_type = !is_const;
-  const bool consume_unresolved_prefix = (LookaheadToken(3) == Token::kLT) ||
-                                         (LookaheadToken(3) == Token::kPERIOD);
+  const Token::Kind la3 = LookaheadToken(3);
+  const bool consume_unresolved_prefix =
+      (la3 == Token::kLT) || (la3 == Token::kPERIOD) || (la3 == Token::kHASH);
+
   LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z);
   AbstractType& type = AbstractType::Handle(Z,
       ParseType(ClassFinalizer::kCanonicalizeWellFormed,
                 allow_deferred_type,
                 consume_unresolved_prefix,
                 &prefix));
+
   if (FLAG_load_deferred_eagerly &&
       !prefix.IsNull() && prefix.is_deferred_load() && !prefix.is_loaded()) {
     // Add runtime check.
@@ -12674,20 +13035,37 @@
                 String::Handle(Z, type_class.Name()).ToCString());
   }
 
-  // The grammar allows for an optional ('.' identifier)? after the type, which
-  // is a named constructor. Note that we tell ParseType() above not to
-  // consume it as part of a misinterpreted qualified identifier. Only a
-  // valid library prefix is accepted as qualifier.
+  // The type can be followed by an optional named constructor identifier.
+  // Note that we tell ParseType() above not to consume it as part of
+  // a misinterpreted qualified identifier. Only a valid library
+  // prefix is accepted as qualifier.
   String* named_constructor = NULL;
-  if (CurrentToken() == Token::kPERIOD) {
+  const bool is_tearoff_expression = (CurrentToken() == Token::kHASH);
+  if (is_tearoff_expression) {
+    if (is_const) {
+      ReportError("tear-off closure not allowed with const allocation");
+    }
+    ConsumeToken();
+    if (IsIdentifier()) {
+      named_constructor = ExpectIdentifier("name of constructor expected");
+    }
+  } else if (CurrentToken() == Token::kPERIOD) {
     ConsumeToken();
     named_constructor = ExpectIdentifier("name of constructor expected");
   }
 
   // Parse constructor parameters.
-  CheckToken(Token::kLPAREN);
   intptr_t call_pos = TokenPos();
-  ArgumentListNode* arguments = ParseActualParameters(NULL, is_const);
+  ArgumentListNode* arguments = NULL;
+  if (!is_tearoff_expression) {
+    CheckToken(Token::kLPAREN);
+    call_pos = TokenPos();
+    arguments = ParseActualParameters(NULL, is_const);
+  } else {
+    // Allocate dummy node with no arguments so we don't have to deal
+    // with the NULL corner case below.
+    arguments = new(Z) ArgumentListNode(TokenPos());
+  }
 
   // Parsing is complete, so we can return a throw in case of a malformed or
   // malbounded type or report a compile-time error if the constructor is const.
@@ -12805,10 +13183,10 @@
       arguments_length -= 1;
     }
   }
+  ASSERT(!constructor.IsNull());
 
   // It is ok to call a factory method of an abstract class, but it is
   // a dynamic error to instantiate an abstract class.
-  ASSERT(!constructor.IsNull());
   if (type_class.is_abstract() && !constructor.IsFactory()) {
     // Evaluate arguments before throwing.
     LetNode* result = new(Z) LetNode(call_pos);
@@ -12826,6 +13204,32 @@
                        error_arguments));
     return result;
   }
+
+  type_arguments ^= type_arguments.Canonicalize();
+
+  if (is_tearoff_expression) {
+    const Function& tearoff_func = Function::ZoneHandle(Z,
+        BuildConstructorClosureFunction(constructor, new_pos));
+
+    // Local functions normally get parsed when the enclosing function is
+    // compiled. Since constructor tearoff closures don't get parsed here,
+    // we need to duplicate some of the side effects of parsing, namely
+    // creating a function scope, and capturing the instantiator of the
+    // enclosing function if necessary.
+    OpenFunctionBlock(tearoff_func);
+    // If there are type arguments in the tearoff expression that are
+    // not yet instantiated, capture the instantiator.
+    if (IsInstantiatorRequired() &&
+        !type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
+      CaptureInstantiator();
+    }
+    SequenceNode* tearoff_body = CloseBlock();
+    ClosureNode* closure_obj =
+        new(Z) ClosureNode(new_pos, tearoff_func, NULL, tearoff_body->scope());
+    return closure_obj;
+  }
+
+  ASSERT(!is_tearoff_expression);
   String& error_message = String::Handle(Z);
   if (!constructor.AreValidArguments(arguments_length,
                                      arguments->names(),
@@ -12857,7 +13261,7 @@
     }
     return ThrowTypeError(type_pos, type);
   }
-  type_arguments ^= type_arguments.Canonicalize();
+
   // Make the constructor call.
   AstNode* new_object = NULL;
   if (is_const) {
@@ -13071,6 +13475,14 @@
   } else if (IsIdentifier()) {
     intptr_t qual_ident_pos = TokenPos();
     const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z, ParsePrefix());
+    if (!prefix.IsNull()) {
+      if (CurrentToken() == Token::kHASH) {
+        // Closurization of top-level entity in prefix scope.
+        return new(Z) LiteralNode(qual_ident_pos, prefix);
+      } else {
+        ExpectToken(Token::kPERIOD);
+      }
+    }
     String& ident = *CurrentLiteral();
     ConsumeToken();
     if (prefix.IsNull()) {
@@ -13287,7 +13699,7 @@
                    script_, expr_pos,
                    "error evaluating constant expression");
     }
-    ASSERT(result.IsInstance());
+    ASSERT(result.IsInstance() || result.IsNull());
     Instance& value = Instance::ZoneHandle(Z);
     value ^= result.raw();
     value = TryCanonicalize(value, TokenPos());
@@ -13432,6 +13844,16 @@
   ConsumeToken();  // Skip new or const keyword.
   if (IsIdentifier()) {
     SkipType(false);
+    if (CurrentToken() == Token::kPERIOD) {
+      ConsumeToken();
+      ExpectIdentifier("identifier expected");
+    } else if (CurrentToken() == Token::kHASH) {
+      ConsumeToken();
+      if (IsIdentifier()) {
+        ConsumeToken();
+      }
+      return;
+    }
     if (CurrentToken() == Token::kLPAREN) {
       SkipActualParameters();
       return;
@@ -13550,6 +13972,16 @@
 
 void Parser::SkipPostfixExpr() {
   SkipPrimary();
+  if (CurrentToken() == Token::kHASH) {
+    if (IsIdentifier()) {
+      ConsumeToken();
+      SkipIf(Token::kASSIGN);
+    } else if (Token::CanBeOverloaded(CurrentToken())) {
+      ConsumeToken();
+    } else {
+      ReportError("identifier or operator expected");
+    }
+  }
   SkipSelectors();
   if (IsIncrementOperator(CurrentToken())) {
     ConsumeToken();
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 9cab860..2e74b1c 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -41,7 +41,7 @@
 class ParsedFunction : public ZoneAllocated {
  public:
   ParsedFunction(Thread* thread, const Function& function)
-      : isolate_(thread->isolate()),
+      : thread_(thread),
         function_(function),
         code_(Code::Handle(zone(), function.unoptimized_code())),
         node_sequence_(NULL),
@@ -150,11 +150,11 @@
   void record_await() { have_seen_await_expr_ = true; }
   bool have_seen_await() const { return have_seen_await_expr_; }
 
-  Isolate* isolate() const { return isolate_; }
-  Zone* zone() const { return isolate()->current_zone(); }
+  Isolate* isolate() const { return thread_->isolate(); }
+  Zone* zone() const { return thread_->zone(); }
 
  private:
-  Isolate* isolate_;
+  Thread* thread_;
   const Function& function_;
   Code& code_;
   SequenceNode* node_sequence_;
@@ -509,6 +509,8 @@
   AstNode* ParseSuperOperator();
   AstNode* BuildUnarySuperOperator(Token::Kind op, PrimaryNode* super);
 
+  static bool ParseFormalParameters(const Function& func, ParamList* params);
+
   static void SetupDefaultsForOptionalParams(const ParamList* params,
                                              Array* default_values);
   ClosureNode* CreateImplicitClosureNode(const Function& func,
@@ -536,6 +538,8 @@
                                            Array* default_values);
   SequenceNode* ParseImplicitClosure(const Function& func,
                                      Array* default_values);
+  SequenceNode* ParseConstructorClosure(const Function& func,
+                                        Array* default_values);
 
   void BuildDispatcherScope(const Function& func,
                             const ArgumentsDescriptor& desc,
@@ -694,6 +698,7 @@
   AstNode* ParseUnaryExpr();
   AstNode* ParsePostfixExpr();
   AstNode* ParseSelectors(AstNode* primary, bool is_cascade);
+  AstNode* ParseClosurization(AstNode* primary);
   AstNode* ParseCascades(AstNode* expr);
   AstNode* ParsePrimary();
   AstNode* ParseStringLiteral(bool allow_interpolation);
@@ -706,7 +711,12 @@
   AstNode* ParseMapLiteral(intptr_t type_pos,
                            bool is_const,
                            const TypeArguments& type_arguments);
+
+  RawFunction* BuildConstructorClosureFunction(const Function& ctr,
+                                               intptr_t token_pos);
   AstNode* ParseNewOperator(Token::Kind op_kind);
+  void ParseConstructorClosurization(Function* constructor,
+                                     TypeArguments* type_arguments);
 
   // An implicit argument, if non-null, is prepended to the returned list.
   ArgumentListNode* ParseActualParameters(ArgumentListNode* implicit_arguments,
@@ -807,9 +817,10 @@
   RawInstance* TryCanonicalize(const Instance& instance, intptr_t token_pos);
 
   Isolate* isolate() const { return isolate_; }
-  Zone* zone() const { return isolate()->current_zone(); }
+  Zone* zone() const { return thread_->zone(); }
 
   Isolate* isolate_;  // Cached current isolate.
+  Thread* thread_;
 
   Script& script_;
   TokenStream::Iterator tokens_iterator_;
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
new file mode 100644
index 0000000..52287f3
--- /dev/null
+++ b/runtime/vm/precompiler.cc
@@ -0,0 +1,594 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/precompiler.h"
+
+#include "vm/compiler.h"
+#include "vm/isolate.h"
+#include "vm/longjump.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/resolver.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+
+#define I (isolate())
+#define Z (zone())
+
+
+DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler.");
+
+
+static void Jump(const Error& error) {
+  Isolate::Current()->long_jump_base()->Jump(1, error);
+}
+
+
+RawError* Precompiler::CompileAll() {
+  LongJumpScope jump;
+  if (setjmp(*jump.Set()) == 0) {
+    Precompiler precompiler(Thread::Current());
+    precompiler.DoCompileAll();
+    return Error::null();
+  } else {
+    Isolate* isolate = Isolate::Current();
+    const Error& error = Error::Handle(isolate->object_store()->sticky_error());
+    isolate->object_store()->clear_sticky_error();
+    return error.raw();
+  }
+}
+
+
+Precompiler::Precompiler(Thread* thread) :
+  thread_(thread),
+  zone_(thread->zone()),
+  isolate_(thread->isolate()),
+  changed_(false),
+  function_count_(0),
+  class_count_(0),
+  libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())),
+  pending_functions_(GrowableObjectArray::Handle(Z,
+                                                 GrowableObjectArray::New())),
+  collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())),
+  sent_selectors_(GrowableObjectArray::Handle(Z, GrowableObjectArray::New())),
+  error_(Error::Handle(Z)) {
+}
+
+
+void Precompiler::DoCompileAll() {
+  // Drop all existing code so we can use the presence of code as an indicator
+  // that we have already looked for the function's callees.
+  ClearAllCode();
+
+  // Start with the allocations and invocations that happen from C++.
+  AddRoots();
+
+  // TODO(rmacnak): Eagerly add field-invocation functions to all signature
+  // classes so closure calls don't go through the runtime.
+
+  // Compile newly found targets and add their callees until we reach a fixed
+  // point.
+  Iterate();
+
+  CleanUp();
+
+  if (FLAG_trace_precompiler) {
+    OS::Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
+              " %" Pd " dynamic selectors\n",
+              function_count_,
+              class_count_,
+              sent_selectors_.Length());
+  }
+
+  I->set_compilation_allowed(false);
+}
+
+
+void Precompiler::ClearAllCode() {
+  Library& lib = Library::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  Array& functions = Array::Handle(Z);
+  Function& function = Function::Handle(Z);
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      error_ = cls.EnsureIsFinalized(I);
+      if (!error_.IsNull()) {
+        Jump(error_);
+      }
+    }
+  }
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      functions = cls.functions();
+      for (intptr_t i = 0; i < functions.Length(); i++) {
+        function ^= functions.At(i);
+        function.ClearCode();
+      }
+    }
+  }
+}
+
+
+void Precompiler::AddRoots() {
+  // Note that <rootlibrary>.main is not a root. The appropriate main will be
+  // discovered through _getMainClosure.
+
+  AddSelector(Symbols::NoSuchMethod());
+
+  AddSelector(Symbols::Call());  // For speed, not correctness.
+
+  // Allocated from C++.
+  static const intptr_t kExternallyAllocatedCids[] = {
+    kBoolCid,
+    kNullCid,
+
+    kSmiCid,
+    kMintCid,
+    kBigintCid,
+    kDoubleCid,
+
+    kOneByteStringCid,
+    kTwoByteStringCid,
+    kExternalOneByteStringCid,
+    kExternalTwoByteStringCid,
+
+    kArrayCid,
+    kImmutableArrayCid,
+    kGrowableObjectArrayCid,
+    kLinkedHashMapCid,
+
+    kTypedDataUint8ClampedArrayCid,
+    kTypedDataUint8ArrayCid,
+    kTypedDataUint16ArrayCid,
+    kTypedDataUint32ArrayCid,
+    kTypedDataUint64ArrayCid,
+
+    kTypedDataInt8ArrayCid,
+    kTypedDataInt16ArrayCid,
+    kTypedDataInt32ArrayCid,
+    kTypedDataInt64ArrayCid,
+
+    kExternalTypedDataUint8ArrayCid,
+
+    kTypedDataFloat32ArrayCid,
+    kTypedDataFloat64ArrayCid,
+
+    kTypedDataFloat32x4ArrayCid,
+    kTypedDataInt32x4ArrayCid,
+    kTypedDataFloat64x2ArrayCid,
+
+    kInt32x4Cid,
+    kFloat32x4Cid,
+    kFloat64x2Cid,
+
+    kTypeCid,
+    kTypeRefCid,
+    kTypeParameterCid,
+    kBoundedTypeCid,
+    kLibraryPrefixCid,
+
+    kJSRegExpCid,
+    kUserTagCid,
+    kStacktraceCid,
+    kWeakPropertyCid,
+    kCapabilityCid,
+    ReceivePort::kClassId,
+    SendPort::kClassId,
+
+    kIllegalCid
+  };
+
+  Class& cls = Class::Handle(Z);
+  for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) {
+    cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]);
+    AddClass(cls);
+  }
+
+  static const struct {
+    const char* library_;
+    const char* class_;
+    const char* function_;
+  } kExternallyCalled[] = {
+    { "dart:_builtin", "::", "_getMainClosure" },
+    { "dart:_builtin", "::", "_getPrintClosure" },
+    { "dart:_builtin", "::", "_getUriBaseClosure" },
+    { "dart:_builtin", "::", "_resolveUri" },
+    { "dart:_builtin", "::", "_setWorkingDirectory" },
+    { "dart:async", "::", "_setScheduleImmediateClosure" },
+    { "dart:core", "_InternalError", "_InternalError." },
+    { "dart:core", "_InvocationMirror", "_allocateInvocationMirror" },
+    { "dart:io", "::", "_makeUint8ListView" },
+    { "dart:io", "::", "_makeDatagram" },
+    { "dart:io", "CertificateException", "CertificateException." },
+    { "dart:io", "HandshakeException", "HandshakeException." },
+    { "dart:io", "TlsException", "TlsException." },
+    { "dart:io", "X509Certificate", "X509Certificate." },
+    { "dart:io", "_ExternalBuffer", "set:data" },
+    { "dart:io", "_Platform", "set:_nativeScript" },
+    { "dart:io", "_ProcessStartStatus", "set:_errorCode" },
+    { "dart:io", "_ProcessStartStatus", "set:_errorMessage" },
+    { "dart:io", "_SecureFilterImpl", "get:ENCRYPTED_SIZE" },
+    { "dart:io", "_SecureFilterImpl", "get:SIZE" },
+    { "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" },
+    { "dart:isolate", "::", "_startMainIsolate" },
+    { "dart:isolate", "_RawReceivePortImpl", "_handleMessage" },
+    { "dart:isolate", "_RawReceivePortImpl", "_lookupHandler" },
+    { "dart:vmservice", "::", "_registerIsolate" },
+    { "dart:vmservice", "::", "boot" },
+    { "dart:vmservice_io", "::", "_addResource" },
+    { "dart:vmservice_io", "::", "main" },
+
+    // Cf. Exceptions::Create
+    { "dart:core", "RangeError", "RangeError." },
+    { "dart:core", "RangeError", "RangeError.range" },
+    { "dart:core", "ArgumentError", "ArgumentError." },
+    { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" },
+    { "dart:core", "FormatException", "FormatException." },
+    { "dart:core", "UnsupportedError", "UnsupportedError." },
+    { "dart:core", "NullThrownError", "NullThrownError." },
+    { "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." },
+    { "dart:isolate", "_IsolateUnhandledException",
+                      "_IsolateUnhandledException." },
+    { "dart:core", "_JavascriptIntegerOverflowError",
+                   "_JavascriptIntegerOverflowError." },
+    { "dart:core", "_JavascriptCompatibilityError",
+                   "_JavascriptCompatibilityError." },
+    { "dart:core", "AssertionError", "AssertionError." },
+    { "dart:core", "_CastError", "_CastError._create" },
+    { "dart:core", "_TypeError", "_TypeError._create" },
+    { "dart:core", "FallThroughError", "FallThroughError._create" },
+    { "dart:core", "AbstractClassInstantiationError",
+                   "AbstractClassInstantiationError._create" },
+    { "dart:core", "CyclicInitializationError",
+                   "CyclicInitializationError." },
+    { "dart:core", "StackOverflowError", "StackOverflowError." },
+    { "dart:core", "OutOfMemoryError", "OutOfMemoryError." },
+    { NULL, NULL, NULL }
+  };
+
+  Library& lib = Library::Handle(Z);
+  Function& func = Function::Handle(Z);
+  String& library_name = String::Handle(Z);
+  String& class_name = String::Handle(Z);
+  String& function_name = String::Handle(Z);
+  for (intptr_t i = 0; kExternallyCalled[i].library_ != NULL; i++) {
+    library_name = Symbols::New(kExternallyCalled[i].library_);
+    class_name = Symbols::New(kExternallyCalled[i].class_);
+    function_name = Symbols::New(kExternallyCalled[i].function_);
+
+    lib = Library::LookupLibrary(library_name);
+    if (lib.IsNull()) {
+      if (FLAG_trace_precompiler) {
+        OS::Print("WARNING: Missing %s\n", kExternallyCalled[i].library_);
+      }
+      continue;
+    }
+
+    if (class_name.raw() == Symbols::TopLevel().raw()) {
+      func = lib.LookupFunctionAllowPrivate(function_name);
+    } else {
+      cls = lib.LookupClassAllowPrivate(class_name);
+      if (cls.IsNull()) {
+        if (FLAG_trace_precompiler) {
+          OS::Print("WARNING: Missing %s %s\n",
+                    kExternallyCalled[i].library_,
+                    kExternallyCalled[i].class_);
+        }
+        continue;
+      }
+
+      ASSERT(!cls.IsNull());
+      func = cls.LookupFunctionAllowPrivate(function_name);
+    }
+
+    if (func.IsNull()) {
+      if (FLAG_trace_precompiler) {
+        OS::Print("WARNING: Missing %s %s %s\n",
+                  kExternallyCalled[i].library_,
+                  kExternallyCalled[i].class_,
+                  kExternallyCalled[i].function_);
+      }
+      continue;
+    }
+
+    AddFunction(func);
+  }
+}
+
+
+void Precompiler::Iterate() {
+  Function& function = Function::Handle(Z);
+
+  while (changed_) {
+    changed_ = false;
+
+    while (pending_functions_.Length() > 0) {
+      function ^= pending_functions_.RemoveLast();
+      ProcessFunction(function);
+    }
+
+    CheckForNewDynamicFunctions();
+
+    // Drain collected_closures last because additions to this list come from
+    // outside the Precompiler and so do not flip our changed_ flag.
+    while (collected_closures_.Length() > 0) {
+      function ^= collected_closures_.RemoveLast();
+      ProcessFunction(function);
+    }
+  }
+}
+
+
+void Precompiler::CleanUp() {
+  I->set_collected_closures(GrowableObjectArray::Handle(Z));
+
+  // TODO(rmacnak): Drop functions without code, classes without functions, etc.
+}
+
+
+void Precompiler::ProcessFunction(const Function& function) {
+  if (!function.HasCode()) {
+    function_count_++;
+
+    if (FLAG_trace_precompiler) {
+      OS::Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
+                function_count_,
+                function.ToLibNamePrefixedQualifiedCString(),
+                function.token_pos(),
+                Function::KindToCString(function.kind()));
+    }
+
+    ASSERT(!function.is_abstract());
+    ASSERT(!function.IsRedirectingFactory());
+
+    error_ = Compiler::CompileFunction(thread_, function);
+    if (!error_.IsNull()) {
+      Jump(error_);
+    }
+  }
+
+  ASSERT(function.HasCode());
+  AddCalleesOf(function);
+}
+
+
+void Precompiler::AddCalleesOf(const Function& function) {
+  ASSERT(function.HasCode());
+
+  const Code& code = Code::Handle(Z, function.CurrentCode());
+
+  const Array& table = Array::Handle(Z, code.static_calls_target_table());
+  Object& entry = Object::Handle(Z);
+  Function& target = Function::Handle(Z);
+  for (intptr_t i = 0; i < table.Length(); i++) {
+    entry = table.At(i);
+    if (entry.IsFunction()) {
+      target ^= table.At(i);
+      AddFunction(target);
+    }
+  }
+
+#if defined(TARGET_ARCH_IA32)
+  FATAL("Callee scanning unimplemented for IA32");
+#endif
+
+  const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool());
+  ICData& call_site = ICData::Handle(Z);
+  String& selector = String::Handle(Z);
+  Field& field = Field::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  for (intptr_t i = 0; i < pool.Length(); i++) {
+    if (pool.InfoAt(i) == ObjectPool::kTaggedObject) {
+      entry = pool.ObjectAt(i);
+      if (entry.IsICData()) {
+        call_site ^= entry.raw();
+        if (call_site.NumberOfChecks() == 1) {
+          // Probably a static call.
+          target = call_site.GetTargetAt(0);
+          AddFunction(target);
+          if (!target.is_static()) {
+            // Super call (should not enqueue selector) or dynamic call with a
+            // CHA prediction (should enqueue selector).
+            selector = call_site.target_name();
+            AddSelector(selector);
+          }
+        } else {
+          // A dynamic call.
+          selector = call_site.target_name();
+          AddSelector(selector);
+        }
+      } else if (entry.IsField()) {
+        // Potential need for field initializer.
+        field ^= entry.raw();
+        AddField(field);
+      } else if (entry.IsInstance()) {
+        // Potential const object.
+        cls = entry.clazz();
+        AddClass(cls);
+      }
+    }
+  }
+}
+
+
+void Precompiler::AddField(const Field& field) {
+  if (field.is_static()) {
+    // Potential const object. Uninitialized field will harmlessly do a
+    // redundant add of the Null class.
+    const Object& value = Object::Handle(Z, field.value());
+    const Class& cls = Class::Handle(Z, value.clazz());
+    AddClass(cls);
+
+    if (field.has_initializer()) {
+      if (field.initializer() != Function::null()) return;
+
+      if (FLAG_trace_precompiler) {
+        OS::Print("Precompiling initializer for %s\n", field.ToCString());
+      }
+      Compiler::CompileStaticInitializer(field);
+
+      const Function& function = Function::Handle(Z, field.initializer());
+      AddCalleesOf(function);
+    }
+  }
+}
+
+
+void Precompiler::AddFunction(const Function& function) {
+  if (function.HasCode()) return;
+
+  pending_functions_.Add(function);
+  changed_ = true;
+}
+
+
+bool Precompiler::IsSent(const String& selector) {
+  ASSERT(selector.IsSymbol());
+
+  // TODO(rmacnak): Use a proper set.
+  for (intptr_t i = 0; i < sent_selectors_.Length(); i++) {
+    if (sent_selectors_.At(i) == selector.raw()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+void Precompiler::AddSelector(const String& selector) {
+  if (!IsSent(selector)) {
+    if (FLAG_trace_precompiler) {
+      OS::Print("Enqueueing selector %" Pd " %s\n",
+                sent_selectors_.Length(),
+                selector.ToCString());
+    }
+
+    sent_selectors_.Add(selector);
+    changed_ = true;
+
+    if (!Field::IsGetterName(selector) &&
+        !Field::IsSetterName(selector)) {
+      // Regular method may be call-through-getter.
+      // TODO(rmacnak): Do not create the symbol if it does not already exist.
+      String& getter = String::Handle(Field::GetterName(selector));
+      getter = Symbols::New(getter);
+      AddSelector(getter);
+    }
+  }
+}
+
+
+void Precompiler::AddClass(const Class& cls) {
+  if (cls.is_allocated()) return;
+
+  class_count_++;
+  cls.set_is_allocated();
+  changed_ = true;
+
+  if (FLAG_trace_precompiler) {
+    OS::Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString());
+  }
+
+  const Class& superclass = Class::Handle(cls.SuperClass());
+  if (!superclass.IsNull()) {
+    AddClass(superclass);
+  }
+}
+
+
+void Precompiler::CheckForNewDynamicFunctions() {
+  Library& lib = Library::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  Array& functions = Array::Handle(Z);
+  Function& function = Function::Handle(Z);
+  String& selector = String::Handle(Z);
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+
+      if (!cls.is_allocated()) {
+        bool has_compiled_constructor = false;
+        if (cls.allocation_stub() != Code::null()) {
+          // Regular objects.
+          has_compiled_constructor = true;
+        } else if (cls.is_synthesized_class()) {
+          // Enums.
+          has_compiled_constructor = true;
+        } else {
+          // Objects only allocated via const constructors, and not stored in a
+          // static field or code.
+          // E.g. A in
+          //   class A {
+          //     const A();
+          //     toString() => "Don't drop me!";
+          //   }
+          //   class B {
+          //     const a = const A();
+          //     const B();
+          //     static const theB = const B();
+          //   }
+          //   main() => print(B.theB.a);
+          functions = cls.functions();
+          for (intptr_t k = 0; k < functions.Length(); k++) {
+            function ^= functions.At(k);
+            if (function.IsGenerativeConstructor() &&
+                function.HasCode()) {
+              has_compiled_constructor = true;
+              break;
+            }
+          }
+        }
+        if (!has_compiled_constructor) {
+          continue;
+        }
+        AddClass(cls);
+      }
+
+      functions = cls.functions();
+      for (intptr_t k = 0; k < functions.Length(); k++) {
+        function ^= functions.At(k);
+
+        if (function.is_static() || function.is_abstract()) continue;
+
+        // Don't bail out early if there is already code because we may discover
+        // the corresponding getter selector is sent in some later iteration.
+        // if (function.HasCode()) continue;
+
+        selector = function.name();
+        if (IsSent(selector)) {
+          AddFunction(function);
+        }
+
+        if (function.kind() == RawFunction::kRegularFunction &&
+            !Field::IsGetterName(selector) &&
+            !Field::IsSetterName(selector)) {
+          // TODO(rmacnak): Do not create the symbol if it does not already
+          // exist.
+          selector = Field::GetterName(selector);
+          selector = Symbols::New(selector);
+          if (IsSent(selector)) {
+            function = function.ImplicitClosureFunction();
+            AddFunction(function);
+          }
+        }
+      }
+    }
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
new file mode 100644
index 0000000..158a8ba
--- /dev/null
+++ b/runtime/vm/precompiler.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_PRECOMPILER_H_
+#define VM_PRECOMPILER_H_
+
+#include "vm/allocation.h"
+
+namespace dart {
+
+// Forward declarations.
+class Class;
+class Error;
+class Field;
+class Function;
+class GrowableObjectArray;
+class RawError;
+class String;
+
+class Precompiler : public ValueObject {
+ public:
+  static RawError* CompileAll();
+
+ private:
+  explicit Precompiler(Thread* thread);
+
+  void DoCompileAll();
+  void ClearAllCode();
+  void AddRoots();
+  void Iterate();
+  void CleanUp();
+
+  void AddCalleesOf(const Function& function);
+  void AddField(const Field& field);
+  void AddFunction(const Function& function);
+  void AddClass(const Class& cls);
+  void AddSelector(const String& selector);
+  bool IsSent(const String& selector);
+
+  void ProcessFunction(const Function& function);
+  void CheckForNewDynamicFunctions();
+
+  Thread* thread() const { return thread_; }
+  Zone* zone() const { return zone_; }
+  Isolate* isolate() const { return isolate_; }
+
+  Thread* thread_;
+  Zone* zone_;
+  Isolate* isolate_;
+
+  bool changed_;
+  intptr_t function_count_;
+  intptr_t class_count_;
+
+  const GrowableObjectArray& libraries_;
+  const GrowableObjectArray& pending_functions_;
+  const GrowableObjectArray& collected_closures_;
+  const GrowableObjectArray& sent_selectors_;
+  Error& error_;
+};
+
+}  // namespace dart
+
+#endif  // VM_PRECOMPILER_H_
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index b674952..ff0edc7 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -439,15 +439,13 @@
 // Executing Dart code, walk the stack.
 class ProfilerDartStackWalker : public ValueObject {
  public:
-  ProfilerDartStackWalker(Isolate* isolate,
-                          Sample* sample,
+  ProfilerDartStackWalker(Sample* sample,
                           uword stack_lower,
                           uword stack_upper,
                           uword pc,
                           uword fp,
                           uword sp)
-      : isolate_(isolate),
-        sample_(sample),
+      : sample_(sample),
         stack_upper_(stack_upper),
         stack_lower_(stack_lower) {
     ASSERT(sample_ != NULL);
@@ -464,7 +462,7 @@
     }
     ASSERT(ValidFramePointer());
     uword return_pc = InitialReturnAddress();
-    if (StubCode::InInvocationStubForIsolate(isolate_, return_pc)) {
+    if (StubCode::InInvocationStub(return_pc)) {
       // Edge case- we have called out from the Invocation Stub but have not
       // created the stack frame of the callee. Attempt to locate the exit
       // frame before walking the stack.
@@ -488,16 +486,14 @@
     if (!ValidFramePointer()) {
       return false;
     }
-    if (StubCode::InInvocationStubForIsolate(isolate_,
-                                             reinterpret_cast<uword>(pc_))) {
+    if (StubCode::InInvocationStub(reinterpret_cast<uword>(pc_))) {
       // In invocation stub.
       return NextExit();
     }
     // In regular Dart frame.
     uword* new_pc = CallerPC();
     // Check if we've moved into the invocation stub.
-    if (StubCode::InInvocationStubForIsolate(isolate_,
-                                             reinterpret_cast<uword>(new_pc))) {
+    if (StubCode::InInvocationStub(reinterpret_cast<uword>(new_pc))) {
       // New PC is inside invocation stub, skip.
       return NextExit();
     }
@@ -585,7 +581,6 @@
   uword* pc_;
   uword* fp_;
   uword* sp_;
-  Isolate* isolate_;
   Sample* sample_;
   const uword stack_upper_;
   uword stack_lower_;
@@ -827,8 +822,7 @@
   }
   ASSERT(isolate != Dart::vm_isolate());
 
-  const bool exited_dart_code = (isolate->stub_code() != NULL) &&
-                                (isolate->top_exit_frame_info() != 0) &&
+  const bool exited_dart_code = (isolate->top_exit_frame_info() != 0) &&
                                 (isolate->vm_tag() != VMTag::kDartTagId);
 
   if (!exited_dart_code) {
@@ -883,11 +877,9 @@
 
   ASSERT(isolate != Dart::vm_isolate());
 
-  const bool exited_dart_code = (isolate->stub_code() != NULL) &&
-                                (isolate->top_exit_frame_info() != 0) &&
+  const bool exited_dart_code = (isolate->top_exit_frame_info() != 0) &&
                                 (isolate->vm_tag() != VMTag::kDartTagId);
-  const bool in_dart_code = (isolate->stub_code() != NULL) &&
-                            (isolate->top_exit_frame_info() == 0) &&
+  const bool in_dart_code = (isolate->top_exit_frame_info() == 0) &&
                             (isolate->vm_tag() == VMTag::kDartTagId);
 
   uintptr_t sp = 0;
@@ -1018,8 +1010,7 @@
 
   ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
 
-  ProfilerDartStackWalker dart_stack_walker(isolate,
-                                            sample,
+  ProfilerDartStackWalker dart_stack_walker(sample,
                                             stack_lower,
                                             stack_upper,
                                             pc,
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index bf47f20..872b600 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -97,7 +97,8 @@
       table_index_(table_index),
       profile_codes_(0),
       exclusive_ticks_(0),
-      inclusive_ticks_(0) {
+      inclusive_ticks_(0),
+      inclusive_serial_(-1) {
   ASSERT((kind_ != kDartFunction) || !function_.IsNull());
   ASSERT((kind_ != kDartFunction) || (table_index_ >= 0));
   ASSERT(profile_codes_.length() == 0);
@@ -117,14 +118,14 @@
 void ProfileFunction::Tick(bool exclusive, intptr_t inclusive_serial) {
   if (exclusive) {
     exclusive_ticks_++;
-  } else {
-    if (inclusive_serial_ == inclusive_serial) {
-      // Already ticket.
-      return;
-    }
-    inclusive_serial_ = inclusive_serial;
-    inclusive_ticks_++;
   }
+  // Fall through and tick inclusive count too.
+  if (inclusive_serial_ == inclusive_serial) {
+    // Already ticked.
+    return;
+  }
+  inclusive_serial_ = inclusive_serial;
+  inclusive_ticks_++;
 }
 
 
@@ -268,17 +269,19 @@
 
 
 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) {
+  // If exclusive is set, tick it.
   if (exclusive) {
     exclusive_ticks_++;
-  } else {
-    if (inclusive_serial_ == serial) {
-      // Already ticked for this sample.
-      return;
-    }
-    inclusive_serial_ = serial;
-    inclusive_ticks_++;
+    TickAddress(pc, true);
   }
-  TickAddress(pc, exclusive);
+  // Fall through and tick inclusive count too.
+  if (inclusive_serial_ == serial) {
+    // Already gave inclusive tick for this sample.
+    return;
+  }
+  inclusive_serial_ = serial;
+  inclusive_ticks_++;
+  TickAddress(pc, false);
 }
 
 
@@ -578,11 +581,34 @@
         ASSERT(tag_name != NULL);
         SetName(tag_name);
       } else {
-        if (start() == VMTag::kRootTagId) {
-          SetName("Root");
-        } else {
-          ASSERT(start() == VMTag::kTruncatedTagId);
-          SetName("[Truncated]");
+        switch (start()) {
+          case VMTag::kRootTagId:
+            SetName("Root");
+            break;
+          case VMTag::kTruncatedTagId:
+            SetName("[Truncated]");
+            break;
+          case VMTag::kNoneCodeTagId:
+            SetName("[No Code]");
+            break;
+          case VMTag::kOptimizedCodeTagId:
+            SetName("[Optimized Code]");
+            break;
+          case VMTag::kUnoptimizedCodeTagId:
+            SetName("[Unoptimized Code]");
+            break;
+          case VMTag::kNativeCodeTagId:
+            SetName("[Native Code]");
+            break;
+          case VMTag::kInlineStartCodeTagId:
+            SetName("[Inline Start]");
+            break;
+          case VMTag::kInlineEndCodeTagId:
+            SetName("[Inline End]");
+            break;
+          default:
+            UNIMPLEMENTED();
+          break;
         }
       }
     }
@@ -948,20 +974,34 @@
 
 class ProfileBuilder : public ValueObject {
  public:
+  enum ProfileInfoKind {
+    kNone,
+    kOptimized,
+    kUnoptimized,
+    kNative,
+    kInlineStart,
+    kInlineFinish,
+    kNumProfileInfoKind,
+  };
+
   ProfileBuilder(Isolate* isolate,
                  SampleFilter* filter,
                  Profile::TagOrder tag_order,
+                 intptr_t extra_tags,
                  Profile* profile)
       : isolate_(isolate),
         vm_isolate_(Dart::vm_isolate()),
         filter_(filter),
         tag_order_(tag_order),
+        extra_tags_(extra_tags),
         profile_(profile),
         deoptimized_code_(new DeoptimizedCodeSet(isolate)),
         null_code_(Code::ZoneHandle()),
         null_function_(Function::ZoneHandle()),
         tick_functions_(false),
-        samples_(NULL) {
+        inclusive_tree_(false),
+        samples_(NULL),
+        info_kind_(kNone) {
     ASSERT(profile_ != NULL);
   }
 
@@ -982,6 +1022,12 @@
   }
 
  private:
+  // Returns true if |frame_index| in |sample| is using CPU.
+  static bool IsExecutingFrame(ProcessedSample* sample, intptr_t frame_index) {
+    return (frame_index == 0) && (sample->first_frame_executing() ||
+                                  sample->IsAllocationSample());
+  }
+
   static bool IsInclusiveTrie(Profile::TrieKind kind) {
     return (kind == Profile::kInclusiveFunction) ||
            (kind == Profile::kInclusiveCode);
@@ -995,6 +1041,12 @@
     // Register some synthetic tags.
     RegisterProfileCodeTag(VMTag::kRootTagId);
     RegisterProfileCodeTag(VMTag::kTruncatedTagId);
+    RegisterProfileCodeTag(VMTag::kNoneCodeTagId);
+    RegisterProfileCodeTag(VMTag::kOptimizedCodeTagId);
+    RegisterProfileCodeTag(VMTag::kUnoptimizedCodeTagId);
+    RegisterProfileCodeTag(VMTag::kNativeCodeTagId);
+    RegisterProfileCodeTag(VMTag::kInlineStartCodeTagId);
+    RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId);
   }
 
   void FilterSamples() {
@@ -1021,8 +1073,10 @@
 
   void BuildCodeTable() {
     ScopeTimer sw("ProfileBuilder::BuildCodeTable", FLAG_trace_profiler);
-    for (intptr_t i = 0; i < samples_->length(); i++) {
-      ProcessedSample* sample = samples_->At(i);
+    for (intptr_t sample_index = 0;
+         sample_index < samples_->length();
+         sample_index++) {
+      ProcessedSample* sample = samples_->At(sample_index);
       const int64_t timestamp = sample->timestamp();
 
       // This is our first pass over the sample buffer, use this as an
@@ -1041,12 +1095,14 @@
 
       // Make sure that a ProfileCode objects exist for all pcs in the sample
       // and tick each one.
-      for (intptr_t i = 0; i < sample->length(); i++) {
-        const uword pc = sample->At(i);
+      for (intptr_t frame_index = 0;
+           frame_index < sample->length();
+           frame_index++) {
+        const uword pc = sample->At(frame_index);
         ASSERT(pc != 0);
         ProfileCode* code = RegisterProfileCode(pc, timestamp);
         ASSERT(code != NULL);
-        code->Tick(pc, (i == 0), i);
+        code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index);
       }
     }
   }
@@ -1113,7 +1169,8 @@
   void BuildCodeTrie(Profile::TrieKind kind) {
     ProfileCodeTrieNode* root =
         new ProfileCodeTrieNode(GetProfileCodeTagIndex(VMTag::kRootTagId));
-    if (IsInclusiveTrie(kind)) {
+    inclusive_tree_ = IsInclusiveTrie(kind);
+    if (inclusive_tree_) {
       BuildInclusiveCodeTrie(root);
     } else {
       BuildExclusiveCodeTrie(root);
@@ -1125,8 +1182,10 @@
   void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) {
     ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie",
                   FLAG_trace_profiler);
-    for (intptr_t i = 0; i < samples_->length(); i++) {
-      ProcessedSample* sample = samples_->At(i);
+    for (intptr_t sample_index = 0;
+         sample_index < samples_->length();
+         sample_index++) {
+      ProcessedSample* sample = samples_->At(sample_index);
 
       // Tick the root.
       ProfileCodeTrieNode* current = root;
@@ -1135,17 +1194,27 @@
       // VM & User tags.
       current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
 
+      ResetKind();
+
       // Truncated tag.
       if (sample->truncated()) {
         current = AppendTruncatedTag(current);
       }
 
       // Walk the sampled PCs.
-      for (intptr_t j = sample->length() - 1; j >= 0; j--) {
-        ASSERT(sample->At(j) != 0);
+      Code& code = Code::Handle();
+      for (intptr_t frame_index = sample->length() - 1;
+           frame_index >= 0;
+           frame_index--) {
+        ASSERT(sample->At(frame_index) != 0);
         intptr_t index =
-            GetProfileCodeIndex(sample->At(j), sample->timestamp());
+            GetProfileCodeIndex(sample->At(frame_index), sample->timestamp());
         ASSERT(index >= 0);
+        ProfileCode* profile_code =
+            GetProfileCode(sample->At(frame_index), sample->timestamp());
+        ASSERT(profile_code->code_table_index() == index);
+        code ^= profile_code->code();
+        current = AppendKind(code, current);
         current = current->GetChild(index);
         current->Tick();
       }
@@ -1155,8 +1224,10 @@
   void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) {
     ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie",
                   FLAG_trace_profiler);
-    for (intptr_t i = 0; i < samples_->length(); i++) {
-      ProcessedSample* sample = samples_->At(i);
+    for (intptr_t sample_index = 0;
+         sample_index < samples_->length();
+         sample_index++) {
+      ProcessedSample* sample = samples_->At(sample_index);
 
       // Tick the root.
       ProfileCodeTrieNode* current = root;
@@ -1165,28 +1236,27 @@
       // VM & User tags.
       current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
 
-      // Walk the sampled PCs.
-      for (intptr_t j = 0; j < sample->length(); j++) {
-        ASSERT(sample->At(j) != 0);
-        intptr_t index =
-            GetProfileCodeIndex(sample->At(j), sample->timestamp());
-        ASSERT(index >= 0);
-        current = current->GetChild(index);
+      ResetKind();
 
-        if (j == 0) {
-          // Executing PC.
-          if (!sample->first_frame_executing() || vm_tags_emitted()) {
-            // Only tick if this isn't an exit frame or VM tags are emitted.
-            current->Tick();
-          }
-        } else {
-          // Caller PCs.
+      // Walk the sampled PCs.
+      Code& code = Code::Handle();
+      for (intptr_t frame_index = 0;
+           frame_index < sample->length();
+           frame_index++) {
+        ASSERT(sample->At(frame_index) != 0);
+        intptr_t index =
+            GetProfileCodeIndex(sample->At(frame_index), sample->timestamp());
+        ASSERT(index >= 0);
+        ProfileCode* profile_code =
+            GetProfileCode(sample->At(frame_index), sample->timestamp());
+        ASSERT(profile_code->code_table_index() == index);
+        code ^= profile_code->code();
+        current = current->GetChild(index);
+        if (ShouldTickNode(sample, frame_index)) {
           current->Tick();
         }
-
-        current->Tick();
+        current = AppendKind(code, current);
       }
-
       // Truncated tag.
       if (sample->truncated()) {
         current = AppendTruncatedTag(current);
@@ -1199,9 +1269,10 @@
         new ProfileFunctionTrieNode(
             GetProfileFunctionTagIndex(VMTag::kRootTagId));
     // We tick the functions while building the trie, but, we don't want to do
-    // it for both tries, just one.
-    tick_functions_ = IsInclusiveTrie(kind);
-    if (IsInclusiveTrie(kind)) {
+    // it for both tries, just the exclusive trie.
+    inclusive_tree_ = IsInclusiveTrie(kind);
+    tick_functions_ = !inclusive_tree_;
+    if (inclusive_tree_) {
       BuildInclusiveFunctionTrie(root);
     } else {
       BuildExclusiveFunctionTrie(root);
@@ -1213,8 +1284,11 @@
   void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) {
     ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie",
                   FLAG_trace_profiler);
-    for (intptr_t i = 0; i < samples_->length(); i++) {
-      ProcessedSample* sample = samples_->At(i);
+    ASSERT(!tick_functions_);
+    for (intptr_t sample_index = 0;
+         sample_index < samples_->length();
+         sample_index++) {
+      ProcessedSample* sample = samples_->At(sample_index);
 
       // Tick the root.
       ProfileFunctionTrieNode* current = root;
@@ -1226,20 +1300,14 @@
       // Truncated tag.
       if (sample->truncated()) {
         current = AppendTruncatedTag(current);
-        InclusiveTickTruncatedTag();
       }
 
       // Walk the sampled PCs.
-      for (intptr_t j = sample->length() - 1; j >= 0; j--) {
-        ASSERT(sample->At(j) != 0);
-        current = ProcessFunctionPC(
-            sample->At(j),
-            sample->timestamp(),
-            current,
-            i,
-            (j == 0),
-            sample->first_frame_executing() || sample->IsAllocationSample(),
-            true);
+      for (intptr_t frame_index = sample->length() - 1;
+           frame_index >= 0;
+           frame_index--) {
+        ASSERT(sample->At(frame_index) != 0);
+        current = ProcessFrame(current, sample_index, sample, frame_index);
       }
     }
   }
@@ -1247,8 +1315,11 @@
   void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) {
     ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie",
                   FLAG_trace_profiler);
-    for (intptr_t i = 0; i < samples_->length(); i++) {
-      ProcessedSample* sample = samples_->At(i);
+    ASSERT(tick_functions_);
+    for (intptr_t sample_index = 0;
+         sample_index < samples_->length();
+         sample_index++) {
+      ProcessedSample* sample = samples_->At(sample_index);
 
       // Tick the root.
       ProfileFunctionTrieNode* current = root;
@@ -1257,41 +1328,36 @@
       // VM & User tags.
       current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
 
+      ResetKind();
+
       // Walk the sampled PCs.
-      for (intptr_t j = 0; j < sample->length(); j++) {
-        ASSERT(sample->At(j) != 0);
-        current = ProcessFunctionPC(
-            sample->At(j),
-            sample->timestamp(),
-            current,
-            i,
-            (j == 0),
-            sample->first_frame_executing() || sample->IsAllocationSample(),
-            false);
+      for (intptr_t frame_index = 0;
+           frame_index < sample->length();
+           frame_index++) {
+        ASSERT(sample->At(frame_index) != 0);
+        current = ProcessFrame(current, sample_index, sample, frame_index);
       }
 
       // Truncated tag.
       if (sample->truncated()) {
         current = AppendTruncatedTag(current);
+        InclusiveTickTruncatedTag();
       }
     }
   }
 
-  ProfileFunctionTrieNode* ProcessFunctionPC(
-      uword pc,
-      int64_t timestamp,
+  ProfileFunctionTrieNode* ProcessFrame(
       ProfileFunctionTrieNode* current,
-      intptr_t inclusive_serial,
-      bool top_frame,
-      bool top_frame_executing,
-      bool inclusive_tree) {
-    ProfileCode* profile_code = GetProfileCode(pc, timestamp);
+      intptr_t sample_index,
+      ProcessedSample* sample,
+      intptr_t frame_index) {
+    const uword pc = sample->At(frame_index);
+    ProfileCode* profile_code = GetProfileCode(pc,
+                                               sample->timestamp());
+    ProfileFunction* function = profile_code->function();
+    ASSERT(function != NULL);
+    const intptr_t code_index = profile_code->code_table_index();
     ASSERT(profile_code != NULL);
-    const char* code_name = profile_code->name();
-    if (code_name == NULL) {
-      code_name = "";
-    }
-    intptr_t code_index = profile_code->code_table_index();
     const Code& code = Code::ZoneHandle(profile_code->code());
     GrowableArray<Function*> inlined_functions;
     if (!code.IsNull()) {
@@ -1300,42 +1366,63 @@
     }
     if (code.IsNull() || (inlined_functions.length() == 0)) {
       // No inlined functions.
-      ProfileFunction* function = profile_code->function();
-      ASSERT(function != NULL);
-      current = ProcessFunction(function,
-                                current,
-                                inclusive_serial,
-                                top_frame,
-                                top_frame_executing,
+      if (inclusive_tree_) {
+        current = AppendKind(code, current);
+      }
+      current = ProcessFunction(current,
+                                sample_index,
+                                sample,
+                                frame_index,
+                                function,
                                 code_index);
+      if (!inclusive_tree_) {
+        current = AppendKind(code, current);
+      }
       return current;
     }
 
-    if (inclusive_tree) {
+    ASSERT(code.is_optimized());
+
+    if (inclusive_tree_) {
       for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) {
         Function* inlined_function = inlined_functions[i];
         ASSERT(inlined_function != NULL);
         ASSERT(!inlined_function->IsNull());
-        current = ProcessInlinedFunction(inlined_function,
-                                         current,
-                                         inclusive_serial,
-                                         top_frame,
-                                         top_frame_executing,
+        const bool inliner = i == (inlined_functions.length() - 1);
+        if (inliner) {
+          current = AppendKind(code, current);
+        }
+        current = ProcessInlinedFunction(current,
+                                         sample_index,
+                                         sample,
+                                         frame_index,
+                                         inlined_function,
                                          code_index);
-        top_frame = false;
+        if (inliner) {
+          current = AppendKind(kInlineStart, current);
+        }
       }
+      current = AppendKind(kInlineFinish, current);
     } else {
+      // Append the inlined children.
+      current = AppendKind(kInlineFinish, current);
       for (intptr_t i = 0; i < inlined_functions.length(); i++) {
         Function* inlined_function = inlined_functions[i];
         ASSERT(inlined_function != NULL);
         ASSERT(!inlined_function->IsNull());
-        current = ProcessInlinedFunction(inlined_function,
-                                         current,
-                                         inclusive_serial,
-                                         top_frame,
-                                         top_frame_executing,
+        const bool inliner = i == (inlined_functions.length() - 1);
+        if (inliner) {
+          current = AppendKind(kInlineStart, current);
+        }
+        current = ProcessInlinedFunction(current,
+                                         sample_index,
+                                         sample,
+                                         frame_index + i,
+                                         inlined_function,
                                          code_index);
-        top_frame = false;
+        if (inliner) {
+          current = AppendKind(code, current);
+        }
       }
     }
 
@@ -1343,44 +1430,47 @@
   }
 
   ProfileFunctionTrieNode* ProcessInlinedFunction(
-      Function* inlined_function,
       ProfileFunctionTrieNode* current,
-      intptr_t inclusive_serial,
-      bool top_frame,
-      bool top_frame_executing,
+      intptr_t sample_index,
+      ProcessedSample* sample,
+      intptr_t frame_index,
+      Function* inlined_function,
       intptr_t code_index) {
     ProfileFunctionTable* function_table = profile_->functions_;
     ProfileFunction* function = function_table->LookupOrAdd(*inlined_function);
     ASSERT(function != NULL);
-    return ProcessFunction(function,
-                           current,
-                           inclusive_serial,
-                           top_frame,
-                           top_frame_executing,
+    return ProcessFunction(current,
+                           sample_index,
+                           sample,
+                           frame_index,
+                           function,
                            code_index);
   }
 
-  ProfileFunctionTrieNode* ProcessFunction(ProfileFunction* function,
-                                           ProfileFunctionTrieNode* current,
-                                           intptr_t inclusive_serial,
-                                           bool top_frame,
-                                           bool top_frame_executing,
+  bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) {
+    if (frame_index != 0) {
+      return true;
+    }
+    // Only tick the first frame's node, if we are executing OR
+    // vm tags have been emitted.
+    return IsExecutingFrame(sample, frame_index) || vm_tags_emitted();
+  }
+
+  ProfileFunctionTrieNode* ProcessFunction(ProfileFunctionTrieNode* current,
+                                           intptr_t sample_index,
+                                           ProcessedSample* sample,
+                                           intptr_t frame_index,
+                                           ProfileFunction* function,
                                            intptr_t code_index) {
-    const bool exclusive = top_frame && top_frame_executing;
     if (tick_functions_) {
-      function->Tick(exclusive, exclusive ? -1 : inclusive_serial);
+      function->Tick(IsExecutingFrame(sample, frame_index), sample_index);
     }
     function->AddProfileCode(code_index);
     current = current->GetChild(function->table_index());
-    current->AddCodeObjectIndex(code_index);
-    if (top_frame) {
-      if (top_frame_executing || vm_tags_emitted()) {
-        // Only tick if this function is using CPU time or VM tags are emitted.
-        current->Tick();
-      }
-    } else {
+    if (ShouldTickNode(sample, frame_index)) {
       current->Tick();
     }
+    current->AddCodeObjectIndex(code_index);
     return current;
   }
 
@@ -1457,6 +1547,53 @@
     return current;
   }
 
+  uword ProfileInfoKindToVMTag(ProfileInfoKind kind) {
+    switch (kind) {
+      case kNone:
+        return VMTag::kNoneCodeTagId;
+      case kOptimized:
+        return VMTag::kOptimizedCodeTagId;
+      case kUnoptimized:
+        return VMTag::kUnoptimizedCodeTagId;
+      case kNative:
+        return VMTag::kNativeCodeTagId;
+      case kInlineStart:
+        return VMTag::kInlineStartCodeTagId;
+      case kInlineFinish:
+        return VMTag::kInlineEndCodeTagId;
+      default:
+        UNIMPLEMENTED();
+        return VMTag::kInvalidTagId;
+    }
+  }
+
+  ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind,
+                                  ProfileCodeTrieNode* current) {
+    if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) {
+      // Only emit if debug tags are requested.
+      return current;
+    }
+    if (kind != info_kind_) {
+      info_kind_ = kind;
+      intptr_t tag_index = GetProfileCodeTagIndex(ProfileInfoKindToVMTag(kind));
+      ASSERT(tag_index >= 0);
+      current = current->GetChild(tag_index);
+      current->Tick();
+    }
+    return current;
+  }
+
+  ProfileCodeTrieNode* AppendKind(const Code& code,
+                                  ProfileCodeTrieNode* current) {
+    if (code.IsNull()) {
+      return AppendKind(kNone, current);
+    } else if (code.is_optimized()) {
+      return AppendKind(kOptimized, current);
+    } else {
+      return AppendKind(kUnoptimized, current);
+    }
+  }
+
   ProfileCodeTrieNode* AppendVMTags(uword vm_tag,
                                     ProfileCodeTrieNode* current) {
     current = AppendVMTag(vm_tag, current);
@@ -1493,6 +1630,38 @@
   }
 
   // ProfileFunctionTrieNode
+  void ResetKind() {
+    info_kind_ = kNone;
+  }
+
+  ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind,
+                                      ProfileFunctionTrieNode* current) {
+    if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) {
+      // Only emit if debug tags are requested.
+      return current;
+    }
+    if (kind != info_kind_) {
+      info_kind_ = kind;
+      intptr_t tag_index =
+          GetProfileFunctionTagIndex(ProfileInfoKindToVMTag(kind));
+      ASSERT(tag_index >= 0);
+      current = current->GetChild(tag_index);
+      current->Tick();
+    }
+    return current;
+  }
+
+  ProfileFunctionTrieNode* AppendKind(const Code& code,
+                                      ProfileFunctionTrieNode* current) {
+    if (code.IsNull()) {
+      return AppendKind(kNone, current);
+    } else if (code.is_optimized()) {
+      return AppendKind(kOptimized, current);
+    } else {
+      return AppendKind(kUnoptimized, current);
+    }
+  }
+
   ProfileFunctionTrieNode* AppendUserTag(uword user_tag,
                                          ProfileFunctionTrieNode* current) {
     intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag);
@@ -1514,7 +1683,7 @@
   }
 
   ProfileFunctionTrieNode* AppendVMTag(uword vm_tag,
-                                   ProfileFunctionTrieNode* current) {
+                                       ProfileFunctionTrieNode* current) {
     if (VMTag::IsNativeEntryTag(vm_tag)) {
       // Insert a dummy kNativeTagId node.
       intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kNativeTagId);
@@ -1776,17 +1945,24 @@
            (tag_order_ == Profile::kVM);
   }
 
+  bool TagsEnabled(intptr_t extra_tags_bits) const {
+    return (extra_tags_ & extra_tags_bits) != 0;
+  }
+
   Isolate* isolate_;
   Isolate* vm_isolate_;
   SampleFilter* filter_;
   Profile::TagOrder tag_order_;
+  intptr_t extra_tags_;
   Profile* profile_;
   DeoptimizedCodeSet* deoptimized_code_;
   const Code& null_code_;
   const Function& null_function_;
   bool tick_functions_;
+  bool inclusive_tree_;
 
   ProcessedSampleBuffer* samples_;
+  ProfileInfoKind info_kind_;
 };
 
 
@@ -1807,8 +1983,10 @@
 }
 
 
-void Profile::Build(SampleFilter* filter, TagOrder tag_order) {
-  ProfileBuilder builder(isolate_, filter, tag_order, this);
+void Profile::Build(SampleFilter* filter,
+                    TagOrder tag_order,
+                    intptr_t extra_tags) {
+  ProfileBuilder builder(isolate_, filter, tag_order, extra_tags, this);
   builder.Build();
 }
 
@@ -1937,6 +2115,44 @@
 }
 
 
+intptr_t ProfileTrieWalker::CurrentNodeTickCount() {
+  if (current_ == NULL) {
+    return -1;
+  }
+  return current_->count();
+}
+
+
+intptr_t ProfileTrieWalker::CurrentInclusiveTicks() {
+  if (current_ == NULL) {
+    return -1;
+  }
+  if (code_trie_) {
+    ProfileCode* code = profile_->GetCode(current_->table_index());
+    return code->inclusive_ticks();
+  } else {
+    ProfileFunction* func = profile_->GetFunction(current_->table_index());
+    return func->inclusive_ticks();
+  }
+  UNREACHABLE();
+}
+
+
+intptr_t ProfileTrieWalker::CurrentExclusiveTicks() {
+  if (current_ == NULL) {
+    return -1;
+  }
+  if (code_trie_) {
+    ProfileCode* code = profile_->GetCode(current_->table_index());
+    return code->exclusive_ticks();
+  } else {
+    ProfileFunction* func = profile_->GetFunction(current_->table_index());
+    return func->exclusive_ticks();
+  }
+  UNREACHABLE();
+}
+
+
 bool ProfileTrieWalker::Down() {
   if ((current_ == NULL) || (current_->NumChildren() == 0)) {
     return false;
@@ -1964,9 +2180,16 @@
 }
 
 
+intptr_t ProfileTrieWalker::SiblingCount() {
+  ASSERT(parent_ != NULL);
+  return parent_->NumChildren();
+}
+
+
 void ProfilerService::PrintJSONImpl(Isolate* isolate,
                                     JSONStream* stream,
                                     Profile::TagOrder tag_order,
+                                    intptr_t extra_tags,
                                     SampleFilter* filter) {
   // Disable profile interrupts while processing the buffer.
   Profiler::EndExecution(isolate);
@@ -1984,7 +2207,7 @@
     StackZone zone(isolate);
     HANDLESCOPE(isolate);
     Profile profile(isolate);
-    profile.Build(filter, tag_order);
+    profile.Build(filter, tag_order, extra_tags);
     profile.PrintJSON(stream);
   }
 
@@ -2006,10 +2229,11 @@
 
 
 void ProfilerService::PrintJSON(JSONStream* stream,
-                                Profile::TagOrder tag_order) {
+                                Profile::TagOrder tag_order,
+                                intptr_t extra_tags) {
   Isolate* isolate = Isolate::Current();
   NoAllocationSampleFilter filter(isolate);
-  PrintJSONImpl(isolate, stream, tag_order, &filter);
+  PrintJSONImpl(isolate, stream, tag_order, extra_tags, &filter);
 }
 
 
@@ -2036,7 +2260,7 @@
                                           const Class& cls) {
   Isolate* isolate = Isolate::Current();
   ClassAllocationSampleFilter filter(isolate, cls);
-  PrintJSONImpl(isolate, stream, tag_order, &filter);
+  PrintJSONImpl(isolate, stream, tag_order, kNoExtraTags, &filter);
 }
 
 
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 7990b4d..7f0b9a3 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -300,7 +300,7 @@
   explicit Profile(Isolate* isolate);
 
   // Build a filtered model using |filter| with the specified |tag_order|.
-  void Build(SampleFilter* filter, TagOrder tag_order);
+  void Build(SampleFilter* filter, TagOrder tag_order, intptr_t extra_tags = 0);
 
   // After building:
   int64_t min_time() const { return min_time_; }
@@ -349,6 +349,14 @@
   void Reset(Profile::TrieKind trie_kind);
 
   const char* CurrentName();
+  // Return the current node's peer's inclusive tick count.
+  intptr_t CurrentInclusiveTicks();
+  // Return the current node's peer's exclusive tick count.
+  intptr_t CurrentExclusiveTicks();
+  // Return the current node's tick count.
+  intptr_t CurrentNodeTickCount();
+  // Return the number siblings (including yourself).
+  intptr_t SiblingCount();
 
   bool Down();
   bool NextSibling();
@@ -363,8 +371,14 @@
 
 class ProfilerService : public AllStatic {
  public:
+  enum {
+    kNoExtraTags = 0,
+    kCodeTransitionTagsBit = (1 << 0),
+  };
+
   static void PrintJSON(JSONStream* stream,
-                        Profile::TagOrder tag_order);
+                        Profile::TagOrder tag_order,
+                        intptr_t extra_tags);
 
   static void PrintAllocationJSON(JSONStream* stream,
                                   Profile::TagOrder tag_order,
@@ -376,6 +390,7 @@
   static void PrintJSONImpl(Isolate* isolate,
                             JSONStream* stream,
                             Profile::TagOrder tag_order,
+                            intptr_t extra_tags,
                             SampleFilter* filter);
 };
 
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index b4b9080..965d6b3 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -314,6 +314,190 @@
 }
 
 
+TEST_CASE(Profiler_CodeTicks) {
+  const char* kScript =
+      "class A {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n"
+      "class B {\n"
+      "  static boo() {\n"
+      "    return new A();\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  B.boo();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+
+  const Class& class_a = Class::Handle(GetClass(root_library, "A"));
+  EXPECT(!class_a.IsNull());
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  // Turn on allocation tracing for A.
+  class_a.SetTraceAllocation(true);
+
+  // Allocate three times.
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have three allocation samples.
+    EXPECT_EQ(3, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    // Exclusive code: B.boo -> main.
+    walker.Reset(Profile::kExclusiveCode);
+    // Move down from the root.
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(3, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+
+    // Inclusive code: main -> B.boo.
+    walker.Reset(Profile::kInclusiveCode);
+    // Move down from the root.
+    EXPECT(walker.Down());
+    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(3, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+  }
+}
+
+
+TEST_CASE(Profiler_FunctionTicks) {
+  const char* kScript =
+      "class A {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n"
+      "class B {\n"
+      "  static boo() {\n"
+      "    return new A();\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  B.boo();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+
+  const Class& class_a = Class::Handle(GetClass(root_library, "A"));
+  EXPECT(!class_a.IsNull());
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  // Turn on allocation tracing for A.
+  class_a.SetTraceAllocation(true);
+
+  // Allocate three times.
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have three allocation samples.
+    EXPECT_EQ(3, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    // Exclusive function: B.boo -> main.
+    walker.Reset(Profile::kExclusiveFunction);
+    // Move down from the root.
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(3, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+
+    // Inclusive function: main -> B.boo.
+    walker.Reset(Profile::kInclusiveFunction);
+    // Move down from the root.
+    EXPECT(walker.Down());
+    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(3, walker.CurrentNodeTickCount());
+    EXPECT_EQ(3, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(3, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+  }
+}
+
+
 TEST_CASE(Profiler_IntrinsicAllocation) {
   const char* kScript = "double foo(double a, double b) => a + b;";
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
@@ -731,4 +915,247 @@
   }
 }
 
+
+TEST_CASE(Profiler_FunctionInline) {
+  const char* kScript =
+      "class A {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n"
+      "class B {\n"
+      "  static choo(bool alloc) {\n"
+      "    if (alloc) return new A();\n"
+      "    return alloc && alloc && !alloc;\n"
+      "  }\n"
+      "  static foo(bool alloc) {\n"
+      "    choo(alloc);\n"
+      "  }\n"
+      "  static boo(bool alloc) {\n"
+      "    for (var i = 0; i < 50000; i++) {\n"
+      "      foo(alloc);\n"
+      "    }\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  B.boo(false);\n"
+      "}\n"
+      "mainA() {\n"
+      "  B.boo(true);\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+
+  const Class& class_a = Class::Handle(GetClass(root_library, "A"));
+  EXPECT(!class_a.IsNull());
+
+  // Compile "main".
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  // Compile "mainA".
+  result = Dart_Invoke(lib, NewString("mainA"), 0, NULL);
+  EXPECT_VALID(result);
+  // At this point B.boo should be optimized and inlined B.foo and B.choo.
+
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  // Turn on allocation tracing for A.
+  class_a.SetTraceAllocation(true);
+
+  // Allocate 50,000 instances of A.
+  result = Dart_Invoke(lib, NewString("mainA"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have 50,000 allocation samples.
+    EXPECT_EQ(50000, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+    // We have two code objects: mainA and B.boo.
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+    // We have two code objects: mainA and B.boo.
+    walker.Reset(Profile::kInclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+
+    // Inline expansion should show us the complete call chain:
+    // mainA -> B.boo -> B.foo -> B.choo.
+    walker.Reset(Profile::kExclusiveFunction);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.choo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.foo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+
+    // Inline expansion should show us the complete call chain:
+    // mainA -> B.boo -> B.foo -> B.choo.
+    walker.Reset(Profile::kInclusiveFunction);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.foo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(0, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.choo", walker.CurrentName());
+    EXPECT_EQ(1, walker.SiblingCount());
+    EXPECT_EQ(50000, walker.CurrentNodeTickCount());
+    EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
+    EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
+    EXPECT(!walker.Down());
+  }
+
+  // Test code transition tags.
+  {
+    Isolate* isolate = Isolate::Current();
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, class_a.id());
+    profile.Build(&filter,
+                  Profile::kNoTags,
+                  ProfilerService::kCodeTransitionTagsBit);
+    // We should have 50,000 allocation samples.
+    EXPECT_EQ(50000, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+    // We have two code objects: mainA and B.boo.
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
+    EXPECT(!walker.Down());
+    // We have two code objects: mainA and B.boo.
+    walker.Reset(Profile::kInclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT(!walker.Down());
+
+    // Inline expansion should show us the complete call chain:
+    // mainA -> B.boo -> B.foo -> B.choo.
+    walker.Reset(Profile::kExclusiveFunction);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Inline End]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.choo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.foo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Inline Start]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
+    EXPECT(!walker.Down());
+
+    // Inline expansion should show us the complete call chain:
+    // mainA -> B.boo -> B.foo -> B.choo.
+    walker.Reset(Profile::kInclusiveFunction);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Inline Start]", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.foo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("B.choo", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("[Inline End]", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+}
+
 }  // namespace dart
+
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 3313d17..fa91a14 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -369,6 +369,9 @@
   void SetCanonical() {
     UpdateTagBit<CanonicalObjectTag>(true);
   }
+  void ClearCanonical() {
+    UpdateTagBit<CanonicalObjectTag>(false);
+  }
   bool IsCreatedFromSnapshot() const {
     return CreatedFromSnapshotTag::decode(ptr()->tags_);
   }
@@ -581,6 +584,7 @@
   friend class Scavenger;
   friend class ScavengerVisitor;
   friend class SizeExcludingClassVisitor;  // GetClassId
+  friend class RetainingPathVisitor;  // GetClassId
   friend class SnapshotReader;
   friend class SnapshotWriter;
   friend class String;
@@ -828,6 +832,7 @@
   RawAbstractType* type_;
   RawInstance* value_;  // Offset in words for instance and value for static.
   RawArray* dependent_code_;
+  RawFunction* initializer_;
   RawSmi* guarded_list_length_;
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->guarded_list_length_);
@@ -971,7 +976,8 @@
   enum InlinedMetadataIndex {
     kInlinedIntervalsIndex = 0,
     kInlinedIdToFunctionIndex = 1,
-    kInlinedMetadataSize = 2,
+    kInlinedCallerIdMapIndex = 2,
+    kInlinedMetadataSize = 3,
   };
 
   RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 057f8e9..cc193fa 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -21,6 +21,8 @@
   ((kind == Snapshot::kFull) ?                                                 \
   reader->New##type(len) : type::New(len, HEAP_SPACE(kind)))
 
+#define OFFSET_OF_FROM(obj)                                                    \
+  obj.raw()->from() - reinterpret_cast<RawObject**>(obj.raw()->ptr())
 
 RawClass* Class::ReadFrom(SnapshotReader* reader,
                           intptr_t object_id,
@@ -67,9 +69,11 @@
     // TODO(5411462): Need to assert No GC can happen here, even though
     // allocations may happen.
     intptr_t num_flds = (cls.raw()->to() - cls.raw()->from());
+    intptr_t from_offset = OFFSET_OF_FROM(cls);
     for (intptr_t i = 0; i <= num_flds; i++) {
-      (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
-       cls.StorePointer((cls.raw()->from() + i),
+      (*reader->PassiveObjectHandle()) =
+          reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
+      cls.StorePointer((cls.raw()->from() + i),
                        reader->PassiveObjectHandle()->raw());
     }
   } else {
@@ -152,7 +156,7 @@
   intptr_t num_flds = (unresolved_class.raw()->to() -
                        unresolved_class.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     unresolved_class.StorePointer((unresolved_class.raw()->from() + i),
                                   reader->PassiveObjectHandle()->raw());
   }
@@ -205,7 +209,11 @@
 
   // Allocate type object.
   Type& type = Type::ZoneHandle(reader->zone(), NEW_OBJECT(Type));
-  reader->AddBackRef(object_id, &type, kIsDeserialized);
+  bool is_canonical = RawObject::IsCanonical(tags);
+  bool defer_canonicalization = is_canonical &&
+      ((kind == Snapshot::kScript && RawObject::IsCreatedFromSnapshot(tags)) ||
+       kind == Snapshot::kMessage);
+  reader->AddBackRef(object_id, &type, kIsDeserialized, defer_canonicalization);
 
   // Set all non object fields.
   type.set_token_pos(reader->Read<int32_t>());
@@ -215,28 +223,15 @@
   // TODO(5411462): Need to assert No GC can happen here, even though
   // allocations may happen.
   intptr_t num_flds = (type.raw()->to() - type.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(type);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsInlinedObject, object_id, (i + from_offset));
     type.StorePointer((type.raw()->from() + i),
                       reader->PassiveObjectHandle()->raw());
   }
 
-  // If object needs to be a canonical object, Canonicalize it.
-  // When reading a full snapshot we don't need to canonicalize the object
-  // as it would already be a canonical object.
-  // When reading a script snapshot we need to canonicalize only those object
-  // references that are objects from the core library (loaded from a
-  // full snapshot). Objects that are only in the script need not be
-  // canonicalized as they are already canonical.
-  // When reading a message snapshot we always have to canonicalize the object.
-  if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
-      (RawObject::IsCreatedFromSnapshot(tags) ||
-       (kind == Snapshot::kMessage))) {
-    type ^= type.Canonicalize();
-  }
-
-  // Set the object tags (This is done after 'Canonicalize', which
-  // does not canonicalize a type already marked as canonical).
+  // Set the object tags.
   type.set_tags(tags);
 
   return type.raw();
@@ -289,8 +284,10 @@
   // TODO(5411462): Need to assert No GC can happen here, even though
   // allocations may happen.
   intptr_t num_flds = (type_ref.raw()->to() - type_ref.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(type_ref);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
     type_ref.StorePointer((type_ref.raw()->from() + i),
                           reader->PassiveObjectHandle()->raw());
   }
@@ -341,8 +338,10 @@
   // allocations may happen.
   intptr_t num_flds = (type_parameter.raw()->to() -
                        type_parameter.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(type_parameter);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
     type_parameter.StorePointer((type_parameter.raw()->from() + i),
                                 reader->PassiveObjectHandle()->raw());
   }
@@ -396,8 +395,10 @@
   // allocations may happen.
   intptr_t num_flds = (bounded_type.raw()->to() -
                        bounded_type.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(bounded_type);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
     bounded_type.StorePointer((bounded_type.raw()->from() + i),
                               reader->PassiveObjectHandle()->raw());
   }
@@ -451,40 +452,33 @@
 
   TypeArguments& type_arguments = TypeArguments::ZoneHandle(
       reader->zone(), NEW_OBJECT_WITH_LEN_SPACE(TypeArguments, len, kind));
-  reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
+  bool is_canonical = RawObject::IsCanonical(tags);
+  bool defer_canonicalization = is_canonical &&
+      ((kind == Snapshot::kScript && RawObject::IsCreatedFromSnapshot(tags)) ||
+       kind == Snapshot::kMessage);
+  reader->AddBackRef(object_id,
+                     &type_arguments,
+                     kIsDeserialized,
+                     defer_canonicalization);
 
   // Set the instantiations field, which is only read from a full snapshot.
   if (kind == Snapshot::kFull) {
-    *(reader->ArrayHandle()) ^= reader->ReadObjectImpl();
+    *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
     type_arguments.set_instantiations(*(reader->ArrayHandle()));
   } else {
     type_arguments.set_instantiations(Object::zero_array());
   }
 
   // Now set all the type fields.
+  intptr_t offset = type_arguments.TypeAddr(0) -
+      reinterpret_cast<RawAbstractType**>(type_arguments.raw()->ptr());
   for (intptr_t i = 0; i < len; i++) {
-    *reader->TypeHandle() ^= reader->ReadObjectImpl();
+    *reader->TypeHandle() ^=
+        reader->ReadObjectImpl(kAsInlinedObject, object_id, (i + offset));
     type_arguments.SetTypeAt(i, *reader->TypeHandle());
   }
 
-  // If object needs to be a canonical object, Canonicalize it.
-  // When reading a full snapshot we don't need to canonicalize the object
-  // as it would already be a canonical object.
-  // When reading a script snapshot we need to canonicalize only those object
-  // references that are objects from the core library (loaded from a
-  // full snapshot). Objects that are only in the script need not be
-  // canonicalized as they are already canonical.
-  // When reading a message snapshot we always have to canonicalize the object.
-  if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
-      (RawObject::IsCreatedFromSnapshot(tags) ||
-       (kind == Snapshot::kMessage))) {
-    type_arguments ^= type_arguments.Canonicalize();
-  }
-
-  // Set the object tags (This is done after setting the object fields
-  // because 'SetTypeAt' has an assertion to check if the object is not
-  // already canonical. Also, this is done after 'Canonicalize', which
-  // does not canonicalize a type already marked as canonical).
+  // Set the object tags .
   type_arguments.set_tags(tags);
 
   return type_arguments.raw();
@@ -508,13 +502,13 @@
 
   // Write out the instantiations field, but only in a full snapshot.
   if (kind == Snapshot::kFull) {
-    writer->WriteObjectImpl(ptr()->instantiations_);
+    writer->WriteObjectImpl(ptr()->instantiations_, kAsInlinedObject);
   }
 
   // Write out the individual types.
   intptr_t len = Smi::Value(ptr()->length_);
   for (intptr_t i = 0; i < len; i++) {
-    writer->WriteObjectImpl(ptr()->types()[i]);
+    writer->WriteObjectImpl(ptr()->types()[i], kAsInlinedObject);
   }
 }
 
@@ -541,7 +535,7 @@
   // allocations may happen.
   intptr_t num_flds = (cls.raw()->to() - cls.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     cls.StorePointer((cls.raw()->from() + i),
                      reader->PassiveObjectHandle()->raw());
   }
@@ -592,7 +586,7 @@
   // allocations may happen.
   intptr_t num_flds = (data.raw()->to() - data.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    *(data.raw()->from() + i) = reader->ReadObjectRef();
+    *(data.raw()->from() + i) = reader->ReadObjectImpl(kAsReference);
   }
 
   return data.raw();
@@ -616,17 +610,17 @@
 
   // Context scope.
   // We don't write the context scope in the snapshot.
-  writer->WriteObjectImpl(Object::null());
+  writer->WriteObjectImpl(Object::null(), kAsInlinedObject);
 
   // Parent function.
-  writer->WriteObjectImpl(ptr()->parent_function_);
+  writer->WriteObjectImpl(ptr()->parent_function_, kAsInlinedObject);
 
   // Signature class.
-  writer->WriteObjectImpl(ptr()->signature_class_);
+  writer->WriteObjectImpl(ptr()->signature_class_, kAsInlinedObject);
 
   // Static closure/Closure allocation stub.
   // We don't write the closure or allocation stub in the snapshot.
-  writer->WriteObjectImpl(Object::null());
+  writer->WriteObjectImpl(Object::null(), kAsInlinedObject);
 }
 
 
@@ -651,8 +645,10 @@
   // TODO(5411462): Need to assert No GC can happen here, even though
   // allocations may happen.
   intptr_t num_flds = (data.raw()->to() - data.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(data);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
     data.StorePointer((data.raw()->from() + i),
                       reader->PassiveObjectHandle()->raw());
   }
@@ -715,8 +711,10 @@
   // TODO(5411462): Need to assert No GC can happen here, even though
   // allocations may happen.
   intptr_t num_flds = (func.raw()->to_snapshot() - func.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(func);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
     func.StorePointer((func.raw()->from() + i),
                       reader->PassiveObjectHandle()->raw());
   }
@@ -787,8 +785,10 @@
   // TODO(5411462): Need to assert No GC can happen here, even though
   // allocations may happen.
   intptr_t num_flds = (field.raw()->to() - field.raw()->from());
+  intptr_t from_offset = OFFSET_OF_FROM(field);
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) =
+        reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
     field.StorePointer((field.raw()->from() + i),
                        reader->PassiveObjectHandle()->raw());
   }
@@ -850,7 +850,7 @@
   // allocations may happen.
   intptr_t num_flds = (literal_token.raw()->to() - literal_token.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     literal_token.StorePointer((literal_token.raw()->from() + i),
                                reader->PassiveObjectHandle()->raw());
   }
@@ -910,10 +910,10 @@
   }
 
   // Read in the literal/identifier token array.
-  *(reader->TokensHandle()) ^= reader->ReadObjectImpl();
+  *(reader->TokensHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
   token_stream.SetTokenObjects(*(reader->TokensHandle()));
   // Read in the private key in use by the token stream.
-  *(reader->StringHandle()) ^= reader->ReadObjectImpl();
+  *(reader->StringHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
   token_stream.SetPrivateKey(*(reader->StringHandle()));
 
   return token_stream.raw();
@@ -942,9 +942,9 @@
   writer->WriteBytes(stream->ptr()->data_, len);
 
   // Write out the literal/identifier token array.
-  writer->WriteObjectImpl(ptr()->token_objects_);
+  writer->WriteObjectImpl(ptr()->token_objects_, kAsInlinedObject);
   // Write out the private key in use by the token stream.
-  writer->WriteObjectImpl(ptr()->private_key_);
+  writer->WriteObjectImpl(ptr()->private_key_, kAsInlinedObject);
 }
 
 
@@ -976,7 +976,7 @@
   // allocations may happen.
   intptr_t num_flds = (script.raw()->to_snapshot() - script.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     script.StorePointer((script.raw()->from() + i),
                         reader->PassiveObjectHandle()->raw());
   }
@@ -1028,7 +1028,7 @@
   if ((kind == Snapshot::kScript) && RawObject::IsCreatedFromSnapshot(tags)) {
     ASSERT(kind != Snapshot::kFull);
     // Lookup the object as it should already exist in the heap.
-    *reader->StringHandle() ^= reader->ReadObjectImpl();
+    *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
     library = Library::LookupLibrary(*reader->StringHandle());
   } else {
     // Allocate library object.
@@ -1063,7 +1063,7 @@
     // allocations may happen.
     intptr_t num_flds = (library.raw()->to() - library.raw()->from());
     for (intptr_t i = 0; i <= num_flds; i++) {
-      (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
       library.StorePointer((library.raw()->from() + i),
                            reader->PassiveObjectHandle()->raw());
     }
@@ -1092,7 +1092,7 @@
       RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) {
     ASSERT(kind != Snapshot::kFull);
     // Write out library URL so that it can be looked up when reading.
-    writer->WriteObjectImpl(ptr()->url_);
+    writer->WriteObjectImpl(ptr()->url_, kAsInlinedObject);
   } else {
     // Write out all non object fields.
     writer->WriteClassIDValue(ptr()->index_);
@@ -1144,7 +1144,7 @@
   // allocations may happen.
   intptr_t num_flds = (prefix.raw()->to() - prefix.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     prefix.StorePointer((prefix.raw()->from() + i),
                          reader->PassiveObjectHandle()->raw());
   }
@@ -1201,7 +1201,7 @@
   // allocations may happen.
   intptr_t num_flds = (ns.raw()->to() - ns.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     ns.StorePointer((ns.raw()->from() + i),
                     reader->PassiveObjectHandle()->raw());
   }
@@ -1390,7 +1390,7 @@
   result.set_tags(tags);
 
   for (intptr_t i = 0; i < num_entries; i++) {
-    (*reader->StringHandle()) ^= reader->ReadObjectRef();
+    (*reader->StringHandle()) ^= reader->ReadObjectImpl(kAsReference);
     result.StorePointer(result.raw()->nameAddrAt(i),
                         reader->StringHandle()->raw());
   }
@@ -1418,7 +1418,7 @@
   writer->WriteTags(writer->GetObjectTags(this));
   writer->Write<int32_t>(ptr()->num_entries_);
   for (intptr_t i = 0; i < ptr()->num_entries_; i++) {
-    writer->WriteObjectImpl(ptr()->names()[i]);
+    writer->WriteObjectImpl(ptr()->names()[i], kAsInlinedObject);
   }
   if (ptr()->num_entries_ > 0) {
     intptr_t len = ptr()->num_entries_ * sizeof(VarInfo);
@@ -1434,7 +1434,8 @@
                                                   Snapshot::Kind kind) {
   ASSERT(reader->allow_code());
 
-  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl();  // handled_types_data_
+  // handled_types_data.
+  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
 
   ExceptionHandlers& result =
       ExceptionHandlers::ZoneHandle(reader->zone(),
@@ -1466,7 +1467,7 @@
   writer->WriteInlinedObjectHeader(object_id);
   writer->WriteIndexedObject(kExceptionHandlersCid);
   writer->WriteTags(writer->GetObjectTags(this));
-  writer->WriteObjectImpl(ptr()->handled_types_data_);
+  writer->WriteObjectImpl(ptr()->handled_types_data_, kAsInlinedObject);
 
   if (ptr()->num_entries_ > 0) {
     intptr_t len = ptr()->num_entries_ * sizeof(HandlerInfo);
@@ -1499,7 +1500,7 @@
     // allocations may happen.
     intptr_t num_flds = (context.raw()->to(num_vars) - context.raw()->from());
     for (intptr_t i = 0; i <= num_flds; i++) {
-      (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
       context.StorePointer((context.raw()->from() + i),
                            reader->PassiveObjectHandle()->raw());
     }
@@ -1630,7 +1631,7 @@
   // allocations may happen.
   intptr_t num_flds = (api_error.raw()->to() - api_error.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     api_error.StorePointer((api_error.raw()->from() + i),
                            reader->PassiveObjectHandle()->raw());
   }
@@ -1681,7 +1682,7 @@
   intptr_t num_flds =
       (language_error.raw()->to() - language_error.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     language_error.StorePointer((language_error.raw()->from() + i),
                                 reader->PassiveObjectHandle()->raw());
   }
@@ -1728,7 +1729,7 @@
   // allocations may happen.
   intptr_t num_flds = (result.raw()->to() - result.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     result.StorePointer((result.raw()->from() + i),
                          reader->PassiveObjectHandle()->raw());
   }
@@ -1829,7 +1830,10 @@
   // Check if the value could potentially fit in a Smi in our current
   // architecture, if so return the object as a Smi.
   if (Smi::IsValid(value)) {
-    return Smi::New(static_cast<intptr_t>(value));
+    Smi& smi = Smi::ZoneHandle(reader->zone(),
+                               Smi::New(static_cast<intptr_t>(value)));
+    reader->AddBackRef(object_id, &smi, kIsDeserialized);
+    return smi.raw();
   }
 
   // Create a Mint object or get canonical one if it is a canonical constant.
@@ -1894,7 +1898,7 @@
   // allocations may happen.
   intptr_t num_flds = (obj.raw()->to() - obj.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsInlinedObject);
     obj.StorePointer(obj.raw()->from() + i,
                      reader->PassiveObjectHandle()->raw());
   }
@@ -2059,7 +2063,9 @@
   String& str_obj = String::Handle(reader->zone(), String::null());
 
   if (kind == Snapshot::kFull) {
-    ASSERT(reader->isolate()->no_safepoint_scope_depth() != 0);
+    // We currently only expect the Dart mutator to read snapshots.
+    reader->isolate()->AssertCurrentThreadIsMutator();
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
     RawOneByteString* obj = reader->NewOneByteString(len);
     str_obj = obj;
     str_obj.set_tags(tags);
@@ -2258,7 +2264,7 @@
     reader->AddBackRef(object_id, array, kIsDeserialized);
   }
   ASSERT(!RawObject::IsCanonical(tags));
-  reader->ArrayReadFrom(*array, len, tags);
+  reader->ArrayReadFrom(object_id, *array, len, tags);
   return array->raw();
 }
 
@@ -2278,7 +2284,7 @@
         NEW_OBJECT_WITH_LEN_SPACE(ImmutableArray, len, kind)));
     reader->AddBackRef(object_id, array, kIsDeserialized);
   }
-  reader->ArrayReadFrom(*array, len, tags);
+  reader->ArrayReadFrom(object_id, *array, len, tags);
   if (RawObject::IsCanonical(tags)) {
     *array ^= array->CheckAndCanonicalize(NULL);
   }
@@ -2328,7 +2334,7 @@
   reader->AddBackRef(object_id, &array, kIsDeserialized);
   intptr_t length = reader->ReadSmiValue();
   array.SetLength(length);
-  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl();
+  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
   array.SetData(*(reader->ArrayHandle()));
   *(reader->TypeArgumentsHandle()) = reader->ArrayHandle()->GetTypeArguments();
   array.SetTypeArguments(*(reader->TypeArgumentsHandle()));
@@ -2352,7 +2358,7 @@
   writer->Write<RawObject*>(ptr()->length_);
 
   // Write out the Array object.
-  writer->WriteObjectImpl(ptr()->data_);
+  writer->WriteObjectImpl(ptr()->data_, kAsInlinedObject);
 }
 
 
@@ -2377,7 +2383,11 @@
   map.set_tags(tags);
 
   // Read the type arguments.
-  *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl();
+  intptr_t typeargs_offset =
+      reinterpret_cast<RawObject**>(&map.raw()->ptr()->type_arguments_) -
+      reinterpret_cast<RawObject**>(map.raw()->ptr());
+  *reader->TypeArgumentsHandle() ^=
+      reader->ReadObjectImpl(kAsInlinedObject, object_id, typeargs_offset);
   map.SetTypeArguments(*reader->TypeArgumentsHandle());
 
   // Read the number of key/value pairs.
@@ -2402,10 +2412,9 @@
   map.SetHashMask(0);  // Prefer sentinel 0 over null for better type feedback.
 
   // Read the keys and values.
-  bool is_canonical = RawObject::IsCanonical(tags);
+  bool as_reference = RawObject::IsCanonical(tags) ? false : true;
   for (intptr_t i = 0; i < used_data; i++) {
-    *reader->PassiveObjectHandle() =
-        is_canonical ? reader->ReadObjectImpl() : reader->ReadObjectRef();
+    *reader->PassiveObjectHandle() = reader->ReadObjectImpl(as_reference);
     data.SetAt(i, *reader->PassiveObjectHandle());
   }
   return map.raw();
@@ -2431,7 +2440,7 @@
   writer->WriteTags(tags);
 
   // Write out the type arguments.
-  writer->WriteObjectImpl(ptr()->type_arguments_);
+  writer->WriteObjectImpl(ptr()->type_arguments_, kAsInlinedObject);
 
   const intptr_t used_data = Smi::Value(ptr()->used_data_);
   ASSERT((used_data & 1) == 0);  // Keys + values, so must be even.
@@ -2441,7 +2450,7 @@
   writer->Write<RawObject*>(Smi::New((used_data >> 1) - deleted_keys));
 
   // Write out the keys and values.
-  const bool is_canonical = RawObject::IsCanonical(tags);
+  const bool as_reference = RawObject::IsCanonical(tags) ? false : true;
   RawArray* data_array = ptr()->data_;
   RawObject** data_elements = data_array->ptr()->data();
   ASSERT(used_data <= Smi::Value(data_array->ptr()->length_));
@@ -2457,13 +2466,8 @@
       continue;
     }
     RawObject* value = data_elements[i + 1];
-    if (is_canonical) {
-      writer->WriteObjectImpl(key);
-      writer->WriteObjectImpl(value);
-    } else {
-      writer->WriteObjectRef(key);
-      writer->WriteObjectRef(value);
-    }
+    writer->WriteObjectImpl(key, as_reference);
+    writer->WriteObjectImpl(value, as_reference);
   }
   DEBUG_ASSERT(deleted_keys_found == deleted_keys);
 }
@@ -2677,8 +2681,9 @@
   intptr_t cid = RawObject::ClassIdTag::decode(tags);
   intptr_t length = reader->ReadSmiValue();
   uint8_t* data = reinterpret_cast<uint8_t*>(reader->ReadRawPointerValue());
-  const ExternalTypedData& obj = ExternalTypedData::Handle(
+  ExternalTypedData& obj = ExternalTypedData::Handle(
       ExternalTypedData::New(cid, data, length));
+  reader->AddBackRef(object_id, &obj, kIsDeserialized);
   void* peer = reinterpret_cast<void*>(reader->ReadRawPointerValue());
   Dart_WeakPersistentHandleFinalizer callback =
       reinterpret_cast<Dart_WeakPersistentHandleFinalizer>(
@@ -2916,7 +2921,7 @@
     // allocations may happen.
     intptr_t num_flds = (result.raw()->to() - result.raw()->from());
     for (intptr_t i = 0; i <= num_flds; i++) {
-      (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
       result.StorePointer((result.raw()->from() + i),
                           reader->PassiveObjectHandle()->raw());
     }
@@ -2978,7 +2983,7 @@
   // Read and Set all the other fields.
   regex.StoreSmi(&regex.raw_ptr()->num_bracket_expressions_,
                  reader->ReadAsSmi());
-  *reader->StringHandle() ^= reader->ReadObjectImpl();
+  *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
   regex.set_pattern(*reader->StringHandle());
   regex.StoreNonPointer(&regex.raw_ptr()->num_registers_,
                         reader->Read<int32_t>());
@@ -3005,7 +3010,7 @@
 
   // Write out all the other fields.
   writer->Write<RawObject*>(ptr()->num_bracket_expressions_);
-  writer->WriteObjectImpl(ptr()->pattern_);
+  writer->WriteObjectImpl(ptr()->pattern_, kAsInlinedObject);
   writer->Write<int32_t>(ptr()->num_registers_);
   writer->Write<int8_t>(ptr()->type_flags_);
 }
@@ -3031,7 +3036,7 @@
   intptr_t num_flds = (weak_property.raw()->to() -
                        weak_property.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectRef();
+    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
     weak_property.StorePointer((weak_property.raw()->from() + i),
                                reader->PassiveObjectHandle()->raw());
   }
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 03abf5a..716afa4 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -217,6 +217,8 @@
 
 
 bool RegExpParser::ParseFunction(ParsedFunction *parsed_function) {
+  VMTagScope tagScope(Thread::Current()->isolate(),
+                      VMTag::kCompileParseRegExpTagId);
   Zone* zone = parsed_function->zone();
   JSRegExp& regexp = JSRegExp::Handle(parsed_function->function().regexp());
 
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 954f340..d9fe847 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -114,6 +114,47 @@
   String& field_name = String::Handle();
   if (is_getter) {
     field_name ^= Field::NameFromGetter(function_name);
+
+    if (field_name.CharAt(0) == '#') {
+      if (!FLAG_lazy_dispatchers) {
+        return Function::null();
+      }
+
+      // Resolving a getter "get:#..." is a request to closurize an instance
+      // property of the receiver object. It can be of the form:
+      //  - get:#id, which closurizes a method or getter id
+      //  - get:#set:id, which closurizes a setter id
+      //  - get:#operator, eg. get:#<<, which closurizes an operator method.
+      // If the property can be resolved, a method extractor function
+      // "get:#..." is created and injected into the receiver's class.
+      String& property_name = String::Handle(String::SubString(field_name, 1));
+      ASSERT(!Field::IsGetterName(property_name));
+
+      String& property_getter_name = String::Handle();
+      if (!Field::IsSetterName(property_name)) {
+        // If this is not a setter, we need to look for both the regular
+        // name and the getter name. (In the case of an operator, this
+        // code will also try to resolve for example get:<< and will fail,
+        // but that's harmless.)
+        property_getter_name = Field::GetterName(property_name);
+      }
+
+      Function& function = Function::Handle();
+      while (!cls.IsNull()) {
+        function = cls.LookupDynamicFunction(property_name);
+        if (!function.IsNull()) {
+          return CreateMethodExtractor(function_name, function);
+        }
+        if (!property_getter_name.IsNull()) {
+          function = cls.LookupDynamicFunction(property_getter_name);
+          if (!function.IsNull()) {
+            return CreateMethodExtractor(function_name, function);
+          }
+        }
+        cls = cls.SuperClass();
+      }
+      return Function::null();
+    }
   }
 
   // Now look for an instance function whose name matches function_name
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index e3aceb0..d355254 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -49,8 +49,7 @@
     // informative error message.
     __ LoadExternalLabel(R5, &label, kNotPatchable);
     __ LoadImmediate(R4, argument_count);
-    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel(),
-                  kNotPatchable);
+    __ BranchLink(*StubCode::CallToRuntime_entry(), kNotPatchable);
   }
 }
 
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index a2edb95..38dbe43 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -49,15 +49,15 @@
     __ mov(R26, SP);
     __ ReserveAlignedFrameSpace(0);
     __ mov(CSP, SP);
-    __ BranchLink(&label, kNoPP);
+    __ BranchLink(&label);
     __ mov(SP, R26);
     __ mov(CSP, R25);
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ LoadExternalLabel(R5, &label, kNotPatchable, PP);
-    __ LoadImmediate(R4, argument_count, kNoPP);
-    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel(), PP);
+    __ LoadExternalLabel(R5, &label);
+    __ LoadImmediate(R4, argument_count);
+    __ BranchLink(*StubCode::CallToRuntime_entry());
   }
 }
 
diff --git a/runtime/vm/runtime_entry_ia32.cc b/runtime/vm/runtime_entry_ia32.cc
index 612b72b..33b0e5a 100644
--- a/runtime/vm/runtime_entry_ia32.cc
+++ b/runtime/vm/runtime_entry_ia32.cc
@@ -33,7 +33,7 @@
     // informative error message.
     __ movl(ECX, Immediate(GetEntryPoint()));
     __ movl(EDX, Immediate(argument_count));
-    __ call(&Isolate::Current()->stub_code()->CallToRuntimeLabel());
+    __ Call(*StubCode::CallToRuntime_entry());
   }
 }
 
diff --git a/runtime/vm/runtime_entry_mips.cc b/runtime/vm/runtime_entry_mips.cc
index 872a37c..03cfa1f 100644
--- a/runtime/vm/runtime_entry_mips.cc
+++ b/runtime/vm/runtime_entry_mips.cc
@@ -49,8 +49,7 @@
     // informative error message.
     __ LoadExternalLabel(S5, &label, kNotPatchable);
     __ LoadImmediate(S4, argument_count);
-    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel(),
-                  kNotPatchable);
+    __ BranchLink(*StubCode::CallToRuntime_entry(), kNotPatchable);
   }
 }
 
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index 705eacd..df24e70 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -29,9 +29,9 @@
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
     ExternalLabel label(GetEntryPoint());
-    __ LoadExternalLabel(RBX, &label, kNotPatchable, PP);
+    __ LoadExternalLabel(RBX, &label, kNotPatchable);
     __ movq(R10, Immediate(argument_count));
-    __ Call(&Isolate::Current()->stub_code()->CallToRuntimeLabel(), PP);
+    __ Call(*StubCode::CallToRuntime_entry());
   }
 }
 
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index e68727a..6f4fd03 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -87,7 +87,7 @@
 StreamInfo Service::gc_stream("GC");
 StreamInfo Service::echo_stream("_Echo");
 StreamInfo Service::graph_stream("_Graph");
-
+StreamInfo Service::logging_stream("_Logging");
 
 static StreamInfo* streams_[] = {
   &Service::isolate_stream,
@@ -95,6 +95,7 @@
   &Service::gc_stream,
   &Service::echo_stream,
   &Service::graph_stream,
+  &Service::logging_stream,
 };
 
 
@@ -508,7 +509,7 @@
     HANDLESCOPE(isolate);
 
     Instance& reply_port = Instance::Handle(isolate);
-    String& seq = String::Handle(isolate);
+    Instance& seq = String::Handle(isolate);
     String& method_name = String::Handle(isolate);
     Array& param_keys = Array::Handle(isolate);
     Array& param_values = Array::Handle(isolate);
@@ -519,7 +520,7 @@
     param_values ^= msg.At(5);
 
     ASSERT(!method_name.IsNull());
-    ASSERT(!seq.IsNull());
+    ASSERT(seq.IsNull() || seq.IsString() || seq.IsNumber());
     ASSERT(!param_keys.IsNull());
     ASSERT(!param_values.IsNull());
     ASSERT(param_keys.Length() == param_values.Length());
@@ -680,9 +681,22 @@
   ASSERT(stream_id != NULL);
   {
     JSONObject jsobj(&js);
-    jsobj.AddProperty("event", event);
-    jsobj.AddProperty("streamId", stream_id);
+    jsobj.AddProperty("jsonrpc", "2.0");
+    jsobj.AddProperty("method", "streamNotify");
+    JSONObject params(&jsobj, "params");
+    params.AddProperty("streamId", stream_id);
+    params.AddProperty("event", event);
   }
+  PostEvent(stream_id, event->KindAsCString(), &js);
+}
+
+
+void Service::PostEvent(const char* stream_id,
+                        const char* kind,
+                        JSONStream* event) {
+  ASSERT(stream_id != NULL);
+  ASSERT(kind != NULL);
+  ASSERT(event != NULL);
 
   // Message is of the format [<stream id>, <json string>].
   //
@@ -702,13 +716,12 @@
 
   Dart_CObject json_cobj;
   json_cobj.type = Dart_CObject_kString;
-  json_cobj.value.as_string = const_cast<char*>(js.ToCString());
+  json_cobj.value.as_string = const_cast<char*>(event->ToCString());
   list_values[1] = &json_cobj;
 
   if (FLAG_trace_service) {
     OS::Print(
-        "vm-service: Pushing event of type %s to stream %s\n",
-        event->KindAsCString(), stream_id);
+        "vm-service: Pushing event of type %s to stream %s\n", kind, stream_id);
   }
 
   Dart_PostCObject(ServiceIsolate::Port(), &list_cobj);
@@ -917,16 +930,21 @@
   JSONStream js;
   {
     JSONObject jsobj(&js);
+    jsobj.AddProperty("jsonrpc", "2.0");
+    jsobj.AddProperty("method", "streamNotify");
     {
-      JSONObject event(&jsobj, "event");
-      event.AddProperty("type", "Event");
-      event.AddProperty("kind", "_Echo");
-      event.AddProperty("isolate", isolate);
-      if (text != NULL) {
-        event.AddProperty("text", text);
+      JSONObject params(&jsobj, "params");
+      params.AddProperty("streamId", echo_stream.id());
+      {
+        JSONObject event(&params, "event");
+        event.AddProperty("type", "Event");
+        event.AddProperty("kind", "_Echo");
+        event.AddProperty("isolate", isolate);
+        if (text != NULL) {
+          event.AddProperty("text", text);
+        }
       }
     }
-    jsobj.AddProperty("streamId", echo_stream.id());
   }
   const String& message = String::Handle(String::New(js.ToCString()));
   uint8_t data[] = {0, 128, 255};
@@ -1505,10 +1523,9 @@
   jsobj.AddProperty("length", length);
   JSONArray elements(&jsobj, "elements");
   Object& element = Object::Handle();
-  Object& parent = Object::Handle();
-  Smi& offset_from_parent = Smi::Handle();
-  Class& parent_class = Class::Handle();
-  Array& parent_field_map = Array::Handle();
+  Smi& slot_offset = Smi::Handle();
+  Class& element_class = Class::Handle();
+  Array& element_field_map = Array::Handle();
   Field& field = Field::Handle();
   limit = Utils::Minimum(limit, length);
   for (intptr_t i = 0; i < limit; ++i) {
@@ -1518,22 +1535,23 @@
     jselement.AddProperty("value", element);
     // Interpret the word offset from parent as list index or instance field.
     // TODO(koda): User-friendly interpretation for map entries.
-    offset_from_parent ^= path.At((i * 2) + 1);
-    int parent_i = i + 1;
-    if (parent_i < limit) {
-      parent = path.At(parent_i * 2);
-      if (parent.IsArray()) {
-        intptr_t element_index = offset_from_parent.Value() -
+    if (i > 0) {
+      slot_offset ^= path.At((i * 2) - 1);
+      if (element.IsArray()) {
+        intptr_t element_index = slot_offset.Value() -
             (Array::element_offset(0) >> kWordSizeLog2);
         jselement.AddProperty("parentListIndex", element_index);
-      } else if (parent.IsInstance()) {
-        parent_class ^= parent.clazz();
-        parent_field_map = parent_class.OffsetToFieldMap();
-        intptr_t offset = offset_from_parent.Value();
-        if (offset > 0 && offset < parent_field_map.Length()) {
-          field ^= parent_field_map.At(offset);
+      } else if (element.IsInstance()) {
+        element_class ^= element.clazz();
+        element_field_map = element_class.OffsetToFieldMap();
+        intptr_t offset = slot_offset.Value();
+        if (offset > 0 && offset < element_field_map.Length()) {
+          field ^= element_field_map.At(offset);
           jselement.AddProperty("parentField", field);
         }
+      } else {
+        intptr_t element_index = slot_offset.Value();
+        jselement.AddProperty("_parentWordOffset", element_index);
       }
     }
   }
@@ -2328,6 +2346,7 @@
 static const MethodParameter* get_cpu_profile_params[] = {
   ISOLATE_PARAMETER,
   new EnumParameter("tags", true, tags_enum_names),
+  new BoolParameter("_codeTransitionTags", false),
   NULL,
 };
 
@@ -2336,7 +2355,11 @@
 static bool GetCpuProfile(Isolate* isolate, JSONStream* js) {
   Profile::TagOrder tag_order =
       EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
-  ProfilerService::PrintJSON(js, tag_order);
+  intptr_t extra_tags = 0;
+  if (BoolParameter::Parse(js->LookupParam("_codeTransitionTags"))) {
+    extra_tags |= ProfilerService::kCodeTransitionTagsBit;
+  }
+  ProfilerService::PrintJSON(js, tag_order, extra_tags);
   return true;
 }
 
@@ -2460,17 +2483,22 @@
     JSONStream js;
     {
       JSONObject jsobj(&js);
+      jsobj.AddProperty("jsonrpc", "2.0");
+      jsobj.AddProperty("method", "streamNotify");
       {
-        JSONObject event(&jsobj, "event");
-        event.AddProperty("type", "Event");
-        event.AddProperty("kind", "_Graph");
-        event.AddProperty("isolate", isolate);
+        JSONObject params(&jsobj, "params");
+        params.AddProperty("streamId", graph_stream.id());
+        {
+          JSONObject event(&params, "event");
+          event.AddProperty("type", "Event");
+          event.AddProperty("kind", "_Graph");
+          event.AddProperty("isolate", isolate);
 
-        event.AddProperty("chunkIndex", i);
-        event.AddProperty("chunkCount", num_chunks);
-        event.AddProperty("nodeCount", node_count);
+          event.AddProperty("chunkIndex", i);
+          event.AddProperty("chunkCount", num_chunks);
+          event.AddProperty("nodeCount", node_count);
+        }
       }
-      jsobj.AddProperty("streamId", graph_stream.id());
     }
 
     const String& message = String::Handle(String::New(js.ToCString()));
@@ -2512,6 +2540,30 @@
 }
 
 
+void Service::SendLogEvent(Isolate* isolate,
+                           int64_t sequence_number,
+                           int64_t timestamp,
+                           intptr_t level,
+                           const String& name,
+                           const String& message,
+                           const Instance& zone,
+                           const Object& error,
+                           const Instance& stack_trace) {
+  ServiceEvent::LogRecord log_record;
+  log_record.sequence_number = sequence_number;
+  log_record.timestamp = timestamp;
+  log_record.level = level;
+  log_record.name = &name;
+  log_record.message = &message;
+  log_record.zone = &zone;
+  log_record.error = &error;
+  log_record.stack_trace = &stack_trace;
+  ServiceEvent event(isolate, ServiceEvent::kLogging);
+  event.set_log_record(log_record);
+  Service::HandleEvent(&event);
+}
+
+
 class ContainsAddressVisitor : public FindObjectVisitor {
  public:
   ContainsAddressVisitor(Isolate* isolate, uword addr)
@@ -2540,6 +2592,29 @@
 };
 
 
+static RawObject* GetObjectHelper(Isolate* isolate, uword addr) {
+  Object& object = Object::Handle(isolate);
+
+  {
+    NoSafepointScope no_safepoint;
+    ContainsAddressVisitor visitor(isolate, addr);
+    object = isolate->heap()->FindObject(&visitor);
+  }
+
+  if (!object.IsNull()) {
+    return object.raw();
+  }
+
+  {
+    NoSafepointScope no_safepoint;
+    ContainsAddressVisitor visitor(Dart::vm_isolate(), addr);
+    object = Dart::vm_isolate()->heap()->FindObject(&visitor);
+  }
+
+  return object.raw();
+}
+
+
 static bool GetObjectByAddress(Isolate* isolate, JSONStream* js) {
   const char* addr_str = js->LookupParam("address");
   if (addr_str == NULL) {
@@ -2554,16 +2629,11 @@
     return true;
   }
   bool ref = js->HasParam("ref") && js->ParamIs("ref", "true");
-  Object& object = Object::Handle(isolate);
-  {
-    NoSafepointScope no_safepoint;
-    ContainsAddressVisitor visitor(isolate, addr);
-    object = isolate->heap()->FindObject(&visitor);
-  }
-  if (object.IsNull()) {
+  const Object& obj = Object::Handle(isolate, GetObjectHelper(isolate, addr));
+  if (obj.IsNull()) {
     PrintSentinel(js, kFreeSentinel);
   } else {
-    object.PrintJSON(js, ref);
+    obj.PrintJSON(js, ref);
   }
   return true;
 }
@@ -2706,7 +2776,7 @@
 static bool GetVersion(Isolate* isolate, JSONStream* js) {
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "Version");
-  jsobj.AddProperty("major", static_cast<intptr_t>(1));
+  jsobj.AddProperty("major", static_cast<intptr_t>(2));
   jsobj.AddProperty("minor", static_cast<intptr_t>(0));
   jsobj.AddProperty("_privateMajor", static_cast<intptr_t>(0));
   jsobj.AddProperty("_privateMinor", static_cast<intptr_t>(0));
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 9e253403..3b23f6d 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -108,12 +108,23 @@
                                 const uint8_t* bytes,
                                 intptr_t bytes_len);
 
+  static void SendLogEvent(Isolate* isolate,
+                           int64_t sequence_number,
+                           int64_t timestamp,
+                           intptr_t level,
+                           const String& name,
+                           const String& message,
+                           const Instance& zone,
+                           const Object& error,
+                           const Instance& stack_trace);
+
   // Well-known streams.
   static StreamInfo isolate_stream;
   static StreamInfo debug_stream;
   static StreamInfo gc_stream;
   static StreamInfo echo_stream;
   static StreamInfo graph_stream;
+  static StreamInfo logging_stream;
 
   static bool ListenStream(const char* stream_id);
   static void CancelStream(const char* stream_id);
@@ -137,6 +148,7 @@
   static void SendEvent(const char* stream_id,
                         const char* event_type,
                         const Object& eventMessage);
+
   // Does not take ownership of 'data'.
   static void SendEventWithData(const char* stream_id,
                                 const char* event_type,
@@ -144,6 +156,10 @@
                                 const uint8_t* data,
                                 intptr_t size);
 
+  static void PostEvent(const char* stream_id,
+                        const char* kind,
+                        JSONStream* event);
+
   static EmbedderServiceHandler* isolate_service_handler_head_;
   static EmbedderServiceHandler* root_service_handler_head_;
   static Dart_ServiceStreamListenCallback stream_listen_callback_;
diff --git a/runtime/vm/service/message.dart b/runtime/vm/service/message.dart
index 631f0a7..f27a48b 100644
--- a/runtime/vm/service/message.dart
+++ b/runtime/vm/service/message.dart
@@ -52,12 +52,12 @@
   }
 
   Message.fromUri(this.client, Uri uri)
-      : method = _methodNameFromUri(uri) {
+      : serial = '', method = _methodNameFromUri(uri) {
     params.addAll(uri.queryParameters);
   }
 
   Message.forIsolate(this.client, Uri uri, RunningIsolate isolate)
-      : method = _methodNameFromUri(uri) {
+      : serial = '', method = _methodNameFromUri(uri) {
     params.addAll(uri.queryParameters);
     params['isolateId'] = isolate.serviceId;
   }
@@ -102,7 +102,7 @@
     var request = new List(6)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = receivePort.sendPort
-        ..[2] = serial.toString()
+        ..[2] = serial
         ..[3] = method
         ..[4] = keys
         ..[5] = values;
@@ -129,7 +129,7 @@
     var request = new List(6)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = receivePort.sendPort
-        ..[2] = serial.toString()
+        ..[2] = serial
         ..[3] = method
         ..[4] = keys
         ..[5] = values;
@@ -143,6 +143,7 @@
 
   void setErrorResponse(String message) {
     var response = {
+      'jsonrpc': '2.0',
       'id': serial,
       'result' : {
         'type': 'Error',
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 338cc8e..f05214d 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,10 +1,9 @@
-# Dart VM Service Protocol 1.0 (Draft 1)
+# Dart VM Service Protocol 2.0
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes _draft 1_ of _version 1.0_ of the Dart VM
-Service Protocol.  This protocol is used to communicate with a running
-Dart Virtual Machine.
+This document describes of _version 2.0_ of the Dart VM Service Protocol. This
+protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
 The VM will start a webserver which services protocol requests via WebSocket.
@@ -12,10 +11,9 @@
 but this does not allow access to VM _events_ and is not documented
 here.
 
-The Service Protocol is based on JSON-RPC 2.0
-(http://www.jsonrpc.org/specification). The Service Protocol has been
-extended to support pushing _events_ to the client, which is
-apparently outside the scope of the JSON-RPC specification.
+The Service Protocol uses [JSON-RPC 2.0][].
+
+[JSON-RPC 2.0]: http://www.jsonrpc.org/specification
 
 **Table of Contents**
 
@@ -97,7 +95,7 @@
 }
 ```
 
-Currently the _id_ property must be a string. The Service Protocol
+The _id_ property must be a string, number, or `null`. The Service Protocol
 optionally accepts requests without the _jsonprc_ property.
 
 An RPC response is a JSON object (http://json.org/). The response always specifies an
@@ -108,10 +106,10 @@
 
 ```
 {
-  "json-rpc": "2.0",
+  "jsonrpc": "2.0",
   "result": {
     "type": "Version",
-    "major": 1,
+    "major": 2,
     "minor": 0
   }
   "id": "1"
@@ -152,7 +150,7 @@
 
 ```
 {
-  "json-rpc": "2.0",
+  "jsonrpc": "2.0",
   "error": {
     "code": 103,
     "message": "Stream already subscribed",
@@ -189,22 +187,27 @@
 access to events pertaining to isolate births, deaths, and name changes. See [streamListen](#streamlisten)
 for a list of the well-known stream ids and their associated events.
 
-Events arrive asynchronously over the WebSocket and always have the
-_streamId_ and _event_ properties:
+Stream events arrive asynchronously over the WebSocket. They're structured as
+JSON-RPC 2.0 requests with no _id_ property. The _method_ property will be
+_streamNotify_, and the _params_ will have _streamId_ and _event_ properties:
 
-```
+```json
 {
-  "event": {
-    "type": "Event",
-    "kind": "IsolateExit",
-    "isolate": {
-      "type": "@Isolate",
-      "id": "isolates/33",
-      "number": "51048743613",
-      "name": "worker-isolate"
+  "json-rpc": "2.0",
+  "method": "streamNotify",
+  "params": {
+    "streamId": "Isolate",
+    "event": {
+      "type": "Event",
+      "kind": "IsolateExit",
+      "isolate": {
+        "type": "@Isolate",
+        "id": "isolates/33",
+        "number": "51048743613",
+        "name": "worker-isolate"
+      }
     }
   }
-  "streamId": "Isolate"
 }
 ```
 
@@ -212,6 +215,7 @@
 Clients should be written to handle this gracefully.
 
 
+
 ## Types
 
 By convention, every result and event provided by the Service Protocol
@@ -295,7 +299,7 @@
 ```
   "result": {
     "type": "Version",
-    "major": 1,
+    "major": 2,
     "minor": 0
   }
 ```
diff --git a/runtime/vm/service/vmservice.dart b/runtime/vm/service/vmservice.dart
index e6889bb..2be15b6 100644
--- a/runtime/vm/service/vmservice.dart
+++ b/runtime/vm/service/vmservice.dart
@@ -156,6 +156,7 @@
 
   String _encodeError(Message message, int code, {String details}) {
     var response = {
+      'jsonrpc': '2.0',
       'id' : message.serial,
       'error' : {
         'code': code,
@@ -172,6 +173,7 @@
 
   String _encodeResult(Message message, Map result) {
     var response = {
+      'jsonrpc': '2.0',
       'id' : message.serial,
       'result' : result,
     };
@@ -259,7 +261,7 @@
     // Make requests to each isolate.
     for (var isolate in isolates) {
       for (var request in perIsolateRequests) {
-        var message = new Message.forIsolate(request, isolate);
+        var message = new Message.forIsolate(client, request, isolate);
         // Decode the JSON and and insert it into the map. The map key
         // is the request Uri.
         var response = JSON.decode(await isolate.route(message));
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index a53ace2..d704091 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -89,6 +89,8 @@
       return "Inspect";
     case kEmbedder:
       return embedder_kind();
+    case kLogging:
+      return "_Logging";
     case kDebuggerSettingsUpdate:
       return "_DebuggerSettingsUpdate";
     case kIllegal:
@@ -126,6 +128,9 @@
     case kEmbedder:
       return embedder_stream_id_;
 
+    case kLogging:
+      return Service::logging_stream.id();
+
     default:
       UNREACHABLE();
       return NULL;
@@ -135,9 +140,7 @@
 
 void ServiceEvent::PrintJSON(JSONStream* js) const {
   JSONObject jsobj(js);
-  jsobj.AddProperty("type", "Event");
-  jsobj.AddProperty("kind", KindAsCString());
-  jsobj.AddProperty("isolate", isolate());
+  PrintJSONHeader(&jsobj);
   if (kind() == kPauseBreakpoint) {
     JSONArray jsarr(&jsobj, "pauseBreakpoints");
     // TODO(rmacnak): If we are paused at more than one breakpoint,
@@ -163,7 +166,7 @@
   if (exception() != NULL) {
     jsobj.AddProperty("exception", *(exception()));
   }
-  if (async_continuation() != NULL) {
+  if (async_continuation() != NULL && !async_continuation()->IsNull()) {
     jsobj.AddProperty("_asyncContinuation", *(async_continuation()));
   }
   if (inspectee() != NULL) {
@@ -177,6 +180,25 @@
   if (bytes() != NULL) {
     jsobj.AddPropertyBase64("bytes", bytes(), bytes_length());
   }
+  if (kind() == kLogging) {
+    JSONObject logRecord(&jsobj, "logRecord");
+    logRecord.AddProperty64("sequenceNumber", log_record_.sequence_number);
+    logRecord.AddPropertyTimeMillis("time", log_record_.timestamp);
+    logRecord.AddProperty64("level", log_record_.level);
+    logRecord.AddProperty("loggerName", *(log_record_.name));
+    logRecord.AddProperty("message", *(log_record_.message));
+    logRecord.AddProperty("zone", *(log_record_.zone));
+    logRecord.AddProperty("error", *(log_record_.error));
+    logRecord.AddProperty("stackTrace", *(log_record_.stack_trace));
+  }
+}
+
+
+void ServiceEvent::PrintJSONHeader(JSONObject* jsobj) const {
+  ASSERT(jsobj != NULL);
+  jsobj->AddProperty("type", "Event");
+  jsobj->AddProperty("kind", KindAsCString());
+  jsobj->AddProperty("isolate", isolate());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index 8f81da5..6ebc211 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -34,9 +34,22 @@
 
     kEmbedder,
 
+    kLogging,
+
     kIllegal,
   };
 
+  struct LogRecord {
+    int64_t sequence_number;
+    int64_t timestamp;
+    intptr_t level;
+    const String* name;
+    const String* message;
+    const Instance* zone;
+    const Object* error;
+    const Instance* stack_trace;
+  };
+
   ServiceEvent(Isolate* isolate, EventKind event_kind)
       : isolate_(isolate),
         kind_(event_kind),
@@ -138,8 +151,14 @@
     bytes_length_ = bytes_length;
   }
 
+  void set_log_record(const LogRecord& log_record) {
+    log_record_ = log_record;
+  }
+
   void PrintJSON(JSONStream* js) const;
 
+  void PrintJSONHeader(JSONObject* jsobj) const;
+
  private:
   Isolate* isolate_;
   EventKind kind_;
@@ -153,6 +172,7 @@
   const Heap::GCStats* gc_stats_;
   const uint8_t* bytes_;
   intptr_t bytes_length_;
+  LogRecord log_record_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 8c16909..310305a 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -530,15 +530,15 @@
 
 
   Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, "[0, port, '0', 'alpha', [], []]");
+  service_msg = Eval(lib, "[0, port, '\"', 'alpha', [], []]");
   Service::HandleRootMessage(service_msg);
   handler.HandleNextMessage();
-  EXPECT_STREQ("{\"json-rpc\":\"2.0\", \"result\":alpha, \"id\":\"0\"}",
+  EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":alpha,\"id\":\"\\\"\"}",
                handler.msg());
-  service_msg = Eval(lib, "[0, port, '0', 'beta', [], []]");
+  service_msg = Eval(lib, "[0, port, 1, 'beta', [], []]");
   Service::HandleRootMessage(service_msg);
   handler.HandleNextMessage();
-  EXPECT_STREQ("{\"json-rpc\":\"2.0\", \"result\":beta, \"id\":\"0\"}",
+  EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":beta,\"id\":1}",
                handler.msg());
 }
 
@@ -573,12 +573,12 @@
   service_msg = Eval(lib, "[0, port, '0', 'alpha', [], []]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
-  EXPECT_STREQ("{\"json-rpc\":\"2.0\", \"result\":alpha, \"id\":\"0\"}",
+  EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":alpha,\"id\":\"0\"}",
                handler.msg());
   service_msg = Eval(lib, "[0, port, '0', 'beta', [], []]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
-  EXPECT_STREQ("{\"json-rpc\":\"2.0\", \"result\":beta, \"id\":\"0\"}",
+  EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":beta,\"id\":\"0\"}",
                handler.msg());
 }
 
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 37d4f43..45ae49a 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -3859,7 +3859,7 @@
   // Prepare for unwinding frames by destroying all the stack resources
   // in the previous C++ frames.
   Isolate* isolate = thread->isolate();
-  StackResource::Unwind(isolate);
+  StackResource::Unwind(thread);
 
   // Unwind the C++ stack and continue simulation in the target frame.
   set_register(PC, static_cast<int32_t>(pc));
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index c3dadd2..9663fdc 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -3519,7 +3519,7 @@
   // Prepare for unwinding frames by destroying all the stack resources
   // in the previous C++ frames.
   Isolate* isolate = thread->isolate();
-  StackResource::Unwind(isolate);
+  StackResource::Unwind(thread);
 
   // Unwind the C++ stack and continue simulation in the target frame.
   set_pc(static_cast<int64_t>(pc));
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index cd20f68..fdcdcf2 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -2467,7 +2467,7 @@
   // Prepare for unwinding frames by destroying all the stack resources
   // in the previous C++ frames.
   Isolate* isolate = thread->isolate();
-  StackResource::Unwind(isolate);
+  StackResource::Unwind(thread);
 
   // Unwind the C++ stack and continue simulation in the target frame.
   set_pc(static_cast<int32_t>(pc));
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index a566bc9..98ae976 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -20,6 +20,11 @@
 #include "vm/verified_memory.h"
 #include "vm/version.h"
 
+// We currently only expect the Dart mutator to read snapshots.
+#define ASSERT_NO_SAFEPOINT_SCOPE()                            \
+    isolate()->AssertCurrentThreadIsMutator();                 \
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0)
+
 namespace dart {
 
 static const int kNumVmIsolateSnapshotReferences = 32 * KB;
@@ -201,13 +206,15 @@
   // Setup for long jump in case there is an exception while reading.
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
-    PassiveObject& obj = PassiveObject::Handle(isolate(), ReadObjectImpl());
+    PassiveObject& obj =
+        PassiveObject::Handle(isolate(), ReadObjectImpl(kAsInlinedObject));
     for (intptr_t i = 0; i < backward_references_->length(); i++) {
       if (!(*backward_references_)[i].is_deserialized()) {
-        ReadObjectImpl();
+        ReadObjectImpl(kAsInlinedObject);
         (*backward_references_)[i].set_state(kIsDeserialized);
       }
     }
+    ProcessDeferredCanonicalizations();
     return obj.raw();
   } else {
     // An error occurred while reading, return the error object.
@@ -230,12 +237,12 @@
   Class& cls = Class::ZoneHandle(zone(), Class::null());
   AddBackRef(object_id, &cls, kIsDeserialized);
   // Read the library/class information and lookup the class.
-  str_ ^= ReadObjectImpl(class_header);
+  str_ ^= ReadObjectImpl(class_header, kAsInlinedObject, kInvalidPatchIndex, 0);
   library_ = Library::LookupLibrary(str_);
   if (library_.IsNull() || !library_.Loaded()) {
     SetReadException("Invalid object found in message.");
   }
-  str_ ^= ReadObjectImpl();
+  str_ ^= ReadObjectImpl(kAsInlinedObject);
   cls = library_.LookupClass(str_);
   if (cls.IsNull()) {
     SetReadException("Invalid object found in message.");
@@ -256,14 +263,14 @@
   AddBackRef(object_id, &obj, kIsDeserialized);
 
   // Read the library/class/function information and lookup the function.
-  str_ ^= ReadObjectImpl();
+  str_ ^= ReadObjectImpl(kAsInlinedObject);
   library_ = Library::LookupLibrary(str_);
   if (library_.IsNull() || !library_.Loaded()) {
     SetReadException("Invalid Library object found in message.");
   }
-  str_ ^= ReadObjectImpl();
+  str_ ^= ReadObjectImpl(kAsInlinedObject);
   if (str_.Equals(Symbols::TopLevel())) {
-    str_ ^= ReadObjectImpl();
+    str_ ^= ReadObjectImpl(kAsInlinedObject);
     func = library_.LookupFunctionAllowPrivate(str_);
   } else {
     cls_ = library_.LookupClassAllowPrivate(str_);
@@ -272,7 +279,7 @@
       SetReadException("Invalid Class object found in message.");
     }
     cls_.EnsureIsFinalized(isolate());
-    str_ ^= ReadObjectImpl();
+    str_ ^= ReadObjectImpl(kAsInlinedObject);
     func = cls_.LookupFunctionAllowPrivate(str_);
   }
   if (func.IsNull()) {
@@ -287,16 +294,6 @@
 }
 
 
-RawObject* SnapshotReader::ReadObjectImpl() {
-  int64_t value = Read<int64_t>();
-  if ((value & kSmiTagMask) == kSmiTag) {
-    return NewInteger(value);
-  }
-  ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
-  return ReadObjectImpl(static_cast<intptr_t>(value));
-}
-
-
 intptr_t SnapshotReader::NextAvailableObjectId() const {
   return backward_references_->length() +
       kMaxPredefinedObjectIds + max_vm_isolate_object_id_;
@@ -326,45 +323,63 @@
 }
 
 
-RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value) {
+RawObject* SnapshotReader::ReadObjectImpl(bool as_reference,
+                                          intptr_t patch_object_id,
+                                          intptr_t patch_offset) {
+  int64_t header_value = Read<int64_t>();
+  if ((header_value & kSmiTagMask) == kSmiTag) {
+    return NewInteger(header_value);
+  }
+  ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
+  return ReadObjectImpl(static_cast<intptr_t>(header_value),
+                        as_reference,
+                        patch_object_id,
+                        patch_offset);
+}
+
+
+RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value,
+                                          bool as_reference,
+                                          intptr_t patch_object_id,
+                                          intptr_t patch_offset) {
   if (IsVMIsolateObject(header_value)) {
     return ReadVMIsolateObject(header_value);
   } else {
     if (SerializedHeaderTag::decode(header_value) == kObjectId) {
-      return ReadIndexedObject(SerializedHeaderData::decode(header_value));
+      return ReadIndexedObject(SerializedHeaderData::decode(header_value),
+                               patch_object_id,
+                               patch_offset);
     }
     ASSERT(SerializedHeaderTag::decode(header_value) == kInlined);
     intptr_t object_id = SerializedHeaderData::decode(header_value);
     if (object_id == kOmittedObjectId) {
       object_id = NextAvailableObjectId();
     }
-    return ReadInlinedObject(object_id);
+
+    // Read the class header information.
+    intptr_t class_header = Read<int32_t>();
+    intptr_t tags = ReadTags();
+    if (as_reference && !RawObject::IsCanonical(tags)) {
+      return ReadObjectRef(object_id,
+                           class_header,
+                           tags,
+                           patch_object_id,
+                           patch_offset);
+    }
+    return ReadInlinedObject(object_id,
+                             class_header,
+                             tags,
+                             patch_object_id,
+                             patch_offset);
   }
 }
 
 
-RawObject* SnapshotReader::ReadObjectRef() {
-  int64_t header_value = Read<int64_t>();
-  if ((header_value & kSmiTagMask) == kSmiTag) {
-    return NewInteger(header_value);
-  }
-  ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
-  intptr_t value = static_cast<intptr_t>(header_value);
-  if (IsVMIsolateObject(value)) {
-    return ReadVMIsolateObject(value);
-  } else if (SerializedHeaderTag::decode(value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(value));
-  }
-  ASSERT(SerializedHeaderTag::decode(value) == kInlined);
-  intptr_t object_id = SerializedHeaderData::decode(value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-  ASSERT(GetBackRef(object_id) == NULL);
-
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-
+RawObject* SnapshotReader::ReadObjectRef(intptr_t object_id,
+                                         intptr_t class_header,
+                                         intptr_t tags,
+                                         intptr_t patch_object_id,
+                                         intptr_t patch_offset) {
   // Since we are only reading an object reference, If it is an instance kind
   // then we only need to figure out the class of the object and allocate an
   // instance of it. The individual fields will be read later.
@@ -373,7 +388,7 @@
     Instance& result = Instance::ZoneHandle(zone(), Instance::null());
     AddBackRef(object_id, &result, kIsNotDeserialized);
 
-    cls_ ^= ReadObjectImpl();  // Read class information.
+    cls_ ^= ReadObjectImpl(kAsInlinedObject);  // Read class information.
     ASSERT(!cls_.IsNull());
     intptr_t instance_size = cls_.instance_size();
     ASSERT(instance_size > 0);
@@ -387,7 +402,6 @@
     // We skip the tags that have been written as the implicit static
     // closure is going to be created in this isolate or the canonical
     // version already created in the isolate will be used.
-    ReadTags();
     return ReadStaticImplicitClosure(object_id, class_header);
   }
   ASSERT((class_header & kSmiTagMask) != kSmiTag);
@@ -419,7 +433,6 @@
   }
 
   // For all other internal VM classes we read the object inline.
-  intptr_t tags = ReadTags();
   switch (class_id) {
 #define SNAPSHOT_READ(clazz)                                                   \
     case clazz::kClassId: {                                                    \
@@ -455,14 +468,131 @@
 }
 
 
+RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id,
+                                             intptr_t class_header,
+                                             intptr_t tags,
+                                             intptr_t patch_object_id,
+                                             intptr_t patch_offset) {
+  // Lookup the class based on the class header information.
+  intptr_t header_id = SerializedHeaderData::decode(class_header);
+  if (header_id == kInstanceObjectId) {
+    // Object is regular dart instance.
+    Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
+    intptr_t instance_size = 0;
+    if (result == NULL) {
+      result = &(Instance::ZoneHandle(zone(), Instance::null()));
+      AddBackRef(object_id, result, kIsDeserialized);
+      cls_ ^= ReadObjectImpl(kAsInlinedObject);
+      ASSERT(!cls_.IsNull());
+      instance_size = cls_.instance_size();
+      ASSERT(instance_size > 0);
+      // Allocate the instance and read in all the fields for the object.
+      if (kind_ == Snapshot::kFull) {
+        *result ^= AllocateUninitialized(cls_.id(), instance_size);
+      } else {
+        *result ^= Object::Allocate(cls_.id(),
+                                    instance_size,
+                                    HEAP_SPACE(kind_));
+      }
+    } else {
+      cls_ ^= ReadObjectImpl(kAsInlinedObject);
+      ASSERT(!cls_.IsNull());
+      instance_size = cls_.instance_size();
+    }
+    intptr_t next_field_offset = cls_.next_field_offset();
+    intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
+    ASSERT(next_field_offset > 0);
+    // Instance::NextFieldOffset() returns the offset of the first field in
+    // a Dart object.
+    bool as_reference = RawObject::IsCanonical(tags) ? false : true;
+    intptr_t offset = Instance::NextFieldOffset();
+    intptr_t result_cid = result->GetClassId();
+    while (offset < next_field_offset) {
+      pobj_ = ReadObjectImpl(as_reference);
+      result->SetFieldAtOffset(offset, pobj_);
+      if ((offset != type_argument_field_offset) &&
+          (kind_ == Snapshot::kMessage)) {
+        // TODO(fschneider): Consider hoisting these lookups out of the loop.
+        // This would involve creating a handle, since cls_ can't be reused
+        // across the call to ReadObjectImpl.
+        cls_ = isolate()->class_table()->At(result_cid);
+        array_ = cls_.OffsetToFieldMap();
+        field_ ^= array_.At(offset >> kWordSizeLog2);
+        ASSERT(!field_.IsNull());
+        ASSERT(field_.Offset() == offset);
+        obj_ = pobj_.raw();
+        field_.RecordStore(obj_);
+      }
+      // TODO(fschneider): Verify the guarded cid and length for other kinds of
+      // snapshot (kFull, kScript) with asserts.
+      offset += kWordSize;
+    }
+    if (kind_ == Snapshot::kFull) {
+      // We create an uninitialized object in the case of full snapshots, so
+      // we need to initialize any remaining padding area with the Null object.
+      while (offset < instance_size) {
+        result->SetFieldAtOffset(offset, Object::null_object());
+        offset += kWordSize;
+      }
+      result->SetCreatedFromSnapshot();
+    } else if (RawObject::IsCanonical(tags)) {
+      *result = result->CheckAndCanonicalize(NULL);
+      ASSERT(!result->IsNull());
+    }
+    return result->raw();
+  } else if (header_id == kStaticImplicitClosureObjectId) {
+    // We do not use the tags as the implicit static closure
+    // is going to be created in this isolate or the canonical
+    // version already created in the isolate will be used.
+    return ReadStaticImplicitClosure(object_id, class_header);
+  }
+  ASSERT((class_header & kSmiTagMask) != kSmiTag);
+  intptr_t class_id = LookupInternalClass(class_header);
+  switch (class_id) {
+#define SNAPSHOT_READ(clazz)                                                   \
+    case clazz::kClassId: {                                                    \
+      pobj_ = clazz::ReadFrom(this, object_id, tags, kind_);                   \
+      break;                                                                   \
+    }
+    CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
+#undef SNAPSHOT_READ
+#define SNAPSHOT_READ(clazz)                                                   \
+    case kTypedData##clazz##Cid:                                               \
+
+    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
+      tags = RawObject::ClassIdTag::update(class_id, tags);
+      pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_);
+      break;
+    }
+#undef SNAPSHOT_READ
+#define SNAPSHOT_READ(clazz)                                                   \
+    case kExternalTypedData##clazz##Cid:                                       \
+
+    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
+      tags = RawObject::ClassIdTag::update(class_id, tags);
+      pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_);
+      break;
+    }
+#undef SNAPSHOT_READ
+    default: UNREACHABLE(); break;
+  }
+  if (kind_ == Snapshot::kFull) {
+    pobj_.SetCreatedFromSnapshot();
+  }
+  AddPatchRecord(object_id, patch_object_id, patch_offset);
+  return pobj_.raw();
+}
+
+
 void SnapshotReader::AddBackRef(intptr_t id,
                                 Object* obj,
-                                DeserializeState state) {
+                                DeserializeState state,
+                                bool defer_canonicalization) {
   intptr_t index = (id - kMaxPredefinedObjectIds);
   ASSERT(index >= max_vm_isolate_object_id_);
   index -= max_vm_isolate_object_id_;
   ASSERT(index == backward_references_->length());
-  BackRefNode node(obj, state);
+  BackRefNode node(obj, state, defer_canonicalization);
   backward_references_->Add(node);
 }
 
@@ -518,11 +648,11 @@
     // Read in all the objects stored in the object store.
     intptr_t num_flds = (object_store->to() - object_store->from());
     for (intptr_t i = 0; i <= num_flds; i++) {
-      *(object_store->from() + i) = ReadObjectImpl();
+      *(object_store->from() + i) = ReadObjectImpl(kAsInlinedObject);
     }
     for (intptr_t i = 0; i < backward_references_->length(); i++) {
       if (!(*backward_references_)[i].is_deserialized()) {
-        ReadObjectImpl();
+        ReadObjectImpl(kAsInlinedObject);
         (*backward_references_)[i].set_state(kIsDeserialized);
       }
     }
@@ -609,7 +739,7 @@
 
 #define ALLOC_NEW_OBJECT_WITH_LEN(type, length)                                \
   ASSERT(kind_ == Snapshot::kFull);                                            \
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);                          \
+  ASSERT_NO_SAFEPOINT_SCOPE();                                                 \
   Raw##type* obj = reinterpret_cast<Raw##type*>(                               \
       AllocateUninitialized(k##type##Cid, type::InstanceSize(length)));        \
   obj->StoreSmi(&(obj->ptr()->length_), Smi::New(length));                     \
@@ -643,7 +773,7 @@
 
 RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   stream_ = reinterpret_cast<RawTokenStream*>(
       AllocateUninitialized(kTokenStreamCid, TokenStream::InstanceSize()));
   uint8_t* array = const_cast<uint8_t*>(CurrentBufferAddress());
@@ -661,7 +791,7 @@
 
 RawContext* SnapshotReader::NewContext(intptr_t num_variables) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawContext* obj = reinterpret_cast<RawContext*>(
       AllocateUninitialized(kContextCid, Context::InstanceSize(num_variables)));
   obj->ptr()->num_variables_ = num_variables;
@@ -671,7 +801,7 @@
 
 RawClass* SnapshotReader::NewClass(intptr_t class_id) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   if (class_id < kNumPredefinedCids) {
     ASSERT((class_id >= kInstanceCid) &&
            (class_id <= kNullCid));
@@ -690,7 +820,7 @@
 
 RawInstance* SnapshotReader::NewInstance() {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawInstance* obj = reinterpret_cast<RawInstance*>(
       AllocateUninitialized(kObjectCid, Instance::InstanceSize()));
   return obj;
@@ -699,7 +829,7 @@
 
 RawMint* SnapshotReader::NewMint(int64_t value) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawMint* obj = reinterpret_cast<RawMint*>(
       AllocateUninitialized(kMintCid, Mint::InstanceSize()));
   obj->ptr()->value_ = value;
@@ -709,7 +839,7 @@
 
 RawDouble* SnapshotReader::NewDouble(double value) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawDouble* obj = reinterpret_cast<RawDouble*>(
       AllocateUninitialized(kDoubleCid, Double::InstanceSize()));
   obj->ptr()->value_ = value;
@@ -719,7 +849,7 @@
 
 RawTypedData* SnapshotReader::NewTypedData(intptr_t class_id, intptr_t len) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   const intptr_t lengthInBytes = len * TypedData::ElementSizeInBytes(class_id);
   RawTypedData* obj = reinterpret_cast<RawTypedData*>(
       AllocateUninitialized(class_id, TypedData::InstanceSize(lengthInBytes)));
@@ -730,7 +860,7 @@
 
 #define ALLOC_NEW_OBJECT(type)                                                 \
   ASSERT(kind_ == Snapshot::kFull);                                            \
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);                          \
+  ASSERT_NO_SAFEPOINT_SCOPE();                                                 \
   return reinterpret_cast<Raw##type*>(                                         \
       AllocateUninitialized(k##type##Cid, type::InstanceSize()));              \
 
@@ -828,7 +958,7 @@
 RawFloat32x4* SnapshotReader::NewFloat32x4(float v0, float v1, float v2,
                                            float v3) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawFloat32x4* obj = reinterpret_cast<RawFloat32x4*>(
       AllocateUninitialized(kFloat32x4Cid, Float32x4::InstanceSize()));
   obj->ptr()->value_[0] = v0;
@@ -842,7 +972,7 @@
 RawInt32x4* SnapshotReader::NewInt32x4(uint32_t v0, uint32_t v1, uint32_t v2,
                                        uint32_t v3) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawInt32x4* obj = reinterpret_cast<RawInt32x4*>(
       AllocateUninitialized(kInt32x4Cid, Int32x4::InstanceSize()));
   obj->ptr()->value_[0] = v0;
@@ -855,7 +985,7 @@
 
 RawFloat64x2* SnapshotReader::NewFloat64x2(double v0, double v1) {
   ASSERT(kind_ == Snapshot::kFull);
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   RawFloat64x2* obj = reinterpret_cast<RawFloat64x2*>(
       AllocateUninitialized(kFloat64x2Cid, Float64x2::InstanceSize()));
   obj->ptr()->value_[0] = v0;
@@ -914,7 +1044,7 @@
 
 RawObject* SnapshotReader::AllocateUninitialized(intptr_t class_id,
                                                  intptr_t size) {
-  ASSERT(isolate()->no_safepoint_scope_depth() != 0);
+  ASSERT_NO_SAFEPOINT_SCOPE();
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
 
   // Allocate memory where all words look like smis. This is currently
@@ -987,7 +1117,9 @@
 }
 
 
-RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
+RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id,
+                                             intptr_t patch_object_id,
+                                             intptr_t patch_offset) {
   intptr_t class_id = ClassIdFromObjectId(object_id);
   if (IsObjectStoreClassId(class_id)) {
     return isolate()->class_table()->At(class_id);  // get singleton class.
@@ -1002,137 +1134,90 @@
   if (index < max_vm_isolate_object_id_) {
     return VmIsolateSnapshotObject(index);
   }
+  AddPatchRecord(object_id, patch_object_id, patch_offset);
   return GetBackRef(object_id)->raw();
 }
 
 
-RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-  intptr_t tags = ReadTags();
-  intptr_t header_id = SerializedHeaderData::decode(class_header);
-  if (header_id == kInstanceObjectId) {
-    // Object is regular dart instance.
-    Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
-    intptr_t instance_size = 0;
-    if (result == NULL) {
-      result = &(Instance::ZoneHandle(zone(), Instance::null()));
-      AddBackRef(object_id, result, kIsDeserialized);
-      cls_ ^= ReadObjectImpl();
-      ASSERT(!cls_.IsNull());
-      instance_size = cls_.instance_size();
-      ASSERT(instance_size > 0);
-      // Allocate the instance and read in all the fields for the object.
-      if (kind_ == Snapshot::kFull) {
-        *result ^= AllocateUninitialized(cls_.id(), instance_size);
-      } else {
-        *result ^= Object::Allocate(cls_.id(),
-                                    instance_size,
-                                    HEAP_SPACE(kind_));
-      }
-    } else {
-      cls_ ^= ReadObjectImpl();
-      ASSERT(!cls_.IsNull());
-      instance_size = cls_.instance_size();
-    }
-    intptr_t next_field_offset = cls_.next_field_offset();
-    intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
-    ASSERT(next_field_offset > 0);
-    // Instance::NextFieldOffset() returns the offset of the first field in
-    // a Dart object.
-    bool is_canonical = RawObject::IsCanonical(tags);
-    intptr_t offset = Instance::NextFieldOffset();
-    intptr_t result_cid = result->GetClassId();
-    while (offset < next_field_offset) {
-      pobj_ = is_canonical ? ReadObjectImpl() : ReadObjectRef();
-      result->SetFieldAtOffset(offset, pobj_);
-      if ((offset != type_argument_field_offset) &&
-          (kind_ == Snapshot::kMessage)) {
-        // TODO(fschneider): Consider hoisting these lookups out of the loop.
-        // This would involve creating a handle, since cls_ can't be reused
-        // across the call to ReadObjectRef.
-        cls_ = isolate()->class_table()->At(result_cid);
-        array_ = cls_.OffsetToFieldMap();
-        field_ ^= array_.At(offset >> kWordSizeLog2);
-        ASSERT(!field_.IsNull());
-        ASSERT(field_.Offset() == offset);
-        obj_ = pobj_.raw();
-        field_.RecordStore(obj_);
-      }
-      // TODO(fschneider): Verify the guarded cid and length for other kinds of
-      // snapshot (kFull, kScript) with asserts.
-      offset += kWordSize;
-    }
-    if (kind_ == Snapshot::kFull) {
-      // We create an uninitialized object in the case of full snapshots, so
-      // we need to initialize any remaining padding area with the Null object.
-      while (offset < instance_size) {
-        result->SetFieldAtOffset(offset, Object::null_object());
-        offset += kWordSize;
-      }
-      result->SetCreatedFromSnapshot();
-    } else if (RawObject::IsCanonical(tags)) {
-      *result = result->CheckAndCanonicalize(NULL);
-      ASSERT(!result->IsNull());
-    }
-    return result->raw();
-  } else if (header_id == kStaticImplicitClosureObjectId) {
-    // We do not use the tags as the implicit static closure
-    // is going to be created in this isolate or the canonical
-    // version already created in the isolate will be used.
-    return ReadStaticImplicitClosure(object_id, class_header);
+void SnapshotReader::AddPatchRecord(intptr_t object_id,
+                                    intptr_t patch_object_id,
+                                    intptr_t patch_offset) {
+  if (patch_object_id != kInvalidPatchIndex && kind() != Snapshot::kFull) {
+    ASSERT(object_id >= kMaxPredefinedObjectIds);
+    intptr_t index = (object_id - kMaxPredefinedObjectIds);
+    ASSERT(index >= max_vm_isolate_object_id_);
+    index -= max_vm_isolate_object_id_;
+    ASSERT(index < backward_references_->length());
+    BackRefNode& ref = (*backward_references_)[index];
+    ref.AddPatchRecord(patch_object_id, patch_offset);
   }
-  ASSERT((class_header & kSmiTagMask) != kSmiTag);
-  intptr_t class_id = LookupInternalClass(class_header);
-  switch (class_id) {
-#define SNAPSHOT_READ(clazz)                                                   \
-    case clazz::kClassId: {                                                    \
-      pobj_ = clazz::ReadFrom(this, object_id, tags, kind_);                   \
-      break;                                                                   \
-    }
-    CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz)                                                   \
-    case kTypedData##clazz##Cid:                                               \
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = RawObject::ClassIdTag::update(class_id, tags);
-      pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_);
-      break;
-    }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz)                                                   \
-    case kExternalTypedData##clazz##Cid:                                       \
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = RawObject::ClassIdTag::update(class_id, tags);
-      pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_);
-      break;
-    }
-#undef SNAPSHOT_READ
-    default: UNREACHABLE(); break;
-  }
-  if (kind_ == Snapshot::kFull) {
-    pobj_.SetCreatedFromSnapshot();
-  }
-  return pobj_.raw();
 }
 
 
-void SnapshotReader::ArrayReadFrom(const Array& result,
+void SnapshotReader::ProcessDeferredCanonicalizations() {
+  AbstractType& typeobj = AbstractType::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 an abstract type or a type argument.
+      if (objref->IsAbstractType()) {
+        typeobj ^= objref->raw();
+        typeobj.ClearCanonical();
+        newobj = typeobj.Canonicalize();
+      } else {
+        ASSERT(objref->IsTypeArguments());
+        typeargs ^= objref->raw();
+        typeargs.ClearCanonical();
+        newobj = typeargs.Canonicalize();
+      }
+      if (newobj.raw() == objref->raw()) {
+        // Restore Canonical bit.
+        objref->SetCanonical();
+      } else {
+        ZoneGrowableArray<intptr_t>* patches = backref.patch_records();
+        ASSERT(newobj.IsCanonical());
+        ASSERT(patches != NULL);
+        for (intptr_t j = 0; j < patches->length(); j+=2) {
+          NoSafepointScope no_safepoint;
+          intptr_t patch_object_id = (*patches)[j];
+          intptr_t patch_offset = (*patches)[j + 1];
+          Object* target = GetBackRef(patch_object_id);
+          RawObject** rawptr =
+              reinterpret_cast<RawObject**>(target->raw()->ptr());
+          target->StorePointer((rawptr + patch_offset), newobj.raw());
+        }
+      }
+    }
+  }
+}
+
+
+void SnapshotReader::ArrayReadFrom(intptr_t object_id,
+                                   const Array& result,
                                    intptr_t len,
                                    intptr_t tags) {
   // Set the object tags.
   result.set_tags(tags);
 
   // Setup the object fields.
-  *TypeArgumentsHandle() ^= ReadObjectImpl();
+  const intptr_t typeargs_offset =
+      reinterpret_cast<RawObject**>(&result.raw()->ptr()->type_arguments_) -
+      reinterpret_cast<RawObject**>(result.raw()->ptr());
+  *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject,
+                                           object_id,
+                                           typeargs_offset);
   result.SetTypeArguments(*TypeArgumentsHandle());
 
-  bool is_canonical = RawObject::IsCanonical(tags);
-
+  bool as_reference = RawObject::IsCanonical(tags) ? false : true;
+  intptr_t offset = result.raw_ptr()->data() -
+      reinterpret_cast<RawObject**>(result.raw()->ptr());
   for (intptr_t i = 0; i < len; i++) {
-    *PassiveObjectHandle() = is_canonical ? ReadObjectImpl() : ReadObjectRef();
+    *PassiveObjectHandle() = ReadObjectImpl(as_reference,
+                                            object_id,
+                                            (i + offset));
     result.SetAt(i, *PassiveObjectHandle());
   }
 }
@@ -1279,7 +1364,7 @@
 
 
 void SnapshotWriter::WriteObject(RawObject* rawobj) {
-  WriteObjectImpl(rawobj);
+  WriteObjectImpl(rawobj, kAsInlinedObject);
   WriteForwardedObjects();
 }
 
@@ -1402,104 +1487,6 @@
 #undef VM_OBJECT_WRITE
 
 
-void SnapshotWriter::WriteObjectRef(RawObject* raw) {
-  // First check if object can be written as a simple predefined type.
-  if (CheckAndWritePredefinedObject(raw)) {
-    return;
-  }
-
-  NoSafepointScope no_safepoint;
-  RawClass* cls = class_table_->At(raw->GetClassId());
-  intptr_t class_id = cls->ptr()->id_;
-  ASSERT(class_id == raw->GetClassId());
-  if (class_id >= kNumPredefinedCids) {
-    WriteInstanceRef(raw, cls);
-    return;
-  }
-  if (class_id == kArrayCid) {
-    // Object is being referenced, add it to the forward ref list and mark
-    // it so that future references to this object in the snapshot will use
-    // this object id. Mark it as not having been serialized yet so that we
-    // will serialize the object when we go through the forward list.
-    forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
-
-    RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
-
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(kOmittedObjectId);
-
-    // Write out the class information.
-    WriteIndexedObject(kArrayCid);
-
-    // Write out the length field.
-    Write<RawObject*>(rawarray->ptr()->length_);
-
-    return;
-  }
-  if (class_id == kImmutableArrayCid) {
-    // Object is being referenced, add it to the forward ref list and mark
-    // it so that future references to this object in the snapshot will use
-    // this object id. Mark it as not having been serialized yet so that we
-    // will serialize the object when we go through the forward list.
-    forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
-
-    RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
-
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(kOmittedObjectId);
-
-    // Write out the class information.
-    WriteIndexedObject(kImmutableArrayCid);
-
-    // Write out the length field.
-    Write<RawObject*>(rawarray->ptr()->length_);
-
-    return;
-  }
-  if (RawObject::IsImplicitFieldClassId(class_id)) {
-    WriteInstanceRef(raw, cls);
-    return;
-  }
-  // Add object to the forward ref list and mark it so that future references
-  // to this object in the snapshot will use this object id. Mark it as having
-  // been serialized so that we do not serialize the object when we go through
-  // the forward list.
-  forward_list_->MarkAndAddObject(raw, kIsSerialized);
-  switch (class_id) {
-#define SNAPSHOT_WRITE(clazz)                                                  \
-    case clazz::kClassId: {                                                    \
-      Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw);                \
-      raw_obj->WriteTo(this, kOmittedObjectId, kind_);                         \
-      return;                                                                  \
-    }                                                                          \
-
-    CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz)                                                  \
-    case kTypedData##clazz##Cid:                                               \
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-      RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw);
-      raw_obj->WriteTo(this, kOmittedObjectId, kind_);
-      return;
-    }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz)                                                  \
-    case kExternalTypedData##clazz##Cid:                                       \
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-      RawExternalTypedData* raw_obj =
-        reinterpret_cast<RawExternalTypedData*>(raw);
-      raw_obj->WriteTo(this, kOmittedObjectId, kind_);
-      return;
-    }
-#undef SNAPSHOT_WRITE
-    default: break;
-  }
-  UNREACHABLE();
-}
-
-
 // An object visitor which will iterate over all the script objects in the heap
 // and either count them or collect them into an array. This is used during
 // full snapshot generation of the VM isolate to write out all script
@@ -1703,14 +1690,15 @@
       first_unprocessed_object_id_(first_object_id) {
   // The ForwardList encodes information in the header tag word. There cannot
   // be any concurrent GC tasks while it is in use.
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
   PageSpace* page_space = isolate->heap()->old_space();
   MonitorLocker ml(page_space->tasks_lock());
   while (page_space->tasks() > 0) {
     ml.Wait();
   }
   // Ensure that no GC happens while we are writing out the full snapshot.
-  isolate->IncrementNoSafepointScopeDepth();
+  thread->IncrementNoSafepointScopeDepth();
 }
 
 
@@ -1769,7 +1757,7 @@
       raw->ptr()->tags_ = node->tags();  // Restore original tags.
     }
   }
-  Isolate::Current()->DecrementNoSafepointScopeDepth();
+  Thread::Current()->DecrementNoSafepointScopeDepth();
 }
 
 
@@ -1847,18 +1835,95 @@
 }
 
 
-void SnapshotWriter::WriteObjectImpl(RawObject* raw) {
+void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) {
   // First check if object can be written as a simple predefined type.
   if (CheckAndWritePredefinedObject(raw)) {
     return;
   }
 
-  // Object is being serialized, add it to the forward ref list and mark
-  // it so that future references to this object in the snapshot will use
-  // an object id, instead of trying to serialize it again.
-  forward_list_->MarkAndAddObject(raw, kIsSerialized);
+  if (as_reference && !raw->IsCanonical()) {
+    WriteObjectRef(raw);
+  } else {
+    // Object is being serialized, add it to the forward ref list and mark
+    // it so that future references to this object in the snapshot will use
+    // an object id, instead of trying to serialize it again.
+    forward_list_->MarkAndAddObject(raw, kIsSerialized);
 
-  WriteInlinedObject(raw);
+    WriteInlinedObject(raw);
+  }
+}
+
+
+void SnapshotWriter::WriteObjectRef(RawObject* raw) {
+  NoSafepointScope no_safepoint;
+  RawClass* cls = class_table_->At(raw->GetClassId());
+  intptr_t class_id = cls->ptr()->id_;
+  ASSERT(class_id == raw->GetClassId());
+  if (class_id >= kNumPredefinedCids ||
+      RawObject::IsImplicitFieldClassId(class_id)) {
+    WriteInstanceRef(raw, cls);
+    return;
+  }
+  if (class_id == kArrayCid || class_id == kImmutableArrayCid) {
+    intptr_t tags = GetObjectTags(raw);
+
+    // Object is being referenced, add it to the forward ref list and mark
+    // it so that future references to this object in the snapshot will use
+    // this object id. Mark it as not having been serialized yet so that we
+    // will serialize the object when we go through the forward list.
+    forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
+
+    RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
+
+    // Write out the serialization header value for this object.
+    WriteInlinedObjectHeader(kOmittedObjectId);
+
+    // Write out the class information.
+    WriteIndexedObject(class_id);
+    WriteTags(tags);
+
+    // Write out the length field.
+    Write<RawObject*>(rawarray->ptr()->length_);
+
+    return;
+  }
+  // Add object to the forward ref list and mark it so that future references
+  // to this object in the snapshot will use this object id. Mark it as having
+  // been serialized so that we do not serialize the object when we go through
+  // the forward list.
+  forward_list_->MarkAndAddObject(raw, kIsSerialized);
+  switch (class_id) {
+#define SNAPSHOT_WRITE(clazz)                                                  \
+    case clazz::kClassId: {                                                    \
+      Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw);                \
+      raw_obj->WriteTo(this, kOmittedObjectId, kind_);                         \
+      return;                                                                  \
+    }                                                                          \
+
+    CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
+#undef SNAPSHOT_WRITE
+#define SNAPSHOT_WRITE(clazz)                                                  \
+    case kTypedData##clazz##Cid:                                               \
+
+    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
+      RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw);
+      raw_obj->WriteTo(this, kOmittedObjectId, kind_);
+      return;
+    }
+#undef SNAPSHOT_WRITE
+#define SNAPSHOT_WRITE(clazz)                                                  \
+    case kExternalTypedData##clazz##Cid:                                       \
+
+    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
+      RawExternalTypedData* raw_obj =
+        reinterpret_cast<RawExternalTypedData*>(raw);
+      raw_obj->WriteTo(this, kOmittedObjectId, kind_);
+      return;
+    }
+#undef SNAPSHOT_WRITE
+    default: break;
+  }
+  UNREACHABLE();
 }
 
 
@@ -1988,8 +2053,8 @@
   // Write out the library url and class name.
   RawLibrary* library = cls->ptr()->library_;
   ASSERT(library != Library::null());
-  WriteObjectImpl(library->ptr()->url_);
-  WriteObjectImpl(cls->ptr()->name_);
+  WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
+  WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
 }
 
 
@@ -2010,9 +2075,9 @@
   ASSERT(cls != Class::null());
   RawLibrary* library = cls->ptr()->library_;
   ASSERT(library != Library::null());
-  WriteObjectImpl(library->ptr()->url_);
-  WriteObjectImpl(cls->ptr()->name_);
-  WriteObjectImpl(func->ptr()->name_);
+  WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
+  WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
+  WriteObjectImpl(func->ptr()->name_, kAsInlinedObject);
 }
 
 
@@ -2035,16 +2100,12 @@
   Write<RawObject*>(length);
 
   // Write out the type arguments.
-  WriteObjectImpl(type_arguments);
+  WriteObjectImpl(type_arguments, kAsInlinedObject);
 
   // Write out the individual object ids.
-  bool is_canonical = RawObject::IsCanonical(tags);
+  bool as_reference = RawObject::IsCanonical(tags) ? false : true;
   for (intptr_t i = 0; i < len; i++) {
-    if (is_canonical) {
-      WriteObjectImpl(data[i]);
-    } else {
-      WriteObjectRef(data[i]);
-    }
+    WriteObjectImpl(data[i], as_reference);
   }
 }
 
@@ -2153,21 +2214,17 @@
   WriteTags(tags);
 
   // Write out the class information for this object.
-  WriteObjectImpl(cls);
+  WriteObjectImpl(cls, kAsInlinedObject);
 
   // Write out all the fields for the object.
   // Instance::NextFieldOffset() returns the offset of the first field in
   // a Dart object.
-  bool is_canonical = RawObject::IsCanonical(tags);
+  bool as_reference = RawObject::IsCanonical(tags) ? false : true;
   intptr_t offset = Instance::NextFieldOffset();
   while (offset < next_field_offset) {
     RawObject* raw_obj = *reinterpret_cast<RawObject**>(
         reinterpret_cast<uword>(raw->ptr()) + offset);
-    if (is_canonical) {
-      WriteObjectImpl(raw_obj);
-    } else {
-      WriteObjectRef(raw_obj);
-    }
+    WriteObjectImpl(raw_obj, as_reference);
     offset += kWordSize;
   }
   return;
@@ -2199,6 +2256,7 @@
   // it so that future references to this object in the snapshot will use
   // this object id. Mark it as not having been serialized yet so that we
   // will serialize the object when we go through the forward list.
+  intptr_t tags = raw->ptr()->tags_;
   forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
 
   // Write out the serialization header value for this object.
@@ -2206,9 +2264,10 @@
 
   // Indicate this is an instance object.
   Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
+  WriteTags(tags);
 
   // Write out the class information for this object.
-  WriteObjectImpl(cls);
+  WriteObjectImpl(cls, kAsInlinedObject);
 }
 
 
@@ -2307,11 +2366,7 @@
 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) {
   for (RawObject** current = first; current <= last; current++) {
     RawObject* raw_obj = *current;
-    if (as_references_) {
-      writer_->WriteObjectRef(raw_obj);
-    } else {
-      writer_->WriteObjectImpl(raw_obj);
-    }
+    writer_->WriteObjectImpl(raw_obj, as_references_);
   }
 }
 
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 1989c7b..161da59 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -97,6 +97,9 @@
 static const int8_t kHeaderTagBits = 2;
 static const int8_t kObjectIdBits = (kBitsPerInt32 - (kHeaderTagBits + 1));
 static const intptr_t kMaxObjectId = (kMaxUint32 >> (kHeaderTagBits + 1));
+static const bool kAsReference = true;
+static const bool kAsInlinedObject = false;
+static const intptr_t kInvalidPatchIndex = -1;
 
 
 class SerializedHeaderTag : public BitField<enum SerializedHeaderType,
@@ -248,21 +251,42 @@
 
 class BackRefNode : public ValueObject {
  public:
-  BackRefNode(Object* reference, DeserializeState state)
-      : reference_(reference), state_(state) {}
+  BackRefNode(Object* reference,
+              DeserializeState state,
+              bool defer_canonicalization)
+      : reference_(reference),
+        state_(state),
+        defer_canonicalization_(defer_canonicalization),
+        patch_records_(NULL) {}
   Object* reference() const { return reference_; }
   bool is_deserialized() const { return state_ == kIsDeserialized; }
   void set_state(DeserializeState state) { state_ = state; }
+  bool defer_canonicalization() const { return defer_canonicalization_; }
+  ZoneGrowableArray<intptr_t>* patch_records() const { return patch_records_; }
 
   BackRefNode& operator=(const BackRefNode& other) {
     reference_ = other.reference_;
     state_ = other.state_;
+    defer_canonicalization_ = other.defer_canonicalization_;
+    patch_records_ = other.patch_records_;
     return *this;
   }
 
+  void AddPatchRecord(intptr_t patch_object_id, intptr_t patch_offset) {
+    if (defer_canonicalization_) {
+      if (patch_records_ == NULL) {
+        patch_records_ = new ZoneGrowableArray<intptr_t>();
+      }
+      patch_records_->Add(patch_object_id);
+      patch_records_->Add(patch_offset);
+    }
+  }
+
  private:
   Object* reference_;
   DeserializeState state_;
+  bool defer_canonicalization_;
+  ZoneGrowableArray<intptr_t>* patch_records_;
 };
 
 
@@ -290,7 +314,10 @@
   RawObject* ReadObject();
 
   // Add object to backward references.
-  void AddBackRef(intptr_t id, Object* obj, DeserializeState state);
+  void AddBackRef(intptr_t id,
+                  Object* obj,
+                  DeserializeState state,
+                  bool defer_canonicalization = false);
 
   // Get an object from the backward references list.
   Object* GetBackRef(intptr_t id);
@@ -367,24 +394,55 @@
 
   RawClass* ReadClassId(intptr_t object_id);
   RawObject* ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
-  RawObject* ReadObjectImpl();
-  RawObject* ReadObjectImpl(intptr_t header);
-  RawObject* ReadObjectRef();
+
+  // Implementation to read an object.
+  RawObject* ReadObjectImpl(bool as_reference,
+                            intptr_t patch_object_id = kInvalidPatchIndex,
+                            intptr_t patch_offset = 0);
+  RawObject* ReadObjectImpl(intptr_t header,
+                            bool as_reference,
+                            intptr_t patch_object_id,
+                            intptr_t patch_offset);
+
+  // Read an object reference from the stream.
+  RawObject* ReadObjectRef(intptr_t object_id,
+                           intptr_t class_header,
+                           intptr_t tags,
+                           intptr_t patch_object_id = kInvalidPatchIndex,
+                           intptr_t patch_offset = 0);
+
+  // Read an inlined object from the stream.
+  RawObject* ReadInlinedObject(intptr_t object_id,
+                               intptr_t class_header,
+                               intptr_t tags,
+                               intptr_t patch_object_id,
+                               intptr_t patch_offset);
 
   // Read a VM isolate object that was serialized as an Id.
   RawObject* ReadVMIsolateObject(intptr_t object_id);
 
   // Read an object that was serialized as an Id (singleton in object store,
   // or an object that was already serialized before).
-  RawObject* ReadIndexedObject(intptr_t object_id);
+  RawObject* ReadIndexedObject(intptr_t object_id,
+                               intptr_t patch_object_id,
+                               intptr_t patch_offset);
 
-  // Read an inlined object from the stream.
-  RawObject* ReadInlinedObject(intptr_t object_id);
+  // Add a patch record for the object so that objects whose canonicalization
+  // is deferred can be back patched after they are canonicalized.
+  void AddPatchRecord(intptr_t object_id,
+                      intptr_t patch_object_id,
+                      intptr_t patch_offset);
+
+  // Process all the deferred canonicalization entries and patch all references.
+  void ProcessDeferredCanonicalizations();
 
   // Decode class id from the header field.
   intptr_t LookupInternalClass(intptr_t class_header);
 
-  void ArrayReadFrom(const Array& result, intptr_t len, intptr_t tags);
+  void ArrayReadFrom(intptr_t object_id,
+                     const Array& result,
+                     intptr_t len,
+                     intptr_t tags);
 
   intptr_t NextAvailableObjectId() const;
 
@@ -703,12 +761,12 @@
   bool CheckAndWritePredefinedObject(RawObject* raw);
   void HandleVMIsolateObject(RawObject* raw);
 
-  void WriteObjectRef(RawObject* raw);
   void WriteClassId(RawClass* cls);
   void WriteStaticImplicitClosure(intptr_t object_id,
                                   RawFunction* func,
                                   intptr_t tags);
-  void WriteObjectImpl(RawObject* raw);
+  void WriteObjectImpl(RawObject* raw, bool as_reference);
+  void WriteObjectRef(RawObject* raw);
   void WriteInlinedObject(RawObject* raw);
   void WriteForwardedObjects();
   void ArrayWriteTo(intptr_t object_id,
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 23c687a..2843561 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -120,6 +120,9 @@
                             second->value.as_array.values[i]);
       }
       break;
+    case Dart_CObject_kCapability:
+      EXPECT_EQ(first->value.as_capability.id, second->value.as_capability.id);
+      break;
     default:
       EXPECT(false);
   }
@@ -402,6 +405,38 @@
 }
 
 
+TEST_CASE(SerializeCapability) {
+  StackZone zone(Isolate::Current());
+
+  // Write snapshot with object content.
+  const Capability& capability = Capability::Handle(Capability::New(12345));
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, true);
+  writer.WriteMessage(capability);
+  intptr_t buffer_len = writer.BytesWritten();
+
+  // Read object back from the snapshot.
+  MessageSnapshotReader reader(buffer,
+                               buffer_len,
+                               Isolate::Current(),
+                               zone.GetZone());
+  Capability& obj = Capability::Handle();
+  obj ^= reader.ReadObject();
+
+  EXPECT_STREQ(12345, obj.Id());
+
+  // Read object back from the snapshot into a C structure.
+  ApiNativeScope scope;
+  ApiMessageReader api_reader(buffer, buffer_len, &zone_allocator);
+  Dart_CObject* root = api_reader.ReadMessage();
+  EXPECT_NOTNULL(root);
+  EXPECT_EQ(Dart_CObject_kCapability, root->type);
+  int64_t id = root->value.as_capability.id;
+  EXPECT_EQ(12345, id);
+  CheckEncodeDecodeMessage(root);
+}
+
+
 TEST_CASE(SerializeBigint) {
   StackZone zone(Isolate::Current());
 
@@ -1020,6 +1055,120 @@
 }
 
 
+#if 0
+UNIT_TEST_CASE(CanonicalizationInScriptSnapshots) {
+  const char* kScriptChars =
+      "\n"
+      "import 'dart:mirrors';"
+      "import 'dart:isolate';"
+      "void main() {"
+      "  if (reflectClass(MyException).superclass.reflectedType != "
+      "      IsolateSpawnException) {"
+      "    throw new Exception('Canonicalization failure');"
+      "  }"
+      "  if (reflectClass(IsolateSpawnException).reflectedType != "
+      "      IsolateSpawnException) {"
+      "    throw new Exception('Canonicalization failure');"
+      "  }"
+      "}\n"
+      "class MyException extends IsolateSpawnException {}"
+      "\n";
+
+  Dart_Handle result;
+
+  uint8_t* buffer;
+  intptr_t size;
+  intptr_t vm_isolate_snapshot_size;
+  uint8_t* isolate_snapshot = NULL;
+  intptr_t isolate_snapshot_size;
+  uint8_t* full_snapshot = NULL;
+  uint8_t* script_snapshot = NULL;
+
+  bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly;
+  FLAG_load_deferred_eagerly = true;
+  // Workaround until issue 21620 is fixed.
+  // (https://github.com/dart-lang/sdk/issues/21620)
+  bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep;
+  FLAG_concurrent_sweep = false;
+  {
+    // Start an Isolate, and create a full snapshot of it.
+    TestIsolateScope __test_isolate__;
+    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
+
+    // Write out the script snapshot.
+    result = Dart_CreateSnapshot(NULL,
+                                 &vm_isolate_snapshot_size,
+                                 &isolate_snapshot,
+                                 &isolate_snapshot_size);
+    EXPECT_VALID(result);
+    full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
+    memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
+    Dart_ExitScope();
+  }
+  FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode;
+  FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
+
+  {
+    // Now Create an Isolate using the full snapshot and load the
+    // script  and execute it.
+    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
+    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
+
+    // Create a test library and Load up a test script in it.
+    Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+
+    EXPECT_VALID(lib);
+
+    // Invoke a function which returns an object.
+    result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+    EXPECT_VALID(result);
+    Dart_ExitScope();
+    Dart_ShutdownIsolate();
+  }
+
+  {
+    // Create an Isolate using the full snapshot, load a script and create
+    // a script snapshot of the script.
+    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
+    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
+
+    // Create a test library and Load up a test script in it.
+    TestCase::LoadTestScript(kScriptChars, NULL);
+
+    EXPECT_VALID(Api::CheckAndFinalizePendingClasses(Isolate::Current()));
+
+    // Write out the script snapshot.
+    result = Dart_CreateScriptSnapshot(&buffer, &size);
+    EXPECT_VALID(result);
+    script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
+    memmove(script_snapshot, buffer, size);
+    Dart_ExitScope();
+    Dart_ShutdownIsolate();
+  }
+
+  {
+    // Now Create an Isolate using the full snapshot and load the
+    // script snapshot created above and execute it.
+    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
+    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
+
+    // Load the test library from the snapshot.
+    EXPECT(script_snapshot != NULL);
+    result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
+    EXPECT_VALID(result);
+
+    // Invoke a function which returns an object.
+    result = Dart_Invoke(result, NewString("main"), 0, NULL);
+    EXPECT_VALID(result);
+    Dart_ExitScope();
+    Dart_ShutdownIsolate();
+  }
+  free(script_snapshot);
+  free(full_snapshot);
+}
+#endif
+
+
 static void IterateScripts(const Library& lib) {
   const Array& lib_scripts = Array::Handle(lib.LoadedScripts());
   Script& script = Script::Handle();
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index dd849e5..94ba9d3 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -144,7 +144,7 @@
 class EntryFrame : public StackFrame {
  public:
   bool IsValid() const {
-    return StubCode::InInvocationStubForIsolate(isolate(), pc());
+    return StubCode::InInvocationStub(pc());
   }
   bool IsDartFrame(bool validate = true) const { return false; }
   bool IsStubFrame() const { return false; }
@@ -206,7 +206,7 @@
       }
       const uword pc = *(reinterpret_cast<uword*>(
           sp_ + (kSavedPcSlotFromSp * kWordSize)));
-      return !StubCode::InInvocationStubForIsolate(isolate_, pc);
+      return !StubCode::InInvocationStub(pc);
     }
 
     // Get next non entry/exit frame in the set (assumes a next frame exists).
diff --git a/runtime/vm/store_buffer.cc b/runtime/vm/store_buffer.cc
index a590c28..f4fbad7 100644
--- a/runtime/vm/store_buffer.cc
+++ b/runtime/vm/store_buffer.cc
@@ -78,9 +78,14 @@
     MutexLocker ml(mutex_);
     partial_.Push(block);
   }
-  if (check_threshold) {
+  if (check_threshold && Overflowed()) {
     MutexLocker ml(mutex_);
-    CheckThresholdNonEmpty();
+    Isolate* isolate = Isolate::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);
   }
 }
 
@@ -139,16 +144,9 @@
 }
 
 
-void StoreBuffer::CheckThresholdNonEmpty() {
-  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
-  if (full_.length() + partial_.length() > kMaxNonEmpty) {
-    Isolate* isolate = Isolate::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::kStoreBufferInterrupt);
-  }
+bool StoreBuffer::Overflowed() {
+  MutexLocker ml(mutex_);
+  return (full_.length() + partial_.length()) > kMaxNonEmpty;
 }
 
 
diff --git a/runtime/vm/store_buffer.h b/runtime/vm/store_buffer.h
index b8f36a5..b1bd387 100644
--- a/runtime/vm/store_buffer.h
+++ b/runtime/vm/store_buffer.h
@@ -97,6 +97,9 @@
   // Discards the contents of this store buffer.
   void Reset();
 
+  // Check whether non-empty blocks have exceeded kMaxNonEmpty.
+  bool Overflowed();
+
  private:
   class List {
    public:
@@ -113,10 +116,6 @@
     DISALLOW_COPY_AND_ASSIGN(List);
   };
 
-  // Check if we run over the max number of deduplication sets.
-  // If we did schedule an interrupt.
-  void CheckThresholdNonEmpty();
-
   // If needed, trims the the global cache of empty blocks.
   static void TrimGlobalEmpty();
 
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index ad51097..486531a 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -38,14 +38,6 @@
 }
 
 
-StubCode::~StubCode() {
-#define STUB_CODE_DELETER(name)                                                \
-  delete name##_entry_;
-  STUB_CODE_LIST(STUB_CODE_DELETER);
-#undef STUB_CODE_DELETER
-}
-
-
 #define STUB_CODE_GENERATE(name)                                               \
   code ^= Generate("_stub_"#name, StubCode::Generate##name##Stub);             \
   name##_entry_ = new StubEntry(code);
@@ -58,83 +50,45 @@
 }
 
 
-void StubCode::GenerateStubsFor(Isolate* init) {
-  // Generate all the other stubs.
-  Code& code = Code::Handle();
-  STUB_CODE_LIST(STUB_CODE_GENERATE);
-}
-
 #undef STUB_CODE_GENERATE
 
 
-void StubCode::Init(Isolate* isolate) {
-  StubCode* stubs = new StubCode(isolate);
-  isolate->set_stub_code(stubs);
-  isolate->stub_code()->GenerateStubsFor(isolate);
-}
+void StubCode::Init(Isolate* isolate) { }
 
 
 void StubCode::VisitObjectPointers(ObjectPointerVisitor* visitor) {
-  // The current isolate is needed as part of the macro.
-  Isolate* isolate = Isolate::Current();
-  StubCode* stubs = isolate->stub_code();
-  if (stubs == NULL) return;
-  StubEntry* entry;
-#define STUB_CODE_VISIT_OBJECT_POINTER(name)                                   \
-  entry = stubs->name##_entry();                                               \
-  if (entry != NULL) {                                                         \
-    entry->VisitObjectPointers(visitor);                                       \
-  }
-
-  STUB_CODE_LIST(STUB_CODE_VISIT_OBJECT_POINTER);
-#undef STUB_CODE_VISIT_OBJECT_POINTER
 }
 
 
 bool StubCode::InInvocationStub(uword pc) {
-  return InInvocationStubForIsolate(Isolate::Current(), pc);
-}
-
-
-bool StubCode::InInvocationStubForIsolate(Isolate* isolate, uword pc) {
-  StubCode* stub_code = isolate->stub_code();
-  uword entry = stub_code->InvokeDartCodeEntryPoint();
-  uword size = stub_code->InvokeDartCodeSize();
+  uword entry = StubCode::InvokeDartCode_entry()->EntryPoint();
+  uword size = StubCode::InvokeDartCodeSize();
   return (pc >= entry) && (pc < (entry + size));
 }
 
 
 bool StubCode::InJumpToExceptionHandlerStub(uword pc) {
-  uword entry = StubCode::JumpToExceptionHandlerEntryPoint();
+  uword entry = StubCode::JumpToExceptionHandler_entry()->EntryPoint();
   uword size = StubCode::JumpToExceptionHandlerSize();
   return (pc >= entry) && (pc < (entry + size));
 }
 
 
-RawCode* StubCode::GetAllocateArrayStub() {
-  const Class& array_cls = Class::Handle(isolate_,
-      isolate_->object_store()->array_class());
-  return GetAllocationStubForClass(array_cls);
-}
-
-
 RawCode* StubCode::GetAllocationStubForClass(const Class& cls) {
   Isolate* isolate = Isolate::Current();
   const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
   ASSERT(error.IsNull());
+  if (cls.id() == kArrayCid) {
+    return AllocateArray_entry()->code();
+  }
   Code& stub = Code::Handle(isolate, cls.allocation_stub());
   if (stub.IsNull()) {
     Assembler assembler;
     const char* name = cls.ToCString();
     uword patch_code_offset = 0;
     uword entry_patch_offset = 0;
-    if (cls.id() == kArrayCid) {
-      StubCode::GeneratePatchableAllocateArrayStub(
-          &assembler, &entry_patch_offset, &patch_code_offset);
-    } else {
-      StubCode::GenerateAllocationStubForClass(
-          &assembler, cls, &entry_patch_offset, &patch_code_offset);
-    }
+    StubCode::GenerateAllocationStubForClass(
+        &assembler, cls, &entry_patch_offset, &patch_code_offset);
     stub ^= Code::FinalizeCode(name, &assembler);
     stub.set_owner(cls);
     cls.set_allocation_stub(stub);
@@ -155,17 +109,18 @@
 }
 
 
-uword StubCode::UnoptimizedStaticCallEntryPoint(intptr_t num_args_tested) {
+const StubEntry* StubCode::UnoptimizedStaticCallEntry(
+    intptr_t num_args_tested) {
   switch (num_args_tested) {
     case 0:
-      return ZeroArgsUnoptimizedStaticCallEntryPoint();
+      return ZeroArgsUnoptimizedStaticCall_entry();
     case 1:
-      return OneArgUnoptimizedStaticCallEntryPoint();
+      return OneArgUnoptimizedStaticCall_entry();
     case 2:
-      return TwoArgsUnoptimizedStaticCallEntryPoint();
+      return TwoArgsUnoptimizedStaticCall_entry();
     default:
       UNIMPLEMENTED();
-      return 0;
+      return NULL;
   }
 }
 
@@ -191,22 +146,12 @@
 
 const char* StubCode::NameOfStub(uword entry_point) {
 #define VM_STUB_CODE_TESTER(name)                                              \
-  if ((name##_entry() != NULL) && (entry_point == name##EntryPoint())) {       \
+  if ((name##_entry() != NULL) &&                                              \
+      (entry_point == name##_entry()->EntryPoint())) {                         \
     return ""#name;                                                            \
   }
   VM_STUB_CODE_LIST(VM_STUB_CODE_TESTER);
-
-#define STUB_CODE_TESTER(name)                                                 \
-  if ((isolate->stub_code()->name##_entry() != NULL) &&                        \
-      (entry_point == isolate->stub_code()->name##EntryPoint())) {             \
-    return ""#name;                                                            \
-  }
-  Isolate* isolate = Isolate::Current();
-  if ((isolate != NULL) && (isolate->stub_code() != NULL)) {
-    STUB_CODE_LIST(STUB_CODE_TESTER);
-  }
 #undef VM_STUB_CODE_TESTER
-#undef STUB_CODE_TESTER
   return NULL;
 }
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index b383478..3a5ffc1 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -35,13 +35,14 @@
   V(DebugStepCheck)                                                            \
   V(MegamorphicLookup)                                                         \
   V(FixAllocationStubTarget)                                                   \
-  V(FixAllocateArrayStubTarget)                                                \
   V(Deoptimize)                                                                \
   V(DeoptimizeLazy)                                                            \
   V(UnoptimizedIdenticalWithNumberCheck)                                       \
   V(OptimizedIdenticalWithNumberCheck)                                         \
   V(ICCallBreakpoint)                                                          \
   V(RuntimeCallBreakpoint)                                                     \
+  V(AllocateArray)                                                             \
+  V(AllocateContext)                                                           \
   V(OneArgCheckInlineCache)                                                    \
   V(TwoArgsCheckInlineCache)                                                   \
   V(SmiAddInlineCache)                                                         \
@@ -57,7 +58,7 @@
   V(Subtype1TestCache)                                                         \
   V(Subtype2TestCache)                                                         \
   V(Subtype3TestCache)                                                         \
-  V(AllocateContext)                                                           \
+  V(CallClosureNoSuchMethod)
 
 // Is it permitted for the stubs above to refer to Object::null(), which is
 // allocated in the VM isolate and shared across all isolates.
@@ -65,12 +66,6 @@
 // using Smi 0 instead of Object::null() is slightly more efficient, since a Smi
 // does not require relocation.
 
-// List of stubs created per isolate, these stubs could potentially contain
-// embedded objects and hence cannot be shared across isolates.
-#define STUB_CODE_LIST(V)                                                      \
-  V(CallClosureNoSuchMethod)                                                   \
-
-
 // class StubEntry is used to describe stub methods generated in dart to
 // abstract out common code executed from generated dart code.
 class StubEntry {
@@ -97,17 +92,8 @@
 
 
 // class StubCode is used to maintain the lifecycle of stubs.
-class StubCode {
+class StubCode : public AllStatic {
  public:
-  explicit StubCode(Isolate* isolate)
-    :
-#define STUB_CODE_INITIALIZER(name)                                            \
-        name##_entry_(NULL),
-  STUB_CODE_LIST(STUB_CODE_INITIALIZER)
-        isolate_(isolate) {}
-  ~StubCode();
-
-
   // Generate all stubs which are shared across all isolates, this is done
   // only once and the stub code resides in the vm_isolate heap.
   static void InitOnce();
@@ -122,8 +108,6 @@
   // transitioning into dart code.
   static bool InInvocationStub(uword pc);
 
-  static bool InInvocationStubForIsolate(Isolate* isolate, uword pc);
-
   // Check if the specified pc is in the jump to exception handler stub.
   static bool InJumpToExceptionHandlerStub(uword pc);
 
@@ -132,42 +116,18 @@
 
   // Define the shared stub code accessors.
 #define STUB_CODE_ACCESSOR(name)                                               \
-  static StubEntry* name##_entry() {                                           \
+  static const StubEntry* name##_entry() {                                     \
     return name##_entry_;                                                      \
   }                                                                            \
-  static const ExternalLabel& name##Label() {                                  \
-    return name##_entry()->label();                                            \
-  }                                                                            \
-  static uword name##EntryPoint() {                                            \
-    return name##_entry()->EntryPoint();                                       \
-  }                                                                            \
   static intptr_t name##Size() {                                               \
     return name##_entry()->Size();                                             \
   }
   VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR);
 #undef STUB_CODE_ACCESSOR
 
-  // Define the per-isolate stub code accessors.
-#define STUB_CODE_ACCESSOR(name)                                               \
-  StubEntry* name##_entry() {                                                  \
-    return name##_entry_;                                                      \
-  }                                                                            \
-  const ExternalLabel& name##Label() {                                         \
-    return name##_entry()->label();                                            \
-  }                                                                            \
-  uword name##EntryPoint() {                                                   \
-    return name##_entry()->EntryPoint();                                       \
-  }                                                                            \
-  intptr_t name##Size() {                                                      \
-    return name##_entry()->Size();                                             \
-  }
-  STUB_CODE_LIST(STUB_CODE_ACCESSOR);
-#undef STUB_CODE_ACCESSOR
-
   static RawCode* GetAllocationStubForClass(const Class& cls);
-  RawCode* GetAllocateArrayStub();
 
-  uword UnoptimizedStaticCallEntryPoint(intptr_t num_args_tested);
+  static const StubEntry* UnoptimizedStaticCallEntry(intptr_t num_args_tested);
 
   static const intptr_t kNoInstantiator = 0;
 
@@ -175,8 +135,6 @@
       Assembler*, Register recv, Register cache, Register target);
 
  private:
-  void GenerateStubsFor(Isolate* isolate);
-
   friend class MegamorphicCacheTable;
 
   static const intptr_t kStubCodeSize = 4 * KB;
@@ -184,7 +142,6 @@
 #define STUB_CODE_GENERATE(name)                                               \
   static void Generate##name##Stub(Assembler* assembler);
   VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
-  STUB_CODE_LIST(STUB_CODE_GENERATE);
 #undef STUB_CODE_GENERATE
 
 #define STUB_CODE_ENTRY(name)                                                  \
@@ -192,12 +149,6 @@
   VM_STUB_CODE_LIST(STUB_CODE_ENTRY);
 #undef STUB_CODE_ENTRY
 
-#define STUB_CODE_ENTRY(name)                                                  \
-  StubEntry* name##_entry_;
-  STUB_CODE_LIST(STUB_CODE_ENTRY);
-#undef STUB_CODE_ENTRY
-  Isolate* isolate_;
-
   enum RangeCollectionMode {
     kCollectRanges,
     kIgnoreRanges
@@ -212,8 +163,6 @@
   static void GenerateAllocationStubForClass(
       Assembler* assembler, const Class& cls,
       uword* entry_patch_offset, uword* patch_code_pc_offset);
-  static void GeneratePatchableAllocateArrayStub(Assembler* assembler,
-      uword* entry_patch_offset, uword* patch_code_pc_offset);
   static void GenerateNArgsCheckInlineCacheStub(
       Assembler* assembler,
       intptr_t num_args,
@@ -224,13 +173,6 @@
   static void GenerateUsageCounterIncrement(Assembler* assembler,
                                             Register temp_reg);
   static void GenerateOptimizedUsageCounterIncrement(Assembler* assembler);
-
-  static void GenerateIdenticalWithNumberCheckStub(
-      Assembler* assembler,
-      const Register left,
-      const Register right,
-      const Register temp1 = kNoRegister,
-      const Register temp2 = kNoRegister);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 5d270ce..9459b29 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -358,39 +358,15 @@
 }
 
 
-// Called from array allocate instruction when the allocation stub has been
-// disabled.
-// R1: element type (preserved).
-// R2: length (preserved).
-void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
-  __ EnterStubFrame();
-  // Setup space on stack for return value and preserve length, element type.
-  __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
-  __ PushList((1 << R0) | (1 << R1) | (1 << R2));
-  __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
-  // Get Code object result and restore length, element type.
-  __ PopList((1 << R0) | (1 << R1) | (1 << R2));
-  // Remove the stub frame.
-  __ LeaveStubFrame();
-  // Jump to the dart function.
-  __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
-  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
-  __ bx(R0);
-}
-
-
 // Input parameters:
 //   R2: smi-tagged argument count, may be zero.
 //   FP[kParamEndSlotFromFp + 1]: last argument.
 static void PushArgumentsArray(Assembler* assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
   // Allocate array to store arguments of caller.
   __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
   // R1: null element type for raw Array.
   // R2: smi-tagged argument count, may be zero.
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchLink(&array_label);
+  __ BranchLink(*StubCode::AllocateArray_entry());
   // R0: newly allocated array.
   // R2: smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(R0);  // Array is in R0 and on top of stack.
@@ -628,20 +604,15 @@
 //   R1: array element type (either NULL or an instantiated type).
 //   R2: array length as Smi (must be preserved).
 // The newly allocated object is returned in R0.
-void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler,
-    uword* entry_patch_offset, uword* patch_code_pc_offset) {
-  *entry_patch_offset = assembler->CodeSize();
+void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
-  Isolate* isolate = Isolate::Current();
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   __ MoveRegister(R3, R2);   // Array length.
-  const Class& cls = Class::Handle(isolate->object_store()->array_class());
-  ASSERT(!cls.IsNull());
   // Check that length is a positive Smi.
   __ tst(R3, Operand(kSmiTagMask));
-  if (FLAG_use_slow_path || cls.trace_allocation()) {
+  if (FLAG_use_slow_path) {
     __ b(&slow_case);
   } else {
     __ b(&slow_case, NE);
@@ -655,6 +626,10 @@
   __ CompareImmediate(R3, max_len);
   __ b(&slow_case, GT);
 
+  const intptr_t cid = kArrayCid;
+  __ MaybeTraceAllocation(cid, R4, &slow_case,
+                          /* inline_isolate = */ false);
+
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ LoadImmediate(R9, fixed_size);
   __ add(R9, R9, Operand(R3, LSL, 1));  // R3 is  a Smi.
@@ -662,12 +637,11 @@
   __ bic(R9, R9, Operand(kObjectAlignment - 1));
 
   // R9: Allocation size.
-
-  Heap* heap = isolate->heap();
-  const intptr_t cid = kArrayCid;
   Heap::Space space = Heap::SpaceForAllocation(cid);
-  __ LoadImmediate(R6, heap->TopAddress(space));
-  __ ldr(R0, Address(R6, 0));  // Potential new object start.
+  __ LoadIsolate(R6);
+  __ ldr(R6, Address(R6, Isolate::heap_offset()));
+  // Potential new object start.
+  __ ldr(R0, Address(R6, Heap::TopOffset(space)));
   __ adds(R7, R0, Operand(R9));  // Potential next object start.
   __ b(&slow_case, CS);  // Branch if unsigned overflow.
 
@@ -675,15 +649,14 @@
   // R0: potential new object start.
   // R7: potential next object start.
   // R9: allocation size.
-  __ LoadImmediate(R3, heap->EndAddress(space));
-  __ ldr(R3, Address(R3, 0));
+  __ ldr(R3, Address(R6, Heap::EndOffset(space)));
   __ cmp(R7, Operand(R3));
   __ b(&slow_case, CS);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ LoadAllocationStatsAddress(R3, cid);
-  __ str(R7, Address(R6, 0));
+  __ LoadAllocationStatsAddress(R3, cid, /* inline_isolate = */ false);
+  __ str(R7, Address(R6, Heap::TopOffset(space)));
   __ add(R0, R0, Operand(kHeapObjectTag));
 
   // Initialize the tags.
@@ -749,9 +722,6 @@
   __ mov(R0, Operand(IP));
   __ LeaveStubFrame();
   __ Ret();
-  *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->FixAllocateArrayStubTargetLabel());
 }
 
 
@@ -863,6 +833,7 @@
   }
   // Restore CPU registers.
   __ PopList(kAbiPreservedCpuRegs);
+  __ set_constant_pool_allowed(false);
 
   // Restore the frame pointer and return.
   __ LeaveFrame((1 << FP) | (1 << LR));
@@ -1091,27 +1062,26 @@
     Label slow_case;
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
-    Heap* heap = Isolate::Current()->heap();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
-    __ LoadImmediate(R5, heap->TopAddress(space));
-    __ ldr(R0, Address(R5, 0));
+    __ ldr(R5, Address(THR, Thread::heap_offset()));
+    __ ldr(R0, Address(R5, Heap::TopOffset(space)));
     __ AddImmediate(R1, R0, instance_size);
     // Check if the allocation fits into the remaining space.
     // R0: potential new object start.
     // R1: potential next object start.
-    __ LoadImmediate(IP, heap->EndAddress(space));
-    __ ldr(IP, Address(IP, 0));
+    // R5: heap.
+    __ ldr(IP, Address(R5, Heap::EndOffset(space)));
     __ cmp(R1, Operand(IP));
     if (FLAG_use_slow_path) {
       __ b(&slow_case);
     } else {
       __ b(&slow_case, CS);  // Unsigned higher or equal.
     }
-    __ str(R1, Address(R5, 0));
+    __ str(R1, Address(R5, Heap::TopOffset(space)));
 
     // Load the address of the allocation stats table. We split up the load
     // and the increment so that the dependent load is not too nearby.
-    __ LoadAllocationStatsAddress(R5, cls.id());
+    __ LoadAllocationStatsAddress(R5, cls.id(), /* inline_isolate = */ false);
 
     // R0: new object start.
     // R1: next object start.
@@ -1202,8 +1172,7 @@
   __ LeaveStubFrame();
   __ Ret();
   *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->FixAllocationStubTargetLabel());
+  __ BranchPatchable(*StubCode::FixAllocationStubTarget_entry());
 }
 
 
@@ -1963,11 +1932,10 @@
 // Return Zero condition flag set if equal.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
-                                                    const Register left,
-                                                    const Register right,
-                                                    const Register temp,
-                                                    const Register unused) {
+static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                 const Register left,
+                                                 const Register right,
+                                                 const Register temp) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ tst(left, Operand(kSmiTagMask));
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 007bfe9..b3bd552 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -52,13 +52,13 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   { Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R8, R28, Isolate::vm_tag_offset(), kNoPP);
-    __ CompareImmediate(R8, VMTag::kDartTagId, kNoPP);
+    __ LoadFromOffset(R8, R28, Isolate::vm_tag_offset());
+    __ CompareImmediate(R8, VMTag::kDartTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -66,7 +66,7 @@
 #endif
 
   // Mark that the isolate is executing VM code.
-  __ StoreToOffset(R5, R28, Isolate::vm_tag_offset(), kNoPP);
+  __ StoreToOffset(R5, R28, Isolate::vm_tag_offset());
 
   // Reserve space for arguments and align frame before entering C++ world.
   // NativeArguments are passed in registers.
@@ -91,15 +91,15 @@
   __ add(R2, ZR, Operand(R4, LSL, 3));
   __ add(R2, FP, Operand(R2));  // Compute argv.
   // Set argv in NativeArguments.
-  __ AddImmediate(R2, R2, exitframe_last_param_slot_from_fp * kWordSize, kNoPP);
+  __ AddImmediate(R2, R2, exitframe_last_param_slot_from_fp * kWordSize);
 
     ASSERT(retval_offset == 3 * kWordSize);
-  __ AddImmediate(R3, R2, kWordSize, kNoPP);
+  __ AddImmediate(R3, R2, kWordSize);
 
-  __ StoreToOffset(R0, SP, thread_offset, kNoPP);
-  __ StoreToOffset(R1, SP, argc_tag_offset, kNoPP);
-  __ StoreToOffset(R2, SP, argv_offset, kNoPP);
-  __ StoreToOffset(R3, SP, retval_offset, kNoPP);
+  __ StoreToOffset(R0, SP, thread_offset);
+  __ StoreToOffset(R1, SP, argc_tag_offset);
+  __ StoreToOffset(R2, SP, argv_offset);
+  __ StoreToOffset(R3, SP, retval_offset);
   __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
   // We are entering runtime code, so the C stack pointer must be restored from
@@ -117,11 +117,11 @@
 
   // Retval is next to 1st argument.
   // Mark that the isolate is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId, kNoPP);
-  __ StoreToOffset(R2, R28, Isolate::vm_tag_offset(), kNoPP);
+  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ StoreToOffset(R2, R28, Isolate::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ ret();
@@ -152,13 +152,13 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   { Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R6, R28, Isolate::vm_tag_offset(), kNoPP);
-    __ CompareImmediate(R6, VMTag::kDartTagId, kNoPP);
+    __ LoadFromOffset(R6, R28, Isolate::vm_tag_offset());
+    __ CompareImmediate(R6, VMTag::kDartTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -166,7 +166,7 @@
 #endif
 
   // Mark that the isolate is executing Native code.
-  __ StoreToOffset(R5, R28, Isolate::vm_tag_offset(), kNoPP);
+  __ StoreToOffset(R5, R28, Isolate::vm_tag_offset());
 
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
@@ -190,15 +190,15 @@
 
   // Set retval in NativeArgs.
   ASSERT(retval_offset == 3 * kWordSize);
-  __ AddImmediate(R3, FP, 2 * kWordSize, kNoPP);
+  __ AddImmediate(R3, FP, 2 * kWordSize);
 
   // Passing the structure by value as in runtime calls would require changing
   // Dart API for native functions.
   // For now, space is reserved on the stack and we pass a pointer to it.
-  __ StoreToOffset(R0, SP, thread_offset, kNoPP);
-  __ StoreToOffset(R1, SP, argc_tag_offset, kNoPP);
-  __ StoreToOffset(R2, SP, argv_offset, kNoPP);
-  __ StoreToOffset(R3, SP, retval_offset, kNoPP);
+  __ StoreToOffset(R0, SP, thread_offset);
+  __ StoreToOffset(R1, SP, argc_tag_offset);
+  __ StoreToOffset(R2, SP, argv_offset);
+  __ StoreToOffset(R3, SP, retval_offset);
   __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
   // We are entering runtime code, so the C stack pointer must be restored from
@@ -213,10 +213,10 @@
   uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
   entry = Simulator::RedirectExternalReference(
       entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
-  __ LoadImmediate(R2, entry, kNoPP);
+  __ LoadImmediate(R2, entry);
   __ blr(R2);
 #else
-  __ BranchLink(&NativeEntry::NativeCallWrapperLabel(), kNoPP);
+  __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
 #endif
 
   // Restore SP and CSP.
@@ -224,11 +224,11 @@
   __ mov(CSP, R26);
 
   // Mark that the isolate is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId, kNoPP);
-  __ StoreToOffset(R2, R28, Isolate::vm_tag_offset(), kNoPP);
+  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ StoreToOffset(R2, R28, Isolate::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ ret();
@@ -254,13 +254,13 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   { Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R6, R28, Isolate::vm_tag_offset(), kNoPP);
-    __ CompareImmediate(R6, VMTag::kDartTagId, kNoPP);
+    __ LoadFromOffset(R6, R28, Isolate::vm_tag_offset());
+    __ CompareImmediate(R6, VMTag::kDartTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -268,7 +268,7 @@
 #endif
 
   // Mark that the isolate is executing Native code.
-  __ StoreToOffset(R5, R28, Isolate::vm_tag_offset(), kNoPP);
+  __ StoreToOffset(R5, R28, Isolate::vm_tag_offset());
 
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
@@ -292,15 +292,15 @@
 
   // Set retval in NativeArgs.
   ASSERT(retval_offset == 3 * kWordSize);
-  __ AddImmediate(R3, FP, 2 * kWordSize, kNoPP);
+  __ AddImmediate(R3, FP, 2 * kWordSize);
 
   // Passing the structure by value as in runtime calls would require changing
   // Dart API for native functions.
   // For now, space is reserved on the stack and we pass a pointer to it.
-  __ StoreToOffset(R0, SP, thread_offset, kNoPP);
-  __ StoreToOffset(R1, SP, argc_tag_offset, kNoPP);
-  __ StoreToOffset(R2, SP, argv_offset, kNoPP);
-  __ StoreToOffset(R3, SP, retval_offset, kNoPP);
+  __ StoreToOffset(R0, SP, thread_offset);
+  __ StoreToOffset(R1, SP, argc_tag_offset);
+  __ StoreToOffset(R2, SP, argv_offset);
+  __ StoreToOffset(R3, SP, retval_offset);
   __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
   // We are entering runtime code, so the C stack pointer must be restored from
@@ -317,11 +317,11 @@
   __ mov(CSP, R26);
 
   // Mark that the isolate is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId, kNoPP);
-  __ StoreToOffset(R2, R28, Isolate::vm_tag_offset(), kNoPP);
+  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ StoreToOffset(R2, R28, Isolate::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ ret();
@@ -336,7 +336,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
   __ Push(R4);
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
   __ Pop(R0);
@@ -344,8 +344,8 @@
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
-  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset());
+  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R0);
 }
 
@@ -359,7 +359,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
   __ Push(R4);
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   // Get Code object result and restore arguments descriptor array.
   __ Pop(R0);
@@ -367,8 +367,8 @@
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
-  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset());
+  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R0);
 }
 
@@ -378,39 +378,15 @@
 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   // Get Code object result.
   __ Pop(R0);
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
-  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
-  __ br(R0);
-}
-
-
-// Called from array allocate instruction when the allocation stub has been
-// disabled.
-// R1: element type (preserved).
-// R2: length (preserved).
-void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
-  __ EnterStubFrame();
-  // Setup space on stack for return value and preserve length, element type.
-  __ Push(R1);
-  __ Push(R2);
-  __ PushObject(Object::null_object(), PP);
-  __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
-  // Get Code object result and restore length, element type.
-  __ Pop(R0);
-  __ Pop(R2);
-  __ Pop(R1);
-  // Remove the stub frame.
-  __ LeaveStubFrame();
-  // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
-  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset());
+  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R0);
 }
 
@@ -419,20 +395,17 @@
 //   R2: smi-tagged argument count, may be zero.
 //   FP[kParamEndSlotFromFp + 1]: last argument.
 static void PushArgumentsArray(Assembler* assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
   // Allocate array to store arguments of caller.
-  __ LoadObject(R1, Object::null_object(), PP);
+  __ LoadObject(R1, Object::null_object());
   // R1: null element type for raw Array.
   // R2: smi-tagged argument count, may be zero.
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchLink(&array_label, PP);
+  __ BranchLink(*StubCode::AllocateArray_entry());
   // R0: newly allocated array.
   // R2: smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(R0);  // Array is in R0 and on top of stack.
   __ add(R1, FP, Operand(R2, LSL, 2));
-  __ AddImmediate(R1, R1, kParamEndSlotFromFp * kWordSize, PP);
-  __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag, PP);
+  __ AddImmediate(R1, R1, kParamEndSlotFromFp * kWordSize);
+  __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag);
   // R1: address of first argument on stack.
   // R3: address of first argument in array.
 
@@ -441,9 +414,9 @@
   __ b(&loop_exit, LE);
   __ Bind(&loop);
   __ ldr(R7, Address(R1));
-  __ AddImmediate(R1, R1, -kWordSize, PP);
-  __ AddImmediate(R3, R3, kWordSize, PP);
-  __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1), PP);
+  __ AddImmediate(R1, R1, -kWordSize);
+  __ AddImmediate(R3, R3, kWordSize);
+  __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1));
   __ str(R7, Address(R3, -kWordSize));
   __ b(&loop, GE);
   __ Bind(&loop_exit);
@@ -513,7 +486,7 @@
 
   if (preserve_result) {
     // Restore result into R1 temporarily.
-    __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize, kNoPP);
+    __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize);
   }
 
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -533,7 +506,7 @@
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
   if (preserve_result) {
     // Restore result into R1.
-    __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize, kNoPP);
+    __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize);
   }
   // Code above cannot cause GC.
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -568,7 +541,7 @@
 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
   // Correct return address to point just after the call that is being
   // deoptimized.
-  __ AddImmediate(LR, LR, -CallPattern::kLengthInBytes, kNoPP);
+  __ AddImmediate(LR, LR, -CallPattern::kLengthInBytes);
   GenerateDeoptimizationSequence(assembler, true);  // Preserve R0.
 }
 
@@ -583,15 +556,15 @@
   __ Comment("NoSuchMethodDispatch");
   // When lazily generated invocation dispatchers are disabled, the
   // miss-handler may return null.
-  __ CompareObject(R0, Object::null_object(), PP);
+  __ CompareObject(R0, Object::null_object());
   __ b(call_target_function, NE);
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
-  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize, kNoPP);
-  __ PushObject(Object::null_object(), PP);
+  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
+  __ PushObject(Object::null_object());
   __ Push(R6);
   __ Push(R5);
   __ Push(R4);
@@ -610,9 +583,9 @@
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
-  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize, kNoPP);
+  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
 
   // Preserve IC data and arguments descriptor.
   __ Push(R5);
@@ -622,7 +595,7 @@
   // Push the receiver.
   // Push IC data object.
   // Push arguments descriptor array.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ Push(R6);
   __ Push(R5);
   __ Push(R4);
@@ -644,8 +617,8 @@
   }
 
   // Tail-call to target function.
-  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
-  __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset());
+  __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R2);
 }
 
@@ -657,19 +630,14 @@
 //   R1: array element type (either NULL or an instantiated type).
 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
 // The newly allocated object is returned in R0.
-void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler,
-    uword* entry_patch_offset, uword* patch_code_pc_offset) {
-  *entry_patch_offset = assembler->CodeSize();
+void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
-  Isolate* isolate = Isolate::Current();
-  const Class& cls = Class::Handle(isolate->object_store()->array_class());
-  ASSERT(!cls.IsNull());
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   // Assert that length is a Smi.
   __ tsti(R2, Immediate(kSmiTagMask));
-  if (FLAG_use_slow_path || cls.trace_allocation()) {
+  if (FLAG_use_slow_path) {
     __ b(&slow_case);
   } else {
     __ b(&slow_case, NE);
@@ -677,24 +645,28 @@
   __ cmp(R2, Operand(0));
   __ b(&slow_case, LT);
 
-  Heap* heap = isolate->heap();
+  // Check for maximum allowed length.
+  const intptr_t max_len =
+      reinterpret_cast<intptr_t>(Smi::New(Array::kMaxElements));
+  __ CompareImmediate(R2, max_len);
+  __ b(&slow_case, GT);
+
   const intptr_t cid = kArrayCid;
+  __ MaybeTraceAllocation(kArrayCid, R4, &slow_case,
+                          /* inline_isolate = */ false);
+
   Heap::Space space = Heap::SpaceForAllocation(cid);
-  const uword top_address = heap->TopAddress(space);
-  __ LoadImmediate(R8, top_address, kNoPP);
-  const uword end_address = heap->EndAddress(space);
-  ASSERT(top_address < end_address);
-  const uword top_offset = 0;
-  const uword end_offset = end_address - top_address;
+  __ LoadIsolate(R8);
+  __ ldr(R8, Address(R8, Isolate::heap_offset()));
 
   // Calculate and align allocation size.
   // Load new object start and calculate next object start.
   // R1: array element type.
   // R2: array length as Smi.
-  // R8: points to new space object.
-  __ LoadFromOffset(R0, R8, top_offset, kNoPP);
+  // R8: heap.
+  __ LoadFromOffset(R0, R8, Heap::TopOffset(space));
   intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
-  __ LoadImmediate(R3, fixed_size, kNoPP);
+  __ LoadImmediate(R3, fixed_size);
   __ add(R3, R3, Operand(R2, LSL, 2));  // R2 is Smi.
   ASSERT(kSmiTagShift == 1);
   __ andi(R3, R3, Immediate(~(kObjectAlignment - 1)));
@@ -709,8 +681,8 @@
   // R2: array length as Smi.
   // R3: array size.
   // R7: potential next object start.
-  // R8: points to new space object.
-  __ LoadFromOffset(TMP, R8, end_offset, kNoPP);
+  // R8: heap.
+  __ LoadFromOffset(TMP, R8, Heap::EndOffset(space));
   __ CompareRegisters(R7, TMP);
   __ b(&slow_case, CS);  // Branch if unsigned higher or equal.
 
@@ -719,10 +691,11 @@
   // R0: potential new object start.
   // R3: array size.
   // R7: potential next object start.
-  // R8: Points to new space object.
-  __ StoreToOffset(R7, R8, top_offset, kNoPP);
+  // R8: heap.
+  __ StoreToOffset(R7, R8, Heap::TopOffset(space));
   __ add(R0, R0, Operand(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, R3, kNoPP, space);
+  __ UpdateAllocationStatsWithSize(cid, R3, space,
+                                   /* inline_isolate = */ false);
 
   // R0: new object start as a tagged pointer.
   // R1: array element type.
@@ -732,10 +705,10 @@
 
   // Store the type argument field.
   __ StoreIntoObjectOffsetNoBarrier(
-      R0, Array::type_arguments_offset(), R1, PP);
+      R0, Array::type_arguments_offset(), R1);
 
   // Set the length field.
-  __ StoreIntoObjectOffsetNoBarrier(R0, Array::length_offset(), R2, PP);
+  __ StoreIntoObjectOffsetNoBarrier(R0, Array::length_offset(), R2);
 
   // Calculate the size tag.
   // R0: new object start as a tagged pointer.
@@ -743,32 +716,32 @@
   // R3: array size.
   // R7: new object end address.
   const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
-  __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag, kNoPP);
+  __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag);
   // If no size tag overflow, shift R1 left, else set R1 to zero.
   __ LslImmediate(TMP, R3, shift);
   __ csel(R1, TMP, R1, LS);
   __ csel(R1, ZR, R1, HI);
 
   // Get the class index and insert it into the tags.
-  __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid), kNoPP);
+  __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
   __ orr(R1, R1, Operand(TMP));
-  __ StoreFieldToOffset(R1, R0, Array::tags_offset(), kNoPP);
+  __ StoreFieldToOffset(R1, R0, Array::tags_offset());
 
   // Initialize all array elements to raw_null.
   // R0: new object start as a tagged pointer.
   // R7: new object end address.
   // R2: array length as Smi.
-  __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag);
   // R1: iterator which initially points to the start of the variable
   // data area to be initialized.
-  __ LoadObject(TMP, Object::null_object(), PP);
+  __ LoadObject(TMP, Object::null_object());
   Label loop, done;
   __ Bind(&loop);
   // TODO(cshapiro): StoreIntoObjectNoBarrier
   __ CompareRegisters(R1, R7);
   __ b(&done, CS);
   __ str(TMP, Address(R1));  // Store if unsigned lower.
-  __ AddImmediate(R1, R1, kWordSize, kNoPP);
+  __ AddImmediate(R1, R1, kWordSize);
   __ b(&loop);  // Loop until R1 == R7.
   __ Bind(&done);
 
@@ -785,7 +758,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value.
   // Push array length as Smi and element type.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ Push(R2);
   __ Push(R1);
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
@@ -795,9 +768,6 @@
   __ Pop(R0);
   __ LeaveStubFrame();
   __ ret();
-  *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->FixAllocateArrayStubTargetLabel());
 }
 
 
@@ -834,7 +804,7 @@
   // We now load the pool pointer(PP) as we are about to invoke dart code and we
   // could potentially invoke some intrinsic functions which need the PP to be
   // set up.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != R3) {
@@ -844,41 +814,41 @@
   __ LoadIsolate(R5);
 
   // Save the current VMTag on the stack.
-  __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset(), PP);
+  __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset());
   __ Push(R4);
 
   // Mark that the isolate is executing Dart code.
-  __ LoadImmediate(R6, VMTag::kDartTagId, PP);
-  __ StoreToOffset(R6, R5, Isolate::vm_tag_offset(), PP);
+  __ LoadImmediate(R6, VMTag::kDartTagId);
+  __ StoreToOffset(R6, R5, Isolate::vm_tag_offset());
 
   // Save top resource and top exit frame info. Use R6 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(R6, THR, Thread::top_resource_offset(), PP);
-  __ StoreToOffset(ZR, THR, Thread::top_resource_offset(), PP);
+  __ LoadFromOffset(R6, THR, Thread::top_resource_offset());
+  __ StoreToOffset(ZR, THR, Thread::top_resource_offset());
   __ Push(R6);
-  __ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset(), PP);
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), PP);
+  __ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
   // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
   ASSERT(kExitLinkSlotFromEntryFp == -21);
   __ Push(R6);
 
   // Load arguments descriptor array into R4, which is passed to Dart code.
-  __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle, PP);
+  __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle);
 
   // Load number of arguments into S5.
-  __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset(), PP);
+  __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset());
   __ SmiUntag(R5);
 
   // Compute address of 'arguments array' data area into R2.
-  __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle, PP);
-  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, PP);
+  __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle);
+  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag);
 
   // Set up arguments for the Dart call.
   Label push_arguments;
   Label done_push_arguments;
   __ cmp(R5, Operand(0));
   __ b(&done_push_arguments, EQ);  // check if there are arguments.
-  __ LoadImmediate(R1, 0, PP);
+  __ LoadImmediate(R1, 0);
   __ Bind(&push_arguments);
   __ ldr(R3, Address(R2));
   __ Push(R3);
@@ -893,23 +863,23 @@
   __ Comment("InvokeDartCodeStub return");
 
   // Restore constant pool pointer after return.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
 
   // Get rid of arguments pushed on the stack.
-  __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize, PP);
+  __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
 
   __ LoadIsolate(R28);
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure. Uses R6 as a temporary register for this.
   __ Pop(R6);
-  __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset(), PP);
+  __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset());
   __ Pop(R6);
-  __ StoreToOffset(R6, THR, Thread::top_resource_offset(), PP);
+  __ StoreToOffset(R6, THR, Thread::top_resource_offset());
 
   // Restore the current VMTag from the stack.
   __ Pop(R4);
-  __ StoreToOffset(R4, R28, Isolate::vm_tag_offset(), PP);
+  __ StoreToOffset(R4, R28, Isolate::vm_tag_offset());
 
   // Restore the bottom 64-bits of callee-saved V registers.
   for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
@@ -926,6 +896,7 @@
     // using it as the stack pointer.
     __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
   }
+  __ set_constant_pool_allowed(false);
 
   // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
@@ -945,7 +916,7 @@
     // First compute the rounded instance size.
     // R1: number of context variables.
     intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1;
-    __ LoadImmediate(R2, fixed_size, kNoPP);
+    __ LoadImmediate(R2, fixed_size);
     __ add(R2, R2, Operand(R1, LSL, 3));
     ASSERT(kSmiTagShift == 1);
     __ andi(R2, R2, Immediate(~(kObjectAlignment - 1)));
@@ -982,7 +953,7 @@
     // R5: heap.
     __ str(R3, Address(R5, Heap::TopOffset(space)));
     __ add(R0, R0, Operand(kHeapObjectTag));
-    __ UpdateAllocationStatsWithSize(cid, R2, kNoPP, space,
+    __ UpdateAllocationStatsWithSize(cid, R2, space,
                                      /* inline_isolate = */ false);
 
     // Calculate the size tag.
@@ -990,7 +961,7 @@
     // R1: number of context variables.
     // R2: object size.
     const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP);
+    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
     // If no size tag overflow, shift R2 left, else set R2 to zero.
     __ LslImmediate(TMP, R2, shift);
     __ csel(R2, TMP, R2, LS);
@@ -998,20 +969,20 @@
 
     // Get the class index and insert it into the tags.
     // R2: size and bit tags.
-    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid), kNoPP);
+    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
     __ orr(R2, R2, Operand(TMP));
-    __ StoreFieldToOffset(R2, R0, Context::tags_offset(), kNoPP);
+    __ StoreFieldToOffset(R2, R0, Context::tags_offset());
 
     // Setup up number of context variables field.
     // R0: new object.
     // R1: number of context variables as integer value (not object).
-    __ StoreFieldToOffset(R1, R0, Context::num_variables_offset(), kNoPP);
+    __ StoreFieldToOffset(R1, R0, Context::num_variables_offset());
 
     // Setup the parent field.
     // R0: new object.
     // R1: number of context variables.
-    __ LoadObject(R2, Object::null_object(), PP);
-    __ StoreFieldToOffset(R2, R0, Context::parent_offset(), kNoPP);
+    __ LoadObject(R2, Object::null_object());
+    __ StoreFieldToOffset(R2, R0, Context::parent_offset());
 
     // Initialize the context variables.
     // R0: new object.
@@ -1019,7 +990,7 @@
     // R2: raw null.
     Label loop, done;
     __ AddImmediate(
-        R3, R0, Context::variable_offset(0) - kHeapObjectTag, kNoPP);
+        R3, R0, Context::variable_offset(0) - kHeapObjectTag);
     __ Bind(&loop);
     __ subs(R1, R1, Operand(1));
     __ b(&done, MI);
@@ -1038,7 +1009,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ SmiTag(R1);
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ Push(R1);
   __ CallRuntime(kAllocateContextRuntimeEntry, 1);  // Allocate context.
   __ Drop(1);  // Pop number of context variables argument.
@@ -1059,7 +1030,7 @@
   Label add_to_buffer;
   // Check whether this object has already been remembered. Skip adding to the
   // store buffer if the object is in the store buffer already.
-  __ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kNoPP);
+  __ LoadFieldFromOffset(TMP, R0, Object::tags_offset());
   __ tsti(TMP, Immediate(1 << RawObject::kRememberedBit));
   __ b(&add_to_buffer, EQ);
   __ ret();
@@ -1071,24 +1042,22 @@
   __ Push(R3);
 
   __ orri(R2, TMP, Immediate(1 << RawObject::kRememberedBit));
-  __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP);
+  __ StoreFieldToOffset(R2, R0, Object::tags_offset());
 
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
-  __ LoadFromOffset(R1, THR, Thread::store_buffer_block_offset(), kNoPP);
-  __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(),
-                    kNoPP, kUnsignedWord);
+  __ LoadFromOffset(R1, THR, Thread::store_buffer_block_offset());
+  __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord);
   __ add(R3, R1, Operand(R2, LSL, 3));
-  __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset(), kNoPP);
+  __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset());
 
   // Increment top_ and check for overflow.
   // R2: top_.
   // R1: StoreBufferBlock.
   Label L;
   __ add(R2, R2, Operand(1));
-  __ StoreToOffset(R2, R1, StoreBufferBlock::top_offset(),
-                   kNoPP, kUnsignedWord);
-  __ CompareImmediate(R2, StoreBufferBlock::kSize, kNoPP);
+  __ StoreToOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord);
+  __ CompareImmediate(R2, StoreBufferBlock::kSize);
   // Restore values.
   __ Pop(R3);
   __ Pop(R2);
@@ -1137,24 +1106,23 @@
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
     // R1: instantiated type arguments (if is_cls_parameterized).
-    Heap* heap = Isolate::Current()->heap();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
-    __ LoadImmediate(R5, heap->TopAddress(space), kNoPP);
-    __ ldr(R2, Address(R5));
-    __ AddImmediate(R3, R2, instance_size, kNoPP);
+    __ ldr(R5, Address(THR, Thread::heap_offset()));
+    __ ldr(R2, Address(R5, Heap::TopOffset(space)));
+    __ AddImmediate(R3, R2, instance_size);
     // Check if the allocation fits into the remaining space.
     // R2: potential new object start.
     // R3: potential next object start.
-    __ LoadImmediate(TMP, heap->EndAddress(space), kNoPP);
-    __ ldr(TMP, Address(TMP));
+    // R5: heap.
+    __ ldr(TMP, Address(R5, Heap::EndOffset(space)));
     __ CompareRegisters(R3, TMP);
     if (FLAG_use_slow_path) {
       __ b(&slow_case);
     } else {
       __ b(&slow_case, CS);  // Unsigned higher or equal.
     }
-    __ str(R3, Address(R5));
-    __ UpdateAllocationStats(cls.id(), kNoPP, space);
+    __ str(R3, Address(R5, Heap::TopOffset(space)));
+    __ UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
 
     // R2: new object start.
     // R3: next object start.
@@ -1164,11 +1132,11 @@
     tags = RawObject::SizeTag::update(instance_size, tags);
     ASSERT(cls.id() != kIllegalCid);
     tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    __ LoadImmediate(R0, tags, kNoPP);
-    __ StoreToOffset(R0, R2, Instance::tags_offset(), kNoPP);
+    __ LoadImmediate(R0, tags);
+    __ StoreToOffset(R0, R2, Instance::tags_offset());
 
     // Initialize the remaining words of the object.
-    __ LoadObject(R0, Object::null_object(), PP);
+    __ LoadObject(R0, Object::null_object());
 
     // R0: raw null.
     // R2: new object start.
@@ -1181,10 +1149,10 @@
       for (intptr_t current_offset = Instance::NextFieldOffset();
            current_offset < instance_size;
            current_offset += kWordSize) {
-        __ StoreToOffset(R0, R2, current_offset, kNoPP);
+        __ StoreToOffset(R0, R2, current_offset);
       }
     } else {
-      __ AddImmediate(R4, R2, Instance::NextFieldOffset(), kNoPP);
+      __ AddImmediate(R4, R2, Instance::NextFieldOffset());
       // Loop until the whole object is initialized.
       // R0: raw null.
       // R2: new object.
@@ -1197,14 +1165,14 @@
       __ CompareRegisters(R4, R3);
       __ b(&done, CS);
       __ str(R0, Address(R4));
-      __ AddImmediate(R4, R4, kWordSize, kNoPP);
+      __ AddImmediate(R4, R4, kWordSize);
       __ b(&init_loop);
       __ Bind(&done);
     }
     if (is_cls_parameterized) {
       // R1: new object type arguments.
       // Set the type arguments in the new object.
-      __ StoreToOffset(R1, R2, cls.type_arguments_field_offset(), kNoPP);
+      __ StoreToOffset(R1, R2, cls.type_arguments_field_offset());
     }
     // Done allocating and initializing the instance.
     // R2: new object still missing its heap tag.
@@ -1220,14 +1188,14 @@
   // calling into the runtime.
   __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
-  __ PushObject(cls, PP);  // Push class of object to be allocated.
+  __ PushObject(Object::null_object());
+  __ PushObject(cls);  // Push class of object to be allocated.
   if (is_cls_parameterized) {
     // Push type arguments.
     __ Push(R1);
   } else {
     // Push null type arguments.
-    __ PushObject(Object::null_object(), PP);
+    __ PushObject(Object::null_object());
   }
   __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
   __ Drop(2);  // Pop arguments.
@@ -1237,8 +1205,7 @@
   __ LeaveStubFrame();
   __ ret();
   *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->FixAllocationStubTargetLabel());
+  __ BranchPatchable(*StubCode::FixAllocationStubTarget_entry());
 }
 
 
@@ -1253,14 +1220,14 @@
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
-  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize, kNoPP);
+  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
 
   // Push space for the return value.
   // Push the receiver.
   // Push arguments descriptor array.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ Push(R6);
   __ Push(R4);
 
@@ -1294,10 +1261,10 @@
     __ LeaveStubFrame();
   }
   __ LoadFieldFromOffset(
-      R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord);
+      R7, func_reg, Function::usage_counter_offset(), kWord);
   __ add(R7, R7, Operand(1));
   __ StoreFieldToOffset(
-      R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord);
+      R7, func_reg, Function::usage_counter_offset(), kWord);
 }
 
 
@@ -1309,12 +1276,12 @@
     Register func_reg = temp_reg;
     ASSERT(temp_reg == R6);
     __ Comment("Increment function counter");
-    __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset(), kNoPP);
+    __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset());
     __ LoadFieldFromOffset(
-        R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord);
-    __ AddImmediate(R7, R7, 1, kNoPP);
+        R7, func_reg, Function::usage_counter_offset(), kWord);
+    __ AddImmediate(R7, R7, 1);
     __ StoreFieldToOffset(
-        R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord);
+        R7, func_reg, Function::usage_counter_offset(), kWord);
   }
 }
 
@@ -1351,8 +1318,8 @@
     }
     case Token::kEQ: {
       __ CompareRegisters(R0, R1);
-      __ LoadObject(R0, Bool::True(), PP);
-      __ LoadObject(R1, Bool::False(), PP);
+      __ LoadObject(R0, Bool::True());
+      __ LoadObject(R1, Bool::False());
       __ csel(R0, R1, R0, NE);
       break;
     }
@@ -1366,19 +1333,19 @@
   }
 
   // R5: IC data object (preserved).
-  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
+  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
   // R6: ic_data_array with check entries: classes and target functions.
-  __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
   // R6: points directly to the first ic data array element.
 #if defined(DEBUG)
   // Check that first entry is for Smi/Smi.
   Label error, ok;
   const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid));
   __ ldr(R1, Address(R6, 0));
-  __ CompareImmediate(R1, imm_smi_cid, kNoPP);
+  __ CompareImmediate(R1, imm_smi_cid);
   __ b(&error, NE);
   __ ldr(R1, Address(R6, kWordSize));
-  __ CompareImmediate(R1, imm_smi_cid, kNoPP);
+  __ CompareImmediate(R1, imm_smi_cid);
   __ b(&ok, EQ);
   __ Bind(&error);
   __ Stop("Incorrect IC data");
@@ -1387,11 +1354,11 @@
   if (FLAG_optimization_counter_threshold >= 0) {
     const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
     // Update counter.
-    __ LoadFromOffset(R1, R6, count_offset, kNoPP);
+    __ LoadFromOffset(R1, R6, count_offset);
     __ adds(R1, R1, Operand(Smi::RawValue(1)));
-    __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP);
+    __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue));
     __ csel(R1, R2, R1, VS);  // Overflow.
-    __ StoreToOffset(R1, R6, count_offset, kNoPP);
+    __ StoreToOffset(R1, R6, count_offset);
   }
 
   __ ret();
@@ -1421,10 +1388,10 @@
     // Check that the IC data array has NumArgsTested() == num_args.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
     __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
-                      kNoPP, kUnsignedWord);
+                      kUnsignedWord);
     ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
     __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask()));
-    __ CompareImmediate(R6, num_args, kNoPP);
+    __ CompareImmediate(R6, num_args);
     __ b(&ok, EQ);
     __ Stop("Incorrect stub for IC data");
     __ Bind(&ok);
@@ -1436,7 +1403,7 @@
     __ Comment("Check single stepping");
     __ LoadIsolate(R6);
     __ LoadFromOffset(
-        R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
+        R6, R6, Isolate::single_step_offset(), kUnsignedByte);
     __ CompareRegisters(R6, ZR);
     __ b(&stepping, NE);
     __ Bind(&done_stepping);
@@ -1465,18 +1432,18 @@
 
   __ Comment("Extract ICData initial values and receiver cid");
   // Load arguments descriptor into R4.
-  __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP);
+  __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
   // Loop that checks if there is an IC data match.
   Label loop, update, test, found;
   // R5: IC data object (preserved).
-  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
+  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
   // R6: ic_data_array with check entries: classes and target functions.
-  __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
   // R6: points directly to the first ic data array element.
 
   // Get the receiver's class ID (first read number of arguments from
   // arguments descriptor array and then access the receiver from the stack).
-  __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), kNoPP);
+  __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
   __ SmiUntag(R7);  // Untag so we can use the LSL 3 addressing mode.
   __ sub(R7, R7, Operand(1));
 
@@ -1494,12 +1461,12 @@
   for (int i = 0; i < num_args; i++) {
     if (i > 0) {
       // If not the first, load the next argument's class ID.
-      __ AddImmediate(R0, R7, -i, kNoPP);
+      __ AddImmediate(R0, R7, -i);
       // R0 <- [SP + (R0 << 3)]
       __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled));
       __ LoadTaggedClassIdMayBeSmi(R0, R0);
       // R0: next argument class ID (smi).
-      __ LoadFromOffset(R1, R6, i * kWordSize, kNoPP);
+      __ LoadFromOffset(R1, R6, i * kWordSize);
       // R1: next class ID to check (smi).
     }
     __ CompareRegisters(R0, R1);  // Class id match?
@@ -1518,11 +1485,11 @@
   }
 
   const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
-  __ AddImmediate(R6, R6, entry_size, kNoPP);  // Next entry.
+  __ AddImmediate(R6, R6, entry_size);  // Next entry.
   __ ldr(R1, Address(R6));  // Next class ID.
 
   __ Bind(&test);
-  __ CompareImmediate(R1, Smi::RawValue(kIllegalCid), kNoPP);  // Done?
+  __ CompareImmediate(R1, Smi::RawValue(kIllegalCid));  // Done?
   __ b(&loop, NE);
 
   __ Comment("IC miss");
@@ -1539,10 +1506,10 @@
   __ Push(R4);  // Preserve arguments descriptor array.
   __ Push(R5);  // Preserve IC Data.
   // Setup space on stack for the result (target code object).
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
-    __ LoadFromOffset(TMP, R7, -i * kWordSize, kNoPP);
+    __ LoadFromOffset(TMP, R7, -i * kWordSize);
     __ Push(TMP);
   }
   // Pass IC data object.
@@ -1568,23 +1535,23 @@
   // R6: pointer to an IC data check group.
   const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
   const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
-  __ LoadFromOffset(R0, R6, target_offset, kNoPP);
+  __ LoadFromOffset(R0, R6, target_offset);
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Update counter.
-    __ LoadFromOffset(R1, R6, count_offset, kNoPP);
+    __ LoadFromOffset(R1, R6, count_offset);
     __ adds(R1, R1, Operand(Smi::RawValue(1)));
-    __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP);
+    __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue));
     __ csel(R1, R2, R1, VS);  // Overflow.
-    __ StoreToOffset(R1, R6, count_offset, kNoPP);
+    __ StoreToOffset(R1, R6, count_offset);
   }
 
   __ Comment("Call target");
   __ Bind(&call_target_function);
   // R0: target function.
-  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset());
   __ AddImmediate(
-      R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+      R2, R2, Instructions::HeaderSize() - kHeapObjectTag);
   if (range_collection_mode == kCollectRanges) {
     __ ldr(R1, Address(SP, 0 * kWordSize));
     if (num_args == 2) {
@@ -1715,10 +1682,10 @@
     // Check that the IC data array has NumArgsTested() == 0.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
     __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
-                      kNoPP, kUnsignedWord);
+                      kUnsignedWord);
     ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
     __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask()));
-    __ CompareImmediate(R6, 0, kNoPP);
+    __ CompareImmediate(R6, 0);
     __ b(&ok, EQ);
     __ Stop("Incorrect IC data for unoptimized static call");
     __ Bind(&ok);
@@ -1730,40 +1697,40 @@
     if (FLAG_support_debugger) {
     __ LoadIsolate(R6);
     __ LoadFromOffset(
-        R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
-    __ CompareImmediate(R6, 0, kNoPP);
+        R6, R6, Isolate::single_step_offset(), kUnsignedByte);
+    __ CompareImmediate(R6, 0);
     __ b(&stepping, NE);
     __ Bind(&done_stepping);
   }
 
   // R5: IC data object (preserved).
-  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
+  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
   // R6: ic_data_array with entries: target functions and count.
-  __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
+  __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
   // R6: points directly to the first ic data array element.
   const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
   const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Increment count for this call.
-    __ LoadFromOffset(R1, R6, count_offset, kNoPP);
+    __ LoadFromOffset(R1, R6, count_offset);
     __ adds(R1, R1, Operand(Smi::RawValue(1)));
-    __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP);
+    __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue));
     __ csel(R1, R2, R1, VS);  // Overflow.
-    __ StoreToOffset(R1, R6, count_offset, kNoPP);
+    __ StoreToOffset(R1, R6, count_offset);
   }
 
   // Load arguments descriptor into R4.
-  __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP);
+  __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
 
   // Get function and call it, if possible.
-  __ LoadFromOffset(R0, R6, target_offset, kNoPP);
-  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
+  __ LoadFromOffset(R0, R6, target_offset);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset());
 
   // R0: function.
   // R2: target instructons.
   __ AddImmediate(
-      R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+      R2, R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R2);
 
   if (FLAG_support_debugger) {
@@ -1810,9 +1777,9 @@
   __ Pop(R5);  // Restore IC Data.
   __ LeaveStubFrame();
 
-  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset());
   __ AddImmediate(
-      R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
+      R2, R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ br(R2);
 }
 
@@ -1821,7 +1788,7 @@
 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R5);
-  __ PushObject(Object::null_object(), PP);  // Space for result.
+  __ PushObject(Object::null_object());  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ Pop(R0);
   __ Pop(R5);
@@ -1832,7 +1799,7 @@
 
 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ PushObject(Object::null_object(), PP);  // Space for result.
+  __ PushObject(Object::null_object());  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ Pop(R0);
   __ LeaveStubFrame();
@@ -1846,8 +1813,8 @@
   Label stepping, done_stepping;
   __ LoadIsolate(R1);
   __ LoadFromOffset(
-      R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
-  __ CompareImmediate(R1, 0, kNoPP);
+      R1, R1, Isolate::single_step_offset(), kUnsignedByte);
+  __ CompareImmediate(R1, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
 
@@ -1871,26 +1838,26 @@
   ASSERT((1 <= n) && (n <= 3));
   if (n > 1) {
     // Get instance type arguments.
-    __ LoadClass(R3, R0, kNoPP);
+    __ LoadClass(R3, R0);
     // Compute instance type arguments into R4.
     Label has_no_type_arguments;
-    __ LoadObject(R4, Object::null_object(), PP);
+    __ LoadObject(R4, Object::null_object());
     __ LoadFieldFromOffset(R5, R3,
-        Class::type_arguments_field_offset_in_words_offset(), kNoPP, kWord);
-    __ CompareImmediate(R5, Class::kNoTypeArguments, kNoPP);
+        Class::type_arguments_field_offset_in_words_offset(), kWord);
+    __ CompareImmediate(R5, Class::kNoTypeArguments);
     __ b(&has_no_type_arguments, EQ);
     __ add(R5, R0, Operand(R5, LSL, 3));
-    __ LoadFieldFromOffset(R4, R5, 0, kNoPP);
+    __ LoadFieldFromOffset(R4, R5, 0);
     __ Bind(&has_no_type_arguments);
   }
-  __ LoadClassId(R3, R0, kNoPP);
+  __ LoadClassId(R3, R0);
   // R0: instance.
   // R1: instantiator type arguments or NULL.
   // R2: SubtypeTestCache.
   // R3: instance class id.
   // R4: instance type arguments (null if none), used only if n > 1.
-  __ LoadFieldFromOffset(R2, R2, SubtypeTestCache::cache_offset(), kNoPP);
-  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, kNoPP);
+  __ LoadFieldFromOffset(R2, R2, SubtypeTestCache::cache_offset());
+  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag);
 
   Label loop, found, not_found, next_iteration;
   // R2: entry start.
@@ -1899,8 +1866,8 @@
   __ SmiTag(R3);
   __ Bind(&loop);
   __ LoadFromOffset(
-      R5, R2, kWordSize * SubtypeTestCache::kInstanceClassId, kNoPP);
-  __ CompareObject(R5, Object::null_object(), PP);
+      R5, R2, kWordSize * SubtypeTestCache::kInstanceClassId);
+  __ CompareObject(R5, Object::null_object());
   __ b(&not_found, EQ);
   __ CompareRegisters(R5, R3);
   if (n == 1) {
@@ -1908,29 +1875,29 @@
   } else {
     __ b(&next_iteration, NE);
     __ LoadFromOffset(
-        R5, R2, kWordSize * SubtypeTestCache::kInstanceTypeArguments, kNoPP);
+        R5, R2, kWordSize * SubtypeTestCache::kInstanceTypeArguments);
     __ CompareRegisters(R5, R4);
     if (n == 2) {
       __ b(&found, EQ);
     } else {
       __ b(&next_iteration, NE);
       __ LoadFromOffset(R5, R2,
-          kWordSize * SubtypeTestCache::kInstantiatorTypeArguments, kNoPP);
+          kWordSize * SubtypeTestCache::kInstantiatorTypeArguments);
       __ CompareRegisters(R5, R1);
       __ b(&found, EQ);
     }
   }
   __ Bind(&next_iteration);
   __ AddImmediate(
-      R2, R2, kWordSize * SubtypeTestCache::kTestEntryLength, kNoPP);
+      R2, R2, kWordSize * SubtypeTestCache::kTestEntryLength);
   __ b(&loop);
   // Fall through to not found.
   __ Bind(&not_found);
-  __ LoadObject(R1, Object::null_object(), PP);
+  __ LoadObject(R1, Object::null_object());
   __ ret();
 
   __ Bind(&found);
-  __ LoadFromOffset(R1, R2, kWordSize * SubtypeTestCache::kTestResult, kNoPP);
+  __ LoadFromOffset(R1, R2, kWordSize * SubtypeTestCache::kTestResult);
   __ ret();
 }
 
@@ -1994,10 +1961,10 @@
   __ mov(THR, R5);
   __ LoadIsolate(R5);
   // Set the tag.
-  __ LoadImmediate(R2, VMTag::kDartTagId, kNoPP);
-  __ StoreToOffset(R2, R5, Isolate::vm_tag_offset(), kNoPP);
+  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ StoreToOffset(R2, R5, Isolate::vm_tag_offset());
   // Clear top exit frame.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
   __ ret();  // Jump to the exception handler code.
 }
 
@@ -2009,14 +1976,14 @@
   __ EnterStubFrame();
   __ Push(R4);
   // Setup space on stack for the return value.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ Push(R6);
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
   __ Pop(R0);  // Discard argument.
   __ Pop(R0);  // Get Code object
   __ Pop(R4);  // Restore argument descriptor.
-  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
-  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, PP);
+  __ LoadFieldFromOffset(R0, R0, Code::instructions_offset());
+  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
   __ LeaveStubFrame();
   __ br(R0);
   __ brk(0);
@@ -2035,11 +2002,9 @@
 // Return Zero condition flag set if equal.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
-                                                    const Register left,
-                                                    const Register right,
-                                                    const Register unused1,
-                                                    const Register unused2) {
+static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                 const Register left,
+                                                 const Register right) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ tsti(left, Immediate(kSmiTagMask));
@@ -2048,35 +2013,35 @@
   __ b(&reference_compare, EQ);
 
   // Value compare for two doubles.
-  __ CompareClassId(left, kDoubleCid, kNoPP);
+  __ CompareClassId(left, kDoubleCid);
   __ b(&check_mint, NE);
-  __ CompareClassId(right, kDoubleCid, kNoPP);
+  __ CompareClassId(right, kDoubleCid);
   __ b(&done, NE);
 
   // Double values bitwise compare.
-  __ LoadFieldFromOffset(left, left, Double::value_offset(), kNoPP);
-  __ LoadFieldFromOffset(right, right, Double::value_offset(), kNoPP);
+  __ LoadFieldFromOffset(left, left, Double::value_offset());
+  __ LoadFieldFromOffset(right, right, Double::value_offset());
   __ CompareRegisters(left, right);
   __ b(&done);
 
   __ Bind(&check_mint);
-  __ CompareClassId(left, kMintCid, kNoPP);
+  __ CompareClassId(left, kMintCid);
   __ b(&check_bigint, NE);
-  __ CompareClassId(right, kMintCid, kNoPP);
+  __ CompareClassId(right, kMintCid);
   __ b(&done, NE);
-  __ LoadFieldFromOffset(left, left, Mint::value_offset(), kNoPP);
-  __ LoadFieldFromOffset(right, right, Mint::value_offset(), kNoPP);
+  __ LoadFieldFromOffset(left, left, Mint::value_offset());
+  __ LoadFieldFromOffset(right, right, Mint::value_offset());
   __ b(&done);
 
   __ Bind(&check_bigint);
-  __ CompareClassId(left, kBigintCid, kNoPP);
+  __ CompareClassId(left, kBigintCid);
   __ b(&reference_compare, NE);
-  __ CompareClassId(right, kBigintCid, kNoPP);
+  __ CompareClassId(right, kBigintCid);
   __ b(&done, NE);
   __ EnterStubFrame();
   __ ReserveAlignedFrameSpace(2 * kWordSize);
-  __ StoreToOffset(left, SP, 0 * kWordSize, kNoPP);
-  __ StoreToOffset(right, SP, 1 * kWordSize, kNoPP);
+  __ StoreToOffset(left, SP, 0 * kWordSize);
+  __ StoreToOffset(right, SP, 1 * kWordSize);
   __ CallRuntime(kBigintCompareRuntimeEntry, 2);
   // Result in R0, 0 means equal.
   __ LeaveStubFrame();
@@ -2100,17 +2065,16 @@
   Label stepping, done_stepping;
   if (FLAG_support_debugger) {
     __ LoadIsolate(R1);
-    __ LoadFromOffset(
-        R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
-    __ CompareImmediate(R1, 0, kNoPP);
+    __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte);
+    __ CompareImmediate(R1, 0);
     __ b(&stepping, NE);
     __ Bind(&done_stepping);
   }
 
   const Register left = R1;
   const Register right = R0;
-  __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP);
-  __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP);
+  __ LoadFromOffset(left, SP, 1 * kWordSize);
+  __ LoadFromOffset(right, SP, 0 * kWordSize);
   GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ ret();
 
@@ -2131,12 +2095,11 @@
 // Return Zero condition flag set if equal.
 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
-  const Register temp = R2;
   const Register left = R1;
   const Register right = R0;
-  __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP);
-  __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP);
-  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
+  __ LoadFromOffset(left, SP, 1 * kWordSize);
+  __ LoadFromOffset(right, SP, 0 * kWordSize);
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ ret();
 }
 
@@ -2146,8 +2109,8 @@
   ASSERT((cache != R0) && (cache != R2));
   __ LoadTaggedClassIdMayBeSmi(R0, receiver);
   // R0: class ID of the receiver (smi).
-  __ LoadFieldFromOffset(R2, cache, MegamorphicCache::buckets_offset(), PP);
-  __ LoadFieldFromOffset(R1, cache, MegamorphicCache::mask_offset(), PP);
+  __ LoadFieldFromOffset(R2, cache, MegamorphicCache::buckets_offset());
+  __ LoadFieldFromOffset(R1, cache, MegamorphicCache::mask_offset());
   // R2: cache buckets array.
   // R1: mask.
   __ mov(R3, R0);
@@ -2162,7 +2125,7 @@
   const intptr_t base = Array::data_offset();
   // R3 is smi tagged, but table entries are 16 bytes, so LSL 3.
   __ add(TMP, R2, Operand(R3, LSL, 3));
-  __ LoadFieldFromOffset(R4, TMP, base, PP);
+  __ LoadFieldFromOffset(R4, TMP, base);
 
   ASSERT(kIllegalCid == 0);
   __ tst(R4, Operand(R4));
@@ -2176,11 +2139,11 @@
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
   __ add(TMP, R2, Operand(R3, LSL, 3));
-  __ LoadFieldFromOffset(R0, TMP, base + kWordSize, PP);
-  __ LoadFieldFromOffset(R1, R0, Function::instructions_offset(), PP);
+  __ LoadFieldFromOffset(R0, TMP, base + kWordSize);
+  __ LoadFieldFromOffset(R1, R0, Function::instructions_offset());
   // TODO(srdjan): Evaluate performance impact of moving the instruction below
   // to the call site, instead of having it here.
-  __ AddImmediate(target, R1, Instructions::HeaderSize() - kHeapObjectTag, PP);
+  __ AddImmediate(target, R1, Instructions::HeaderSize() - kHeapObjectTag);
 }
 
 
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index 94e40ab..142a824 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -45,9 +45,9 @@
   const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
   const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
   __ EnterDartFrame(0);
-  __ PushObject(Object::null_object(), PP);  // Push Null obj for return value.
-  __ PushObject(smi1, PP);  // Push argument 1 smi1.
-  __ PushObject(smi2, PP);  // Push argument 2 smi2.
+  __ PushObject(Object::null_object());  // Push Null obj for return value.
+  __ PushObject(smi1);  // Push argument 1 smi1.
+  __ PushObject(smi2);  // Push argument 2 smi2.
   ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
   __ CallRuntime(kTestSmiSubRuntimeEntry, argc);  // Call SmiSub runtime func.
   __ add(SP, SP, Operand(argc * kWordSize));
@@ -82,8 +82,8 @@
   const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
   __ EnterDartFrame(0);
   __ ReserveAlignedFrameSpace(0);
-  __ LoadObject(R0, smi1, PP);  // Set up argument 1 smi1.
-  __ LoadObject(R1, smi2, PP);  // Set up argument 2 smi2.
+  __ LoadObject(R0, smi1);  // Set up argument 1 smi1.
+  __ LoadObject(R1, smi2);  // Set up argument 2 smi2.
   __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2);  // Call SmiAdd runtime func.
   __ LeaveDartFrame();
   __ ret();  // Return value is in R0.
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 32505f3..3b21fb7 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -321,43 +321,16 @@
 }
 
 
-// Called from array allocate instruction when the allocation stub has been
-// disabled.
-// EDX: length (preserved).
-// ECX: element type (preserved).
-void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ EnterStubFrame();
-  __ pushl(EDX);       // Preserve length.
-  __ pushl(ECX);       // Preserve element type.
-  __ pushl(raw_null);  // Setup space on stack for return value.
-  __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
-  __ popl(EAX);  // Get Code object.
-  __ popl(ECX);  // Restore element type.
-  __ popl(EDX);  // Restore length.
-  __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
-  __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
-  __ LeaveFrame();
-  __ jmp(EAX);
-  __ int3();
-}
-
-
 // Input parameters:
 //   EDX: smi-tagged argument count, may be zero.
 //   EBP[kParamEndSlotFromFp + 1]: last argument.
 // Uses EAX, EBX, ECX, EDX, EDI.
 static void PushArgumentsArray(Assembler* assembler) {
+  // Allocate array to store arguments of caller.
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  StubCode* stub_code = Isolate::Current()->stub_code();
-
-  // Allocate array to store arguments of caller.
   __ movl(ECX, raw_null);  // Null element type for raw Array.
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ call(&array_label);
+  __ Call(*StubCode::AllocateArray_entry());
   __ SmiUntag(EDX);
   // EAX: newly allocated array.
   // EDX: length of the array (was preserved by the stub).
@@ -582,23 +555,17 @@
 //   ECX : array element type (either NULL or an instantiated type).
 // Uses EAX, EBX, ECX, EDI  as temporary registers.
 // The newly allocated object is returned in EAX.
-void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler,
-    uword* entry_patch_offset, uword* patch_code_pc_offset) {
-  *entry_patch_offset = assembler->CodeSize();
+void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
-
-  Isolate* isolate = Isolate::Current();
-  const Class& cls = Class::Handle(isolate->object_store()->array_class());
-  ASSERT(!cls.IsNull());
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   // Assert that length is a Smi.
   __ testl(EDX, Immediate(kSmiTagMask));
 
-  if (FLAG_use_slow_path || cls.trace_allocation()) {
+  if (FLAG_use_slow_path) {
     __ jmp(&slow_case);
   } else {
     __ j(NOT_ZERO, &slow_case);
@@ -612,48 +579,53 @@
   __ cmpl(EDX, max_len);
   __ j(GREATER, &slow_case);
 
+  __ MaybeTraceAllocation(kArrayCid,
+                          EAX,
+                          &slow_case,
+                          /* near_jump = */ false,
+                          /* inline_isolate = */ false);
+
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
-  __ leal(EDI, Address(EDX, TIMES_2, fixed_size));  // EDX is Smi.
+  __ leal(EBX, Address(EDX, TIMES_2, fixed_size));  // EDX is Smi.
   ASSERT(kSmiTagShift == 1);
-  __ andl(EDI, Immediate(-kObjectAlignment));
+  __ andl(EBX, Immediate(-kObjectAlignment));
 
   // ECX: array element type.
   // EDX: array length as Smi.
-  // EDI: allocation size.
+  // EBX: allocation size.
 
-  Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = Heap::SpaceForAllocation(cid);
-  __ movl(EAX, Address::Absolute(heap->TopAddress(space)));
-  __ movl(EBX, EAX);
-
-  // EDI: allocation size.
-  __ addl(EBX, EDI);
+  __ movl(EDI, Address(THR, Thread::heap_offset()));
+  __ movl(EAX, Address(EDI, Heap::TopOffset(space)));
+  __ addl(EBX, EAX);
   __ j(CARRY, &slow_case);
 
   // Check if the allocation fits into the remaining space.
   // EAX: potential new object start.
   // EBX: potential next object start.
-  // EDI: allocation size.
+  // EDI: heap.
   // ECX: array element type.
   // EDX: array length as Smi).
-  __ cmpl(EBX, Address::Absolute(heap->EndAddress(space)));
+  __ cmpl(EBX, Address(EDI, Heap::EndOffset(space)));
   __ j(ABOVE_EQUAL, &slow_case);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movl(Address::Absolute(heap->TopAddress(space)), EBX);
+  __ movl(Address(EDI, Heap::TopOffset(space)), EBX);
+  __ subl(EBX, EAX);
   __ addl(EAX, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, EDI, kNoRegister, space);
+  __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space,
+                                   /* inline_isolate = */ false);
 
   // Initialize the tags.
   // EAX: new object start as a tagged pointer.
-  // EBX: new object end address.
-  // EDI: allocation size.
+  // EBX: allocation size.
   // ECX: array element type.
   // EDX: array length as Smi.
   {
     Label size_tag_overflow, done;
+    __ movl(EDI, EBX);
     __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
     __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
@@ -668,7 +640,7 @@
     __ movl(FieldAddress(EAX, Array::tags_offset()), EDI);  // Tags.
   }
   // EAX: new object start as a tagged pointer.
-  // EBX: new object end address.
+  // EBX: allocation size.
   // ECX: array element type.
   // EDX: Array length as Smi (preserved).
   // Store the type argument field.
@@ -683,11 +655,12 @@
 
   // Initialize all array elements to raw_null.
   // EAX: new object start as a tagged pointer.
-  // EBX: new object end address.
+  // EBX: allocation size.
   // EDI: iterator which initially points to the start of the variable
   // data area to be initialized.
   // ECX: array element type.
   // EDX: array length as Smi.
+  __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0));
   __ leal(EDI, FieldAddress(EAX, sizeof(RawArray)));
   Label done;
   Label init_loop;
@@ -716,11 +689,6 @@
   __ popl(EAX);  // Pop return value from return slot.
   __ LeaveFrame();
   __ ret();
-  // Emit function patching code. This will be swapped with the first 5 bytes
-  // at entry point.
-  *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ jmp(&stub_code->FixAllocateArrayStubTargetLabel());
 }
 
 
@@ -851,8 +819,7 @@
     // EDX: number of context variables.
     const intptr_t cid = kContextCid;
     Heap::Space space = Heap::SpaceForAllocation(cid);
-    __ LoadIsolate(ECX);
-    __ movl(ECX, Address(ECX, Isolate::heap_offset()));
+    __ movl(ECX, Address(THR, Thread::heap_offset()));
     __ movl(EAX, Address(ECX, Heap::TopOffset(space)));
     __ addl(EBX, EAX);
     // Check if the allocation fits into the remaining space.
@@ -877,9 +844,9 @@
     // EBX: next object start.
     // EDX: number of context variables.
     __ movl(Address(ECX, Heap::TopOffset(space)), EBX);
-    __ addl(EAX, Immediate(kHeapObjectTag));
     // EBX: Size of allocation in bytes.
     __ subl(EBX, EAX);
+    __ addl(EAX, Immediate(kHeapObjectTag));
     // Generate isolate-independent code to allow sharing between isolates.
     __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space,
                                      /* inline_isolate = */ false);
@@ -1066,21 +1033,23 @@
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
     // EDX: instantiated type arguments (if is_cls_parameterized).
-    Heap* heap = Isolate::Current()->heap();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
-    __ movl(EAX, Address::Absolute(heap->TopAddress(space)));
+    __ movl(EDI, Address(THR, Thread::heap_offset()));
+    __ movl(EAX, Address(EDI, Heap::TopOffset(space)));
     __ leal(EBX, Address(EAX, instance_size));
     // Check if the allocation fits into the remaining space.
     // EAX: potential new object start.
     // EBX: potential next object start.
-    __ cmpl(EBX, Address::Absolute(heap->EndAddress(space)));
+    // EDI: heap.
+    __ cmpl(EBX, Address(EDI, Heap::EndOffset(space)));
     if (FLAG_use_slow_path) {
       __ jmp(&slow_case);
     } else {
       __ j(ABOVE_EQUAL, &slow_case);
     }
-    __ movl(Address::Absolute(heap->TopAddress(space)), EBX);
-    __ UpdateAllocationStats(cls.id(), ECX, space);
+    __ movl(Address(EDI, Heap::TopOffset(space)), EBX);
+    __ UpdateAllocationStats(cls.id(), ECX, space,
+                             /* inline_isolate = */ false);
 
     // EAX: new object start (untagged).
     // EBX: next object start.
@@ -1164,8 +1133,7 @@
   // Emit function patching code. This will be swapped with the first 5 bytes
   // at entry point.
   *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ jmp(&stub_code->FixAllocationStubTargetLabel());
+  __ Jmp(*StubCode::FixAllocationStubTarget_entry());
 }
 
 
@@ -1967,11 +1935,10 @@
 // Return ZF set.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
-                                                    const Register left,
-                                                    const Register right,
-                                                    const Register temp,
-                                                    const Register unused) {
+static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                 const Register left,
+                                                 const Register right,
+                                                 const Register temp) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ testl(left, Immediate(kSmiTagMask));
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index b605c5b..1f7e244 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -386,48 +386,16 @@
 }
 
 
-// Called from array allocate instruction when the allocation stub has been
-// disabled.
-// A0: element type (preserved).
-// A1: length (preserved).
-void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
-  __ Comment("FixAllocationStubTarget");
-  __ EnterStubFrame();
-  // Setup space on stack for return value.
-  __ addiu(SP, SP, Immediate(-3 * kWordSize));
-  __ sw(A0, Address(SP, 2 * kWordSize));
-  __ sw(A1, Address(SP, 1 * kWordSize));
-  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
-  __ sw(TMP, Address(SP, 0 * kWordSize));
-  __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
-  // Get Code object result.
-  __ lw(T0, Address(SP, 0 * kWordSize));
-  __ lw(A1, Address(SP, 1 * kWordSize));
-  __ lw(A0, Address(SP, 2 * kWordSize));
-  __ addiu(SP, SP, Immediate(3 * kWordSize));
-
-  // Jump to the dart function.
-  __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
-  __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag);
-
-  // Remove the stub frame.
-  __ LeaveStubFrameAndReturn(T0);
-}
-
-
 // Input parameters:
 //   A1: Smi-tagged argument count, may be zero.
 //   FP[kParamEndSlotFromFp + 1]: Last argument.
 static void PushArgumentsArray(Assembler* assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
   __ Comment("PushArgumentsArray");
   // Allocate array to store arguments of caller.
   __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null()));
   // A0: Null element type for raw Array.
   // A1: Smi-tagged argument count, may be zero.
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ BranchLink(&array_label);
+  __ BranchLink(*StubCode::AllocateArray_entry());
   __ Comment("PushArgumentsArray return");
   // V0: newly allocated array.
   // A1: Smi-tagged argument count, may be zero (was preserved by the stub).
@@ -688,15 +656,9 @@
 //   A0: array element type (either NULL or an instantiated type).
 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved.
 // The newly allocated object is returned in V0.
-void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler,
-    uword* entry_patch_offset, uword* patch_code_pc_offset) {
+void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
   __ Comment("AllocateArrayStub");
-  *entry_patch_offset = assembler->CodeSize();
   Label slow_case;
-  Isolate* isolate = Isolate::Current();
-  const Class& cls = Class::Handle(isolate->object_store()->array_class());
-  ASSERT(!cls.IsNull());
-
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
@@ -704,7 +666,7 @@
 
   // Check that length is a positive Smi.
   __ andi(CMPRES1, T3, Immediate(kSmiTagMask));
-  if (FLAG_use_slow_path || cls.trace_allocation()) {
+  if (FLAG_use_slow_path) {
     __ b(&slow_case);
   } else {
     __ bne(CMPRES1, ZR, &slow_case);
@@ -716,6 +678,10 @@
       reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements));
   __ BranchUnsignedGreater(T3, Immediate(max_len), &slow_case);
 
+  const intptr_t cid = kArrayCid;
+  __ MaybeTraceAllocation(kArrayCid, T4, &slow_case,
+                          /* inline_isolate = */ false);
+
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ LoadImmediate(T2, fixed_size);
   __ sll(T3, T3, 1);  // T3 is  a Smi.
@@ -726,11 +692,11 @@
 
   // T2: Allocation size.
 
-  Heap* heap = isolate->heap();
-  const intptr_t cid = kArrayCid;
   Heap::Space space = Heap::SpaceForAllocation(cid);
-  __ LoadImmediate(T3, heap->TopAddress(space));
-  __ lw(T0, Address(T3, 0));  // Potential new object start.
+  __ LoadIsolate(T3);
+  __ lw(T3, Address(T3, Isolate::heap_offset()));
+  // Potential new object start.
+  __ lw(T0, Address(T3, Heap::TopOffset(space)));
 
   __ addu(T1, T0, T2);  // Potential next object start.
   __ BranchUnsignedLess(T1, T0, &slow_case);  // Branch on unsigned overflow.
@@ -739,15 +705,17 @@
   // T0: potential new object start.
   // T1: potential next object start.
   // T2: allocation size.
-  __ LoadImmediate(T4, heap->EndAddress(space));
-  __ lw(T4, Address(T4, 0));
+  // T3: heap.
+  __ lw(T4, Address(T3, Heap::EndOffset(space)));
   __ BranchUnsignedGreaterEqual(T1, T4, &slow_case);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ sw(T1, Address(T3, 0));
+  // T3: heap.
+  __ sw(T1, Address(T3, Heap::TopOffset(space)));
   __ addiu(T0, T0, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, T2, T4, space);
+  __ UpdateAllocationStatsWithSize(cid, T2, T4, space,
+                                   /* inline_isolate = */ false);
 
   // Initialize the tags.
   // T0: new object start as a tagged pointer.
@@ -827,9 +795,6 @@
   __ addiu(SP, SP, Immediate(3 * kWordSize));
 
   __ LeaveStubFrameAndReturn();
-  *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->FixAllocateArrayStubTargetLabel());
 }
 
 
@@ -1192,17 +1157,16 @@
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
     // T1: instantiated type arguments (if is_cls_parameterized).
-    Heap* heap = Isolate::Current()->heap();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
-    __ LoadImmediate(T5, heap->TopAddress(space));
-    __ lw(T2, Address(T5));
+    __ lw(T5, Address(THR, Thread::heap_offset()));
+    __ lw(T2, Address(T5, Heap::TopOffset(space)));
     __ LoadImmediate(T4, instance_size);
     __ addu(T3, T2, T4);
     // Check if the allocation fits into the remaining space.
     // T2: potential new object start.
     // T3: potential next object start.
-    __ LoadImmediate(TMP, heap->EndAddress(space));
-    __ lw(CMPRES1, Address(TMP));
+    // T5: heap.
+    __ lw(CMPRES1, Address(T5, Heap::EndOffset(space)));
     if (FLAG_use_slow_path) {
       __ b(&slow_case);
     } else {
@@ -1210,8 +1174,8 @@
     }
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
-    __ sw(T3, Address(T5));
-    __ UpdateAllocationStats(cls.id(), T5, space);
+    __ sw(T3, Address(T5, Heap::TopOffset(space)));
+    __ UpdateAllocationStats(cls.id(), T5, space, /* inline_isolate = */ false);
 
     // T2: new object start.
     // T3: next object start.
@@ -1295,8 +1259,7 @@
   // Restore the frame pointer and return.
   __ LeaveStubFrameAndReturn(RA);
   *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ BranchPatchable(&stub_code->FixAllocationStubTargetLabel());
+  __ BranchPatchable(*StubCode::FixAllocationStubTarget_entry());
 }
 
 
@@ -2138,11 +2101,11 @@
 // Returns: CMPRES1 is zero if equal, non-zero otherwise.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
-                                                    const Register left,
-                                                    const Register right,
-                                                    const Register temp1,
-                                                    const Register temp2) {
+static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                 const Register left,
+                                                 const Register right,
+                                                 const Register temp1,
+                                                 const Register temp2) {
   __ Comment("IdenticalWithNumberCheckStub");
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index eaf3e41..cdbcabb 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -276,7 +276,7 @@
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
   __ popq(RAX);  // Get Code object result.
   __ popq(R10);  // Restore arguments descriptor array.
@@ -296,7 +296,7 @@
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   __ popq(RAX);  // Get Code object.
   __ popq(R10);  // Restore arguments descriptor array.
@@ -313,7 +313,7 @@
 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   __ popq(RAX);  // Get Code object.
   __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
@@ -324,40 +324,14 @@
 }
 
 
-// Called from array allocate instruction when the allocation stub has been
-// disabled.
-// R10: length (preserved).
-// RBX: element type (preserved).
-void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
-  __ EnterStubFrame();
-  __ pushq(R10);       // Preserve length.
-  __ pushq(RBX);       // Preserve element type.
-  // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
-  __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
-  __ popq(RAX);  // Get Code object.
-  __ popq(RBX);   // Restore element type.
-  __ popq(R10);   // Restore length.
-  __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
-  __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
-  __ LeaveStubFrame();
-  __ jmp(RAX);
-  __ int3();
-}
-
-
 // Input parameters:
 //   R10: smi-tagged argument count, may be zero.
 //   RBP[kParamEndSlotFromFp + 1]: last argument.
 static void PushArgumentsArray(Assembler* assembler) {
-  StubCode* stub_code = Isolate::Current()->stub_code();
-
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   // Allocate array to store arguments of caller.
   __ movq(RBX, R12);  // Null element type for raw Array.
-  const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
-  const ExternalLabel array_label(array_stub.EntryPoint());
-  __ call(&array_label);
+  __ Call(*StubCode::AllocateArray_entry());
   __ SmiUntag(R10);
   // RAX: newly allocated array.
   // R10: length of the array (was preserved by the stub).
@@ -572,7 +546,7 @@
   __ pushq(R10);
 
   // Space for the result of the runtime call.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ pushq(RAX);  // Receiver.
   __ pushq(RBX);  // IC data.
   __ pushq(R10);  // Arguments descriptor.
@@ -604,23 +578,15 @@
 //   RBX : array element type (either NULL or an instantiated type).
 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved.
 // The newly allocated object is returned in RAX.
-void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler,
-    uword* entry_patch_offset, uword* patch_code_pc_offset) {
-  // Must load pool pointer before being able to patch.
-  Register new_pp = R13;
-  __ LoadPoolPointer(new_pp);
-  *entry_patch_offset = assembler->CodeSize();
+void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
-  Isolate* isolate = Isolate::Current();
-  const Class& cls = Class::Handle(isolate->object_store()->array_class());
-  ASSERT(!cls.IsNull());
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   __ movq(RDI, R10);  // Array Length.
   // Check that length is a positive Smi.
   __ testq(RDI, Immediate(kSmiTagMask));
-  if (FLAG_use_slow_path || cls.trace_allocation()) {
+  if (FLAG_use_slow_path) {
     __ jmp(&slow_case);
   } else {
     __ j(NOT_ZERO, &slow_case);
@@ -632,16 +598,22 @@
       Immediate(reinterpret_cast<int64_t>(Smi::New(Array::kMaxElements)));
   __ cmpq(RDI, max_len);
   __ j(GREATER, &slow_case);
+
+  // Check for allocation tracing.
+  __ MaybeTraceAllocation(kArrayCid,
+                          &slow_case,
+                          /* near_jump = */ false,
+                          /* inline_isolate = */ false);
+
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ leaq(RDI, Address(RDI, TIMES_4, fixed_size));  // RDI is a Smi.
   ASSERT(kSmiTagShift == 1);
   __ andq(RDI, Immediate(-kObjectAlignment));
 
-  Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = Heap::SpaceForAllocation(cid);
-  __ movq(RAX, Immediate(heap->TopAddress(space)));
-  __ movq(RAX, Address(RAX, 0));
+  __ movq(R13, Address(THR, Thread::heap_offset()));
+  __ movq(RAX, Address(R13, Heap::TopOffset(space)));
 
   // RDI: allocation size.
   __ movq(RCX, RAX);
@@ -652,16 +624,16 @@
   // RAX: potential new object start.
   // RCX: potential next object start.
   // RDI: allocation size.
-  __ movq(R13, Immediate(heap->EndAddress(space)));
-  __ cmpq(RCX, Address(R13, 0));
+  // R13: heap.
+  __ cmpq(RCX, Address(R13, Heap::EndOffset(space)));
   __ j(ABOVE_EQUAL, &slow_case);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movq(R13, Immediate(heap->TopAddress(space)));
-  __ movq(Address(R13, 0), RCX);
+  __ movq(Address(R13, Heap::TopOffset(space)), RCX);
   __ addq(RAX, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, RDI, space);
+  __ UpdateAllocationStatsWithSize(cid, RDI, space,
+                                   /* inline_isolate = */ false);
   // Initialize the tags.
   // RAX: new object start as a tagged pointer.
   // RDI: allocation size.
@@ -697,7 +669,7 @@
   // RCX: new object end address.
   // RDI: iterator which initially points to the start of the variable
   // data area to be initialized.
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray)));
   Label done;
   Label init_loop;
@@ -723,7 +695,7 @@
   // calling into the runtime.
   __ EnterStubFrame();
   // Setup space on stack for return value.
-  __ PushObject(Object::null_object(), PP);
+  __ PushObject(Object::null_object());
   __ pushq(R10);  // Array length as Smi.
   __ pushq(RBX);  // Element type.
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
@@ -732,9 +704,6 @@
   __ popq(RAX);  // Pop return value from return slot.
   __ LeaveStubFrame();
   __ ret();
-  *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ JmpPatchable(&stub_code->FixAllocateArrayStubTargetLabel(), new_pp);
 }
 
 
@@ -770,7 +739,7 @@
   // We now load the pool pointer(PP) as we are about to invoke dart code and we
   // could potentially invoke some intrinsic functions which need the PP to be
   // set up.
-  __ LoadPoolPointer(PP);
+  __ LoadPoolPointer();
 
   // If any additional (or fewer) values are pushed, the offsets in
   // kExitLinkSlotFromEntryFp will need to be changed.
@@ -864,6 +833,7 @@
   // Restore C++ ABI callee-saved registers.
   __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters,
                   CallingConventions::kCalleeSaveXmmRegisters);
+  __ set_constant_pool_allowed(false);
 
   // Restore the frame pointer.
   __ LeaveFrame();
@@ -878,7 +848,7 @@
 // Output:
 // RAX: new allocated RawContext object.
 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   if (FLAG_inline_alloc) {
     Label slow_case;
     // First compute the rounded instance size.
@@ -891,8 +861,7 @@
     // R10: number of context variables.
     const intptr_t cid = kContextCid;
     Heap::Space space = Heap::SpaceForAllocation(cid);
-    __ LoadIsolate(RCX);
-    __ movq(RCX, Address(RCX, Isolate::heap_offset()));
+    __ movq(RCX, Address(THR, Thread::heap_offset()));
     __ movq(RAX, Address(RCX, Heap::TopOffset(space)));
     __ addq(R13, RAX);
     // Check if the allocation fits into the remaining space.
@@ -914,9 +883,9 @@
     // R10: number of context variables.
     // RCX: heap.
     __ movq(Address(RCX, Heap::TopOffset(space)), R13);
-    __ addq(RAX, Immediate(kHeapObjectTag));
     // R13: Size of allocation in bytes.
     __ subq(R13, RAX);
+    __ addq(RAX, Immediate(kHeapObjectTag));
     // Generate isolate-independent code to allow sharing between isolates.
     __ UpdateAllocationStatsWithSize(cid, R13, space,
                                      /* inline_isolate */ false);
@@ -1091,7 +1060,7 @@
   const int kInlineInstanceSize = 12;  // In words.
   const intptr_t instance_size = cls.instance_size();
   ASSERT(instance_size > 0);
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   if (is_cls_parameterized) {
     __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
     // RDX: instantiated type arguments.
@@ -1102,24 +1071,22 @@
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
     // RDX: instantiated type arguments (if is_cls_parameterized).
-    Heap* heap = Isolate::Current()->heap();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
-    __ movq(RCX, Immediate(heap->TopAddress(space)));
-    __ movq(RAX, Address(RCX, 0));
+    __ movq(RCX, Address(THR, Thread::heap_offset()));
+    __ movq(RAX, Address(RCX, Heap::TopOffset(space)));
     __ leaq(RBX, Address(RAX, instance_size));
     // Check if the allocation fits into the remaining space.
     // RAX: potential new object start.
     // RBX: potential next object start.
-    // RCX: heap top address.
-    __ movq(R13, Immediate(heap->EndAddress(space)));
-    __ cmpq(RBX, Address(R13, 0));
+    // RCX: heap.
+    __ cmpq(RBX, Address(RCX, Heap::EndOffset(space)));
     if (FLAG_use_slow_path) {
       __ jmp(&slow_case);
     } else {
       __ j(ABOVE_EQUAL, &slow_case);
     }
-    __ movq(Address(RCX, 0), RBX);
-    __ UpdateAllocationStats(cls.id(), space);
+    __ movq(Address(RCX, Heap::TopOffset(space)), RBX);
+    __ UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
 
     // RAX: new object start (untagged).
     // RBX: next object start.
@@ -1187,7 +1154,7 @@
   // Create a stub frame.
   __ EnterStubFrame();  // Uses PP to access class object.
   __ pushq(R12);  // Setup space on stack for return value.
-  __ PushObject(cls, PP);  // Push class of object to be allocated.
+  __ PushObject(cls);  // Push class of object to be allocated.
   if (is_cls_parameterized) {
     __ pushq(RDX);  // Push type arguments of object to be allocated.
   } else {
@@ -1202,8 +1169,7 @@
   __ LeaveStubFrame();
   __ ret();
   *patch_code_pc_offset = assembler->CodeSize();
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  __ JmpPatchable(&stub_code->FixAllocationStubTargetLabel(), new_pp);
+  __ JmpPatchable(*StubCode::FixAllocationStubTarget_entry(), new_pp);
 }
 
 
@@ -1221,7 +1187,7 @@
   __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
   __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize));
 
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   __ pushq(R12);  // Setup space on stack for result from noSuchMethod.
   __ pushq(RAX);  // Receiver.
   __ pushq(R10);  // Arguments descriptor array.
@@ -1308,10 +1274,10 @@
       Label done, is_true;
       __ cmpq(RAX, RCX);
       __ j(EQUAL, &is_true, Assembler::kNearJump);
-      __ LoadObject(RAX, Bool::False(), PP);
+      __ LoadObject(RAX, Bool::False());
       __ jmp(&done, Assembler::kNearJump);
       __ Bind(&is_true);
-      __ LoadObject(RAX, Bool::True(), PP);
+      __ LoadObject(RAX, Bool::True());
       __ Bind(&done);
       break;
     }
@@ -1479,7 +1445,7 @@
   __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
 
   __ Comment("IC miss");
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   // Compute address of arguments (first read number of arguments from
   // arguments descriptor array and then compute address on the stack).
   __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
@@ -1797,7 +1763,7 @@
   __ pushq(RBX);
   // Room for result. Debugger stub returns address of the
   // unpatched runtime stub.
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   __ pushq(R12);  // Room for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popq(RAX);  // Address of original.
@@ -1812,7 +1778,7 @@
   __ EnterStubFrame();
   // Room for result. Debugger stub returns address of the
   // unpatched runtime stub.
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   __ pushq(R12);  // Room for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popq(RAX);  // Address of original.
@@ -1852,9 +1818,9 @@
   const intptr_t kInstanceOffsetInBytes = 2 * kWordSize;
   const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
   __ movq(RAX, Address(RSP, kInstanceOffsetInBytes));
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   if (n > 1) {
-    __ LoadClass(R10, RAX, kNoRegister);
+    __ LoadClass(R10, RAX);
     // Compute instance type arguments into R13.
     Label has_no_type_arguments;
     __ movq(R13, R12);
@@ -2003,7 +1969,7 @@
 // R10: argument descriptor (preserved).
 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
-  __ LoadObject(R12, Object::null_object(), PP);
+  __ LoadObject(R12, Object::null_object());
   __ pushq(R10);
   __ pushq(R12);  // Setup space on stack for return value.
   __ pushq(RDI);
@@ -2031,11 +1997,9 @@
 // Return ZF set.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
-                                                    const Register left,
-                                                    const Register right,
-                                                    const Register unused1,
-                                                    const Register unused2) {
+static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                 const Register left,
+                                                 const Register right) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ testq(left, Immediate(kSmiTagMask));
@@ -2151,7 +2115,7 @@
   __ jmp(&loop);
 
   __ Bind(&update);
-  __ AddImmediate(RCX, Immediate(Smi::RawValue(1)), PP);
+  __ AddImmediate(RCX, Immediate(Smi::RawValue(1)));
   __ Bind(&loop);
   __ andq(RCX, RBX);
   const intptr_t base = Array::data_offset();
@@ -2174,7 +2138,7 @@
   // TODO(srdjan): Evaluate performance impact of moving the instruction below
   // to the call site, instead of having it here.
   __ AddImmediate(
-      target, Immediate(Instructions::HeaderSize() - kHeapObjectTag), PP);
+      target, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
 }
 
 
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index c91ae77..4f67eed 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -45,12 +45,12 @@
   const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
   const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
   __ EnterStubFrame();
-  __ PushObject(Object::null_object(), PP);  // Push Null obj for return value.
-  __ PushObject(smi1, PP);  // Push argument 1 smi1.
-  __ PushObject(smi2, PP);  // Push argument 2 smi2.
+  __ PushObject(Object::null_object());  // Push Null obj for return value.
+  __ PushObject(smi1);  // Push argument 1 smi1.
+  __ PushObject(smi2);  // Push argument 2 smi2.
   ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
   __ CallRuntime(kTestSmiSubRuntimeEntry, argc);  // Call SmiSub runtime func.
-  __ AddImmediate(RSP, Immediate(argc * kWordSize), PP);
+  __ AddImmediate(RSP, Immediate(argc * kWordSize));
   __ popq(RAX);  // Pop return value from return slot.
   __ LeaveStubFrame();
   __ ret();
@@ -82,8 +82,8 @@
   const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
   __ enter(Immediate(0));
   __ ReserveAlignedFrameSpace(0);
-  __ LoadObject(CallingConventions::kArg1Reg, smi1, PP);
-  __ LoadObject(CallingConventions::kArg2Reg, smi2, PP);
+  __ LoadObject(CallingConventions::kArg1Reg, smi1);
+  __ LoadObject(CallingConventions::kArg2Reg, smi2);
   __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2);  // Call SmiAdd runtime func.
   __ leave();
   __ ret();  // Return value is in RAX.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index ee8a711..2cdaf9e 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -389,6 +389,7 @@
   V(last, "last")                                                              \
   V(removeLast, "removeLast")                                                  \
   V(add, "add")                                                                \
+  V(ConstructorClosurePrefix, "new#")                                          \
 
 
 // Contains a list of frequently used strings in a canonicalized form. This
@@ -503,6 +504,9 @@
   static const String& At() {
     return *(symbol_handles_[kNullCharId + '@']);
   }
+  static const String& HashMark() {
+    return *(symbol_handles_[kNullCharId + '#']);
+  }
   static const String& Semicolon() {
     return *(symbol_handles_[kNullCharId + ';']);
   }
diff --git a/runtime/vm/tags.cc b/runtime/vm/tags.cc
index 50e5e23..ffd224f 100644
--- a/runtime/vm/tags.cc
+++ b/runtime/vm/tags.cc
@@ -81,11 +81,13 @@
 };
 
 
-VMTagScope::VMTagScope(Isolate* base_isolate, uword tag)
+VMTagScope::VMTagScope(Isolate* base_isolate, uword tag, bool conditional_set)
     : StackResource(base_isolate) {
   ASSERT(isolate() != NULL);
   previous_tag_ = isolate()->vm_tag();
-  isolate()->set_vm_tag(tag);
+  if (conditional_set) {
+    isolate()->set_vm_tag(tag);
+  }
 }
 
 
diff --git a/runtime/vm/tags.h b/runtime/vm/tags.h
index e0077cb..6b16be3 100644
--- a/runtime/vm/tags.h
+++ b/runtime/vm/tags.h
@@ -22,6 +22,9 @@
   V(CompileClass)                                                              \
   V(CompileTopLevel)                                                           \
   V(CompileScanner)                                                            \
+  V(CompileParseFunction)                                                      \
+  V(CompileParseRegExp)                                                        \
+  V(CompileFlowGraphBuilder)                                                   \
   V(Dart)                                                                      \
   V(GCNewSpace)                                                                \
   V(GCOldSpace)                                                                \
@@ -40,6 +43,13 @@
     kNumVMTags,
     kRootTagId,       // Special tag used as root of all profiles.
     kTruncatedTagId,  // Special tag used to indicate a truncated call stack.
+    // ProfileInfo tags.
+    kNoneCodeTagId,
+    kOptimizedCodeTagId,
+    kUnoptimizedCodeTagId,
+    kNativeCodeTagId,
+    kInlineStartCodeTagId,
+    kInlineEndCodeTagId,
     kLastTagId,
   };
 
@@ -65,7 +75,7 @@
 
 class VMTagScope : StackResource {
  public:
-  VMTagScope(Isolate* isolate, uword tag);
+  VMTagScope(Isolate* isolate, uword tag, bool conditional_set = true);
   ~VMTagScope();
  private:
   uword previous_tag_;
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index bbdd1b4..aa4f67e 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -123,9 +123,9 @@
   Thread* thread = Thread::Current();
   ASSERT(thread != NULL);
   ASSERT(thread->isolate() == NULL);
-  ASSERT(isolate->mutator_thread() == NULL);
+  ASSERT(!isolate->HasMutatorThread());
   thread->isolate_ = isolate;
-  isolate->set_mutator_thread(thread);
+  isolate->MakeCurrentThreadMutator(thread);
   // TODO(koda): Migrate thread_state_ and profile_data_ to Thread, to allow
   // helper threads concurrent with mutator.
   ASSERT(isolate->thread_state() == NULL);
@@ -140,6 +140,8 @@
   isolate->set_vm_tag(VMTag::kVMTagId);
   ASSERT(thread->store_buffer_block_ == NULL);
   thread->store_buffer_block_ = isolate->store_buffer()->PopBlock();
+  ASSERT(isolate->heap() != NULL);
+  thread->heap_ = isolate->heap();
   thread->Schedule(isolate);
 }
 
@@ -160,9 +162,10 @@
   }
   isolate->set_thread_state(NULL);
   Profiler::EndExecution(isolate);
-  isolate->set_mutator_thread(NULL);
+  isolate->ClearMutatorThread();
   thread->isolate_ = NULL;
   ASSERT(Isolate::Current() == NULL);
+  thread->heap_ = NULL;
 }
 
 
@@ -171,9 +174,11 @@
   ASSERT(thread != NULL);
   ASSERT(thread->isolate() == NULL);
   thread->isolate_ = isolate;
+  ASSERT(isolate->heap() != NULL);
+  thread->heap_ = isolate->heap();
   // Do not update isolate->mutator_thread, but perform sanity check:
   // this thread should not be both the main mutator and helper.
-  ASSERT(isolate->mutator_thread() != thread);
+  ASSERT(!isolate->MutatorThreadIsCurrentThread());
   thread->Schedule(isolate);
 }
 
@@ -187,7 +192,8 @@
   ASSERT(isolate != NULL);
   thread->Unschedule();
   thread->isolate_ = NULL;
-  ASSERT(isolate->mutator_thread() != thread);
+  thread->heap_ = NULL;
+  ASSERT(!isolate->MutatorThreadIsCurrentThread());
 }
 
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 98cd55d..2b2d343 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -13,6 +13,7 @@
 
 class CHA;
 class HandleScope;
+class Heap;
 class Isolate;
 class Object;
 class RawBool;
@@ -20,6 +21,7 @@
 class StackResource;
 class Zone;
 
+
 // List of VM-global objects/addresses cached in each Thread object.
 #define CACHED_VM_OBJECTS_LIST(V)                                              \
   V(RawObject*, object_null_, Object::null(), NULL)                            \
@@ -28,7 +30,7 @@
 
 #define CACHED_ADDRESSES_LIST(V)                                               \
   V(uword, update_store_buffer_entry_point_,                                   \
-    StubCode::UpdateStoreBufferEntryPoint(), 0)
+    StubCode::UpdateStoreBuffer_entry()->EntryPoint(), 0)
 
 #define CACHED_CONSTANTS_LIST(V)                                               \
   CACHED_VM_OBJECTS_LIST(V)                                                    \
@@ -117,6 +119,10 @@
     return OFFSET_OF(Thread, state_) + OFFSET_OF(State, top_resource);
   }
 
+  static intptr_t heap_offset() {
+    return OFFSET_OF(Thread, heap_);
+  }
+
   int32_t no_handle_scope_depth() const {
 #if defined(DEBUG)
     return state_.no_handle_scope_depth;
@@ -153,6 +159,28 @@
 #endif
   }
 
+  int32_t no_safepoint_scope_depth() const {
+#if defined(DEBUG)
+    return state_.no_safepoint_scope_depth;
+#else
+    return 0;
+#endif
+  }
+
+  void IncrementNoSafepointScopeDepth() {
+#if defined(DEBUG)
+    ASSERT(state_.no_safepoint_scope_depth < INT_MAX);
+    state_.no_safepoint_scope_depth += 1;
+#endif
+  }
+
+  void DecrementNoSafepointScopeDepth() {
+#if defined(DEBUG)
+    ASSERT(state_.no_safepoint_scope_depth > 0);
+    state_.no_safepoint_scope_depth -= 1;
+#endif
+  }
+
   // Collection of isolate-specific state of a thread that is saved/restored
   // on isolate exit/re-entry.
   struct State {
@@ -162,6 +190,7 @@
 #if defined(DEBUG)
     HandleScope* top_handle_scope;
     intptr_t no_handle_scope_depth;
+    int32_t no_safepoint_scope_depth;
 #endif
   };
 
@@ -179,6 +208,7 @@
   static ThreadLocalKey thread_key_;
 
   Isolate* isolate_;
+  Heap* heap_;
   State state_;
   StoreBufferBlock* store_buffer_block_;
 #define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value)      \
@@ -207,6 +237,7 @@
   void Schedule(Isolate* isolate);
   void Unschedule();
 
+  friend class ApiZone;
   friend class Isolate;
   friend class StackZone;
   DISALLOW_COPY_AND_ASSIGN(Thread);
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
new file mode 100644
index 0000000..8ade009
--- /dev/null
+++ b/runtime/vm/thread_registry.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/thread_registry.h"
+
+#include "vm/isolate.h"
+#include "vm/lockers.h"
+
+namespace dart {
+
+void ThreadRegistry::SafepointThreads() {
+  MonitorLocker ml(monitor_);
+  // First wait for any older rounds that are still in progress.
+  while (in_rendezvous_) {
+    // Assert we are not the organizer trying to nest calls to SafepointThreads.
+    ASSERT(remaining_ > 0);
+    CheckSafepointLocked();
+  }
+  // Start a new round.
+  in_rendezvous_ = true;
+  ++round_;  // Overflows after 240+ years @ 10^9 safepoints per second.
+  remaining_ = CountScheduledLocked();
+  Isolate* isolate = Isolate::Current();
+  // We only expect this method to be called from within the isolate itself.
+  ASSERT(isolate->thread_registry() == this);
+  // TODO(koda): Rename Thread::PrepareForGC and call it here?
+  --remaining_;  // Exclude this thread from the count.
+  // Ensure the main mutator will reach a safepoint (could be running Dart).
+  if (!isolate->MutatorThreadIsCurrentThread()) {
+    isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
+  }
+  while (remaining_ > 0) {
+    ml.Wait(Monitor::kNoTimeout);
+  }
+}
+
+
+void ThreadRegistry::ResumeAllThreads() {
+  MonitorLocker ml(monitor_);
+  ASSERT(in_rendezvous_);
+  in_rendezvous_ = false;
+  ml.NotifyAll();
+}
+
+
+void ThreadRegistry::CheckSafepointLocked() {
+  int64_t last_round = -1;
+  while (in_rendezvous_) {
+    ASSERT(round_ >= last_round);
+    if (round_ != last_round) {
+      ASSERT((last_round == -1) || (round_ == (last_round + 1)));
+      last_round = round_;
+      // Participate in this round.
+      // TODO(koda): Rename Thread::PrepareForGC and call it here?
+      if (--remaining_ == 0) {
+        // Ensure the organizing thread is notified.
+        // TODO(koda): Use separate condition variables and plain 'Notify'.
+        monitor_->NotifyAll();
+      }
+    }
+    monitor_->Wait(Monitor::kNoTimeout);
+    // Note: Here, round_ is needed to detect and distinguish two cases:
+    // a) The old rendezvous is still in progress, so just keep waiting, or
+    // b) after ResumeAllThreads, another call to SafepointThreads was
+    // made before this thread got a chance to reaquire monitor_, thus this
+    // thread should (again) decrease remaining_ to indicate cooperation in
+    // this new round.
+  }
+}
+
+
+intptr_t ThreadRegistry::CountScheduledLocked() {
+  intptr_t count = 0;
+  for (int i = 0; i < entries_.length(); ++i) {
+    const Entry& entry = entries_[i];
+    if (entry.scheduled) {
+      ++count;
+    }
+  }
+  return count;
+}
+
+}  // namespace dart
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index af16026..f8f324d 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -16,10 +16,41 @@
 // Unordered collection of threads relating to a particular isolate.
 class ThreadRegistry {
  public:
-  ThreadRegistry() : mutex_(new Mutex()), entries_() {}
+  ThreadRegistry()
+      : monitor_(new Monitor()),
+        entries_(),
+        in_rendezvous_(false),
+        remaining_(0),
+        round_(0) {}
+
+  // Bring all threads in this isolate to a safepoint. The caller is
+  // expected to be implicitly at a safepoint. The threads will wait
+  // until ResumeAllThreads is called. First participates in any
+  // already pending rendezvous requested by another thread. Any
+  // thread that tries to enter this isolate during rendezvous will
+  // wait in RestoreStateTo. Nesting is not supported: the caller must
+  // call ResumeAllThreads before making further calls to
+  // SafepointThreads.
+  void SafepointThreads();
+
+  // Unblocks all threads participating in the rendezvous that was organized
+  // by a prior call to SafepointThreads.
+  // TODO(koda): Consider adding a scope helper to avoid omitting this call.
+  void ResumeAllThreads();
+
+  // Indicate that the current thread is at a safepoint, and offer to wait for
+  // any pending rendezvous request (if none, returns immediately).
+  void CheckSafepoint() {
+    MonitorLocker ml(monitor_);
+    CheckSafepointLocked();
+  }
 
   bool RestoreStateTo(Thread* thread, Thread::State* state) {
-    MutexLocker ml(mutex_);
+    MonitorLocker ml(monitor_);
+    // Wait for any rendezvous in progress.
+    while (in_rendezvous_) {
+      ml.Wait(Monitor::kNoTimeout);
+    }
     Entry* entry = FindEntry(thread);
     if (entry != NULL) {
       Thread::State st = entry->state;
@@ -50,21 +81,28 @@
   }
 
   void SaveStateFrom(Thread* thread, const Thread::State& state) {
-    MutexLocker ml(mutex_);
+    MonitorLocker ml(monitor_);
     Entry* entry = FindEntry(thread);
     ASSERT(entry != NULL);
     ASSERT(entry->scheduled);
     entry->scheduled = false;
     entry->state = state;
+    if (in_rendezvous_) {
+      // Don't wait for this thread.
+      ASSERT(remaining_ > 0);
+      if (--remaining_ == 0) {
+        ml.NotifyAll();
+      }
+    }
   }
 
   bool Contains(Thread* thread) {
-    MutexLocker ml(mutex_);
+    MonitorLocker ml(monitor_);
     return (FindEntry(thread) != NULL);
   }
 
   void CheckNotScheduled(Isolate* isolate) {
-    MutexLocker ml(mutex_);
+    MonitorLocker ml(monitor_);
     for (int i = 0; i < entries_.length(); ++i) {
       const Entry& entry = entries_[i];
       if (entry.scheduled) {
@@ -77,7 +115,7 @@
   }
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor) {
-    MutexLocker ml(mutex_);
+    MonitorLocker ml(monitor_);
     for (int i = 0; i < entries_.length(); ++i) {
       const Entry& entry = entries_[i];
       Zone* zone = entry.scheduled ? entry.thread->zone() : entry.state.zone;
@@ -96,8 +134,8 @@
 
   // Returns Entry corresponding to thread in registry or NULL.
   // Note: Lock should be taken before this function is called.
+  // TODO(koda): Add method Monitor::IsOwnedByCurrentThread.
   Entry* FindEntry(Thread* thread) {
-    DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
     for (int i = 0; i < entries_.length(); ++i) {
       if (entries_[i].thread == thread) {
         return &entries_[i];
@@ -106,9 +144,21 @@
     return NULL;
   }
 
-  Mutex* mutex_;
+  // Note: Lock should be taken before this function is called.
+  void CheckSafepointLocked();
+
+  // Returns the number threads that are scheduled on this isolate.
+  // Note: Lock should be taken before this function is called.
+  intptr_t CountScheduledLocked();
+
+  Monitor* monitor_;  // All access is synchronized through this monitor.
   MallocGrowableArray<Entry> entries_;
 
+  // Safepoint rendezvous state.
+  bool in_rendezvous_;    // A safepoint rendezvous request is in progress.
+  intptr_t remaining_;    // Number of threads yet to reach their safepoint.
+  int64_t round_;         // Counter, to prevent missing updates to remaining_
+                          // (see comments in CheckSafepointLocked).
 
   DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
 };
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index f781783..d1db1d3 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -14,10 +14,8 @@
 
 UNIT_TEST_CASE(Mutex) {
   // This unit test case needs a running isolate.
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
 
   Mutex* mutex = new Mutex();
   mutex->Lock();
@@ -31,18 +29,16 @@
   }
   // The isolate shutdown and the destruction of the mutex are out-of-order on
   // purpose.
-  isolate->Shutdown();
-  delete isolate;
+  Dart_ShutdownIsolate();
   delete mutex;
 }
 
 
 UNIT_TEST_CASE(Monitor) {
   // This unit test case needs a running isolate.
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  Isolate* isolate = Isolate::Current();
   // Thread interrupter interferes with this test, disable interrupts.
   isolate->set_thread_state(NULL);
   Profiler::EndExecution(isolate);
@@ -79,8 +75,7 @@
 
   // The isolate shutdown and the destruction of the mutex are out-of-order on
   // purpose.
-  isolate->Shutdown();
-  delete isolate;
+  Dart_ShutdownIsolate();
   delete monitor;
 }
 
@@ -109,11 +104,10 @@
 class TaskWithZoneAllocation : public ThreadPool::Task {
  public:
   TaskWithZoneAllocation(Isolate* isolate,
-                         const String& foo,
                          Monitor* monitor,
                          bool* done,
                          intptr_t id)
-      : isolate_(isolate), foo_(foo), monitor_(monitor), done_(done), id_(id) {}
+      : isolate_(isolate), monitor_(monitor), done_(done), id_(id) {}
   virtual void Run() {
     Thread::EnterIsolateAsHelper(isolate_);
     {
@@ -129,9 +123,10 @@
         a0->Add(true);
         a1.Add(true);
       }
-      // Check that we can create handles (but not yet allocate heap objects).
-      String& str = String::Handle(zone, foo_.raw());
-      EXPECT(str.Equals("foo"));
+      // Check that we can create handles and allocate in old space.
+      String& str = String::Handle(zone, String::New("old", Heap::kOld));
+      EXPECT(str.Equals("old"));
+
       const intptr_t unique_smi = id_ + 928327281;
       Smi& smi = Smi::Handle(zone, Smi::New(unique_smi));
       EXPECT(smi.Value() == unique_smi);
@@ -140,6 +135,22 @@
       // TODO(koda): Remove "->thread_registry()" after updating stack walker.
       isolate_->thread_registry()->VisitObjectPointers(&counter);
       EXPECT_EQ(1, counter.count());
+
+      char* unique_chars = zone->PrintToString("unique_str_%" Pd, id_);
+      String& unique_str = String::Handle(zone);
+      {
+        // String::New may create additional handles in the topmost scope that
+        // we don't want to count, so wrap this in its own scope.
+        HANDLESCOPE(thread);
+        unique_str = String::New(unique_chars, Heap::kOld);
+      }
+      EXPECT(unique_str.Equals(unique_chars));
+      ObjectCounter str_counter(isolate_, &unique_str);
+      // Ensure that our particular zone is visited.
+      // TODO(koda): Remove "->thread_registry()" after updating stack walker.
+      isolate_->thread_registry()->VisitObjectPointers(&str_counter);
+      // We should visit the string object exactly once.
+      EXPECT_EQ(1, str_counter.count());
     }
     Thread::ExitIsolateAsHelper();
     {
@@ -151,7 +162,6 @@
 
  private:
   Isolate* isolate_;
-  const String& foo_;
   Monitor* monitor_;
   bool* done_;
   intptr_t id_;
@@ -163,12 +173,12 @@
   Monitor sync[kTaskCount];
   bool done[kTaskCount];
   Isolate* isolate = Thread::Current()->isolate();
-  String& foo = String::Handle(String::New("foo"));
-
+  EXPECT(isolate->heap()->GrowthControlState());
+  isolate->heap()->DisableGrowthControl();
   for (int i = 0; i < kTaskCount; i++) {
     done[i] = false;
     Dart::thread_pool()->Run(
-        new TaskWithZoneAllocation(isolate, foo, &sync[i], &done[i], i));
+        new TaskWithZoneAllocation(isolate, &sync[i], &done[i], i));
   }
   for (int i = 0; i < kTaskCount; i++) {
     // Check that main mutator thread can still freely use its own zone.
@@ -195,18 +205,15 @@
   Zone* orig_zone = Thread::Current()->zone();
   char* orig_str = orig_zone->PrintToString("foo");
   Thread::ExitIsolate();
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isos[2];
   // Create and enter a new isolate.
-  isos[0] = Isolate::Init(NULL, api_flags);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
   Zone* zone0 = Thread::Current()->zone();
   EXPECT(zone0 != orig_zone);
-  isos[0]->Shutdown();
-  Thread::ExitIsolate();
+  Dart_ShutdownIsolate();
   // Create and enter yet another isolate.
-  isos[1] = Isolate::Init(NULL, api_flags);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
   {
     // Create a stack resource this time, and exercise it.
     StackZone stack_zone(Thread::Current());
@@ -214,14 +221,220 @@
     EXPECT(zone1 != zone0);
     EXPECT(zone1 != orig_zone);
   }
-  isos[1]->Shutdown();
-  Thread::ExitIsolate();
+  Dart_ShutdownIsolate();
   Thread::EnterIsolate(orig);
   // Original zone should be preserved.
   EXPECT_EQ(orig_zone, Thread::Current()->zone());
   EXPECT_STREQ("foo", orig_str);
-  delete isos[0];
-  delete isos[1];
+}
+
+
+// A helper thread that alternatingly cooperates and organizes
+// safepoint rendezvous. At rendezvous, it explicitly visits the
+// stacks looking for a specific marker (Smi) to verify that the expected
+// number threads are actually visited. The task is "done" when it has
+// successfully made all other tasks and the main thread rendezvous (may
+// not happen in the first rendezvous, since tasks are still starting up).
+class SafepointTestTask : public ThreadPool::Task {
+ public:
+  static const intptr_t kTaskCount;
+
+  SafepointTestTask(Isolate* isolate,
+                    Mutex* mutex,
+                    intptr_t* expected_count,
+                    intptr_t* total_done,
+                    intptr_t* exited)
+    : isolate_(isolate),
+      mutex_(mutex),
+      expected_count_(expected_count),
+      total_done_(total_done),
+      exited_(exited),
+      local_done_(false) {}
+
+  virtual void Run() {
+    Thread::EnterIsolateAsHelper(isolate_);
+    {
+      MutexLocker ml(mutex_);
+      ++*expected_count_;
+    }
+    for (int i = 0; ; ++i) {
+      Thread* thread = Thread::Current();
+      StackZone stack_zone(thread);
+      Zone* zone = thread->zone();
+      HANDLESCOPE(thread);
+      const intptr_t kUniqueSmi = 928327281;
+      Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi));
+      if ((i % 100) != 0) {
+        // Usually, we just cooperate.
+        isolate_->thread_registry()->CheckSafepoint();
+      } else {
+        // But occasionally, organize a rendezvous.
+        isolate_->thread_registry()->SafepointThreads();
+        ObjectCounter counter(isolate_, &smi);
+        isolate_->thread_registry()->VisitObjectPointers(&counter);
+        {
+          MutexLocker ml(mutex_);
+          EXPECT_EQ(*expected_count_, counter.count());
+        }
+        UserTag& tag = UserTag::Handle(zone, isolate_->current_tag());
+        if (tag.raw() != isolate_->default_tag()) {
+          String& label = String::Handle(zone, tag.label());
+          EXPECT(label.Equals("foo"));
+          MutexLocker ml(mutex_);
+          if (*expected_count_ == kTaskCount && !local_done_) {
+            // Success for the first time! Remember that we are done, and
+            // update the total count.
+            local_done_ = true;
+            ++*total_done_;
+          }
+        }
+        isolate_->thread_registry()->ResumeAllThreads();
+      }
+      // Check whether everyone is done.
+      {
+        MutexLocker ml(mutex_);
+        if (*total_done_ == kTaskCount) {
+          // Another task might be at SafepointThreads when resuming. Ensure its
+          // expectation reflects reality, since we pop our handles here.
+          --*expected_count_;
+          break;
+        }
+      }
+    }
+    Thread::ExitIsolateAsHelper();
+    {
+      MutexLocker ml(mutex_);
+      ++*exited_;
+    }
+  }
+
+ private:
+  Isolate* isolate_;
+  Mutex* mutex_;
+  intptr_t* expected_count_;  // # copies of kUniqueSmi we expect to visit.
+  intptr_t* total_done_;      // # tasks that successfully safepointed once.
+  intptr_t* exited_;          // # tasks that are no longer running.
+  bool local_done_;           // this task has successfully safepointed >= once.
+};
+
+
+const intptr_t SafepointTestTask::kTaskCount = 5;
+
+
+// Test rendezvous of:
+// - helpers in VM code,
+// - main thread in pure Dart,
+// organized by
+// - helpers.
+TEST_CASE(SafepointTestDart) {
+  Isolate* isolate = Thread::Current()->isolate();
+  Mutex mutex;
+  intptr_t expected_count = 0;
+  intptr_t total_done = 0;
+  intptr_t exited = 0;
+  for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+    Dart::thread_pool()->Run(new SafepointTestTask(
+        isolate, &mutex, &expected_count, &total_done, &exited));
+  }
+  // Run Dart code on the main thread long enough to allow all helpers
+  // to get their verification done and exit. Use a specific UserTag
+  // to enable the helpers to verify that the main thread is
+  // successfully interrupted in the pure Dart loop.
+#if defined(USING_SIMULATOR)
+  const intptr_t kLoopCount = 12345678;
+#else
+  const intptr_t kLoopCount = 1234567890;
+#endif  // USING_SIMULATOR
+  char buffer[1024];
+  OS::SNPrint(buffer, sizeof(buffer),
+      "import 'dart:profiler';\n"
+      "int dummy = 0;\n"
+      "main() {\n"
+      "  new UserTag('foo').makeCurrent();\n"
+      "  for (dummy = 0; dummy < %" Pd "; ++dummy) {\n"
+      "    dummy += (dummy & 1);\n"
+      "  }\n"
+      "}\n", kLoopCount);
+  Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
+  EXPECT_VALID(lib);
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  // Ensure we looped long enough to allow all helpers to succeed and exit.
+  {
+    MutexLocker ml(&mutex);
+    EXPECT_EQ(SafepointTestTask::kTaskCount, total_done);
+    EXPECT_EQ(SafepointTestTask::kTaskCount, exited);
+  }
+}
+
+
+// Test rendezvous of:
+// - helpers in VM code, and
+// - main thread in VM code,
+// organized by
+// - helpers.
+TEST_CASE(SafepointTestVM) {
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
+  Mutex mutex;
+  intptr_t expected_count = 0;
+  intptr_t total_done = 0;
+  intptr_t exited = 0;
+  for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+    Dart::thread_pool()->Run(new SafepointTestTask(
+        isolate, &mutex, &expected_count, &total_done, &exited));
+  }
+  String& label = String::Handle(String::New("foo"));
+  UserTag& tag = UserTag::Handle(UserTag::New(label));
+  isolate->set_current_tag(tag);
+  while (true) {
+    isolate->thread_registry()->CheckSafepoint();
+    MutexLocker ml(&mutex);
+    if (exited == SafepointTestTask::kTaskCount) {
+      break;
+    }
+  }
+}
+
+
+// Test rendezvous of:
+// - helpers in VM code, and
+// - main thread in VM code,
+// organized by
+// - main thread, and
+// - helpers.
+TEST_CASE(SafepointTestVM2) {
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
+  Mutex mutex;
+  intptr_t expected_count = 0;
+  intptr_t total_done = 0;
+  intptr_t exited = 0;
+  for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+    Dart::thread_pool()->Run(new SafepointTestTask(
+        isolate, &mutex, &expected_count, &total_done, &exited));
+  }
+  bool all_helpers = false;
+  do {
+    isolate->thread_registry()->SafepointThreads();
+    {
+      MutexLocker ml(&mutex);
+      if (expected_count == SafepointTestTask::kTaskCount) {
+        all_helpers = true;
+      }
+    }
+    isolate->thread_registry()->ResumeAllThreads();
+  } while (!all_helpers);
+  String& label = String::Handle(String::New("foo"));
+  UserTag& tag = UserTag::Handle(UserTag::New(label));
+  isolate->set_current_tag(tag);
+  while (true) {
+    isolate->thread_registry()->CheckSafepoint();
+    MutexLocker ml(&mutex);
+    if (exited == SafepointTestTask::kTaskCount) {
+      break;
+    }
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 3d5e179..4c3fb9b 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -197,12 +197,12 @@
   obj.AddProperty("cat", stream_->name());
   obj.AddProperty64("tid", tid);
   obj.AddProperty64("pid", pid);
-  obj.AddProperty("ts", static_cast<double>(TimeOrigin()));
+  obj.AddPropertyTimeMillis("ts", TimeOrigin());
 
   switch (event_type()) {
     case kDuration: {
       obj.AddProperty("ph", "X");
-      obj.AddProperty("dur", static_cast<double>(TimeDuration()));
+      obj.AddPropertyTimeMillis("dur", TimeDuration());
     }
     break;
     case kInstant: {
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 88b8cb2..52dc222 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -335,8 +335,10 @@
     'port.cc',
     'port.h',
     'port_test.cc',
-    'proccpuinfo.h',
+    'precompiler.cc',
+    'precompiler.h',
     'proccpuinfo.cc',
+    'proccpuinfo.h',
     'profiler_service.cc',
     'profiler_service.h',
     'profiler_test.cc',
@@ -452,6 +454,7 @@
     'thread_pool.cc',
     'thread_pool.h',
     'thread_pool_test.cc',
+    'thread_registry.cc',
     'thread_registry.h',
     'thread_test.cc',
     'timeline.cc',
diff --git a/runtime/vm/zone_test.cc b/runtime/vm/zone_test.cc
index 580f968..da5f208 100644
--- a/runtime/vm/zone_test.cc
+++ b/runtime/vm/zone_test.cc
@@ -16,11 +16,9 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT(Isolate::Current() == isolate);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  Isolate* isolate = Isolate::Current();
   EXPECT(isolate->current_zone() == NULL);
   {
     StackZone stack_zone(isolate);
@@ -72,8 +70,7 @@
     EXPECT_LE(allocated_size, zone->SizeInBytes());
   }
   EXPECT(isolate->current_zone() == NULL);
-  isolate->Shutdown();
-  delete isolate;
+  Dart_ShutdownIsolate();
 }
 
 
@@ -81,11 +78,9 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT(Isolate::Current() == isolate);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  Isolate* isolate = Isolate::Current();
   EXPECT(isolate->current_zone() == NULL);
   {
     StackZone zone(isolate);
@@ -98,8 +93,7 @@
     EXPECT_LE(allocated_size, zone.SizeInBytes());
   }
   EXPECT(isolate->current_zone() == NULL);
-  isolate->Shutdown();
-  delete isolate;
+  Dart_ShutdownIsolate();
 }
 
 
@@ -108,11 +102,9 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT(Isolate::Current() == isolate);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  Isolate* isolate = Isolate::Current();
   EXPECT(isolate->current_zone() == NULL);
   {
     StackZone zone(isolate);
@@ -121,8 +113,7 @@
     const intptr_t kNumElements = (kIntptrMax / sizeof(uint32_t)) + 1;
     zone.GetZone()->Alloc<uint32_t>(kNumElements);
   }
-  isolate->Shutdown();
-  delete isolate;
+  Dart_ShutdownIsolate();
 }
 
 
@@ -130,11 +121,9 @@
 #if defined(DEBUG)
   FLAG_trace_zones = true;
 #endif
-  Isolate::Flags vm_flags;
-  Dart_IsolateFlags api_flags;
-  vm_flags.CopyTo(&api_flags);
-  Isolate* isolate = Isolate::Init(NULL, api_flags);
-  EXPECT(Isolate::Current() == isolate);
+  Dart_CreateIsolate(
+      NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
+  Isolate* isolate = Isolate::Current();
   EXPECT(isolate->current_zone() == NULL);
   static int marker;
 
@@ -172,8 +161,7 @@
     EXPECT_EQ(87, second->slot);
   }
   EXPECT(isolate->current_zone() == NULL);
-  isolate->Shutdown();
-  delete isolate;
+  Dart_ShutdownIsolate();
 }
 
 
diff --git a/sdk/lib/_internal/js_runtime/lib/annotations.dart b/sdk/lib/_internal/js_runtime/lib/annotations.dart
index ee33493..2862612 100644
--- a/sdk/lib/_internal/js_runtime/lib/annotations.dart
+++ b/sdk/lib/_internal/js_runtime/lib/annotations.dart
@@ -56,3 +56,6 @@
 
 /// Annotation that marks the declaration as a patch for the lazy emitter.
 const _Patch patch_lazy = const _Patch('lazy');
+
+/// Annotation that marks the declaration as a patch for the startup emitter.
+const _Patch patch_startup = const _Patch('startup');
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 2ec85f0..971b37f 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -8,6 +8,7 @@
 import 'dart:_js_helper' show patch,
                               patch_full,
                               patch_lazy,
+                              patch_startup,
                               checkInt,
                               getRuntimeType,
                               jsonEncodeNative,
@@ -73,7 +74,15 @@
   static apply(Function function,
                List positionalArguments,
                [Map<Symbol, dynamic> namedArguments]) {
-    return Primitives.applyFunctionNewEmitter(function, positionalArguments,
+    return Primitives.applyFunction2(function, positionalArguments,
+        namedArguments == null ? null : _symbolMapToStringMap(namedArguments));
+  }
+
+  @patch_startup
+  static apply(Function function,
+               List positionalArguments,
+               [Map<Symbol, dynamic> namedArguments]) {
+    return Primitives.applyFunction2(function, positionalArguments,
         namedArguments == null ? null : _symbolMapToStringMap(namedArguments));
   }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
index a6087a1..4f06174d 100644
--- a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
@@ -7,26 +7,28 @@
 import 'dart:_js_helper' show patch;
 import 'dart:_foreign_helper' show JS;
 
-/// If [when] is true, stop the program as if a breakpoint where hit at the
-/// following statement. Returns the value of [when]. Some debuggers may
-/// display [msg].
-/// NOTE: When invoked, the isolate will not return until a debugger
-/// continues execution. When running in the Dart VM the behaviour is the same
-/// regardless of whether or not a debugger is connected. When compiled to
-/// JavaScript, this uses the "debugger" statement, and behaves exactly as
-/// that does.
 @patch
 @ForceInline()
-bool debugger({bool when: true, String msg}) {
+bool debugger({bool when: true, String message}) {
   if (when) {
     JS('', 'debugger');
   }
   return when;
 }
 
-/// Send a reference to [object] to any attached debuggers so they may open an
-/// inspector on the object. Returns the argument.
 @patch
-inspect(object) {
+Object inspect(Object object) {
   return object;
 }
+
+@patch
+log(String message,
+    {DateTime time,
+     int sequenceNumber,
+     int level: 0,
+     String name: '',
+     Zone zone,
+     Object error,
+     StackTrace stackTrace}) {
+  // TODO.
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart b/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
index 5ff44bb..b8a44b4 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
@@ -9,9 +9,9 @@
     CLASS_FIELDS_EXTRACTOR,
     CREATE_NEW_ISOLATE,
     CURRENT_SCRIPT,
-    GLOBAL_FUNCTIONS,
     INITIALIZE_EMPTY_INSTANCE,
-    INSTANCE_FROM_CLASS_ID;
+    INSTANCE_FROM_CLASS_ID,
+    STATIC_FUNCTION_NAME_PROPERTY_NAME;
 
 import 'dart:async';
 import 'dart:collection' show Queue;
@@ -24,6 +24,7 @@
     Null,
     Primitives,
     convertDartClosureToJS,
+    createDartClosureFromNameOfStaticFunction,
     isDartObject,
     random64,
     requiresPreamble;
@@ -103,6 +104,7 @@
     throw new ArgumentError("Arguments to main must be a List: $args");
   }
   _globalState = new _Manager(entry);
+  _globalState._initialize();
 
   // Don't start the main loop again, if we are in a worker.
   if (_globalState.isWorker) return;
@@ -220,7 +222,9 @@
   /** The entry point given by [startRootIsolate]. */
   final Function entry;
 
-  _Manager(this.entry) {
+  _Manager(this.entry);
+
+  _initialize() {
     _nativeDetectEnvironment();
     topEventLoop = new _EventLoop();
     isolates = new Map<int, _IsolateContext>();
@@ -235,6 +239,8 @@
     bool isWindowDefined = globalWindow != null;
     bool isWorkerDefined = globalWorker != null;
 
+    // `isWorker` must be initialized now, since `IsolateNatives.thisScript`
+    // may access it.
     isWorker = !isWindowDefined && globalPostMessageDefined;
     supportsWorkers = isWorker
        || (isWorkerDefined && IsolateNatives.thisScript != null);
@@ -764,6 +770,8 @@
     }
     // A worker has no script tag - so get an url from a stack-trace.
     if (_globalState.isWorker) return computeThisScriptFromTrace();
+    // An isolate that doesn't support workers, but doesn't have a
+    // currentScript either. This is most likely a Chrome extension.
     return null;
   }
 
@@ -904,8 +912,7 @@
   }
 
   static _getJSFunctionFromName(String functionName) {
-    var globalFunctionsContainer = JS_EMBEDDED_GLOBAL("", GLOBAL_FUNCTIONS);
-    return JS("", "#[#]()", globalFunctionsContainer, functionName);
+    return createDartClosureFromNameOfStaticFunction(functionName);
   }
 
   /**
@@ -914,7 +921,9 @@
    * but you should probably not count on this.
    */
   static String _getJSFunctionName(Function f) {
-    return (f is Closure) ? JS("String|Null", r'#.$name', f) : null;
+    return (f is Closure)
+        ? JS("String|Null", r'#[#]', f, STATIC_FUNCTION_NAME_PROPERTY_NAME)
+        : null;
   }
 
   /** Create a new JavaScript object instance given its constructor. */
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index dda551e..fd53e61 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -19,7 +19,8 @@
     JsBuiltin,
     JsGetName,
     LEAF_TAGS,
-    NATIVE_SUPERCLASS_TAG_NAME;
+    NATIVE_SUPERCLASS_TAG_NAME,
+    STATIC_FUNCTION_NAME_PROPERTY_NAME;
 
 import 'dart:collection';
 
@@ -188,6 +189,16 @@
                     JsBuiltin.getType, index);
 }
 
+/// Returns a Dart closure for the global function with the given [name].
+///
+/// The [name] is the globally unique (minified) JavaScript name of the
+/// function. The name must be in correspondence with the propertyName that is
+/// used when creating a tear-off (see [fromTearOff]).
+Function createDartClosureFromNameOfStaticFunction(String name) {
+  return JS_BUILTIN('returns:Function',
+                    JsBuiltin.createDartClosureFromNameOfStaticFunction, name);
+}
+
 /// No-op method that is called to inform the compiler that preambles might
 /// be needed when executing the resulting JS file in a command-line
 /// JS engine.
@@ -1145,64 +1156,180 @@
             namedArgumentList));
   }
 
-  static applyFunctionNewEmitter(Function function,
-                                 List positionalArguments,
-                                 Map<String, dynamic> namedArguments) {
-    if (namedArguments == null) {
-      int requiredParameterCount = JS('int', r'#[#]', function,
-          JS_GET_NAME(JsGetName.REQUIRED_PARAMETER_PROPERTY));
-      int argumentCount = positionalArguments.length;
-      if (argumentCount < requiredParameterCount) {
-        return functionNoSuchMethod(function, positionalArguments, null);
+  /**
+   * Implements [Function.apply] for the lazy and startup emitters.
+   *
+   * There are two types of closures that can reach this function:
+   *
+   * 1. tear-offs (including tear-offs of static functions).
+   * 2. anonymous closures.
+   *
+   * They are treated differently (although there are lots of similarities).
+   * Both have in common that they have
+   * a [JsGetName.CALL_CATCH_ALL] and
+   * a [JsGetName.REQUIRED_PARAMETER_PROPERTY] property.
+   *
+   * If the closure supports optional parameters, then they also feature
+   * a [JsGetName.DEFAULT_VALUES_PROPERTY] property.
+   *
+   * The catch-all property is a method that takes all arguments (including
+   * all optional positional or named arguments). If the function accepts
+   * optional arguments, then the default-values property stores (potentially
+   * wrapped in a function) the default values for the optional arguments. If
+   * the function accepts optional positional arguments, then the value is a
+   * JavaScript array with the default values. Otherwise, when the function
+   * accepts optional named arguments, it is a JavaScript object.
+   *
+   * The default-values property may either contain the value directly, or
+   * it can be a function that returns the default-values when invoked.
+   *
+   * If the function is an anonymous closure, then the catch-all property
+   * only contains a string pointing to the property that should be used
+   * instead. For example, if the catch-all property contains the string
+   * "call$4", then the object's "call$4" property should be used as if it was
+   * the value of the catch-all property.
+   */
+  static applyFunction2(Function function,
+                        List positionalArguments,
+                        Map<String, dynamic> namedArguments) {
+    // Fast shortcut for the common case.
+    if (JS('bool', '# instanceof Array', positionalArguments) &&
+        (namedArguments == null || namedArguments.isEmpty)) {
+      // Let the compiler know that we did a type-test.
+      List arguments = (JS('JSArray', '#', positionalArguments));
+      int argumentCount = arguments.length;
+      if (argumentCount == 0) {
+        String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX0);
+        if (JS('bool', '!!#[#]', function, selectorName)) {
+          return JS('', '#[#]()', function, selectorName);
+        }
+      } else if (argumentCount == 1) {
+        String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX1);
+        if (JS('bool', '!!#[#]', function, selectorName)) {
+          return JS('', '#[#](#[0])', function, selectorName, arguments);
+        }
+      } else if (argumentCount == 2) {
+        String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX2);
+        if (JS('bool', '!!#[#]', function, selectorName)) {
+          return JS('', '#[#](#[0],#[1])', function, selectorName,
+          arguments, arguments);
+        }
+      } else if (argumentCount == 3) {
+        String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX3);
+        if (JS('bool', '!!#[#]', function, selectorName)) {
+          return JS('', '#[#](#[0],#[1],#[2])', function, selectorName,
+          arguments, arguments, arguments);
+        }
       }
       String selectorName =
           '${JS_GET_NAME(JsGetName.CALL_PREFIX)}\$$argumentCount';
       var jsStub = JS('var', r'#[#]', function, selectorName);
-      if (jsStub == null) {
-        // Do a dynamic call.
-        var interceptor = getInterceptor(function);
-        var jsFunction = JS('', '#[#]', interceptor,
-            JS_GET_NAME(JsGetName.CALL_CATCH_ALL));
-        var defaultValues = JS('var', r'#[#]', function,
-            JS_GET_NAME(JsGetName.DEFAULT_VALUES_PROPERTY));
-        if (!JS('bool', '# instanceof Array', defaultValues)) {
-          // The function expects named arguments!
-          return functionNoSuchMethod(function, positionalArguments, null);
-        }
-        int defaultsLength = JS('int', "#.length", defaultValues);
-        int maxArguments = requiredParameterCount + defaultsLength;
-        if (argumentCount > maxArguments) {
-          // The function expects less arguments!
-          return functionNoSuchMethod(function, positionalArguments, null);
-        }
-        List arguments = new List.from(positionalArguments);
-        List missingDefaults = JS('JSArray', '#.slice(#)', defaultValues,
-            argumentCount - requiredParameterCount);
-        arguments.addAll(missingDefaults);
-        return JS('var', '#.apply(#, #)', jsFunction, function, arguments);
+      if (jsStub != null) {
+        return JS('var', '#.apply(#, #)', jsStub, function, arguments);
       }
-      return JS('var', '#.apply(#, #)', jsStub, function, positionalArguments);
+    }
+
+    return _genericApplyFunction2(
+        function, positionalArguments, namedArguments);
+  }
+
+  static _genericApplyFunction2(Function function,
+                                List positionalArguments,
+                                Map<String, dynamic> namedArguments) {
+    List arguments;
+    if (positionalArguments != null) {
+      if (JS('bool', '# instanceof Array', positionalArguments)) {
+        arguments = JS('JSArray', '#', positionalArguments);
+      } else {
+        arguments = new List.from(positionalArguments);
+      }
     } else {
-      var interceptor = getInterceptor(function);
-      var jsFunction = JS('', '#[#]', interceptor,
-          JS_GET_NAME(JsGetName.CALL_CATCH_ALL));
-      var defaultValues = JS('JSArray', r'#[#]', function,
+      arguments = [];
+    }
+
+    int argumentCount = arguments.length;
+
+    int requiredParameterCount = JS('int', r'#[#]', function,
+          JS_GET_NAME(JsGetName.REQUIRED_PARAMETER_PROPERTY));
+
+    if (argumentCount < requiredParameterCount) {
+      return functionNoSuchMethod(function, arguments, namedArguments);
+    }
+
+    var defaultValuesClosure = JS('var', r'#[#]', function,
           JS_GET_NAME(JsGetName.DEFAULT_VALUES_PROPERTY));
-      List keys = JS('JSArray', r'Object.keys(#)', defaultValues);
-      List arguments = new List.from(positionalArguments);
-      int used = 0;
-      for (String key in keys) {
-        var value = namedArguments[key];
-        if (value != null) {
-          used++;
-          arguments.add(value);
-        } else {
-          arguments.add(JS('var', r'#[#]', defaultValues, key));
-        }
+
+    bool acceptsOptionalArguments = defaultValuesClosure != null;
+
+    // Default values are stored inside a JavaScript closure to avoid
+    // accessing them too early.
+    var defaultValues = acceptsOptionalArguments
+        ? JS('', '#()', defaultValuesClosure)
+        : null;
+
+    var interceptor = getInterceptor(function);
+    var jsFunction = JS('', '#[#]', interceptor,
+        JS_GET_NAME(JsGetName.CALL_CATCH_ALL));
+    if (jsFunction is String) {
+      // Anonymous closures redirect to the catch-all property instead of
+      // storing the catch-all method directly in the catch-all property.
+      jsFunction = JS('', '#[#]', interceptor, jsFunction);
+    }
+
+    if (!acceptsOptionalArguments) {
+      if (argumentCount == requiredParameterCount) {
+        return JS('var', r'#.apply(#, #)', jsFunction, function, arguments);
       }
-      if (used != namedArguments.length) {
-        return functionNoSuchMethod(function, positionalArguments,
-            namedArguments);
+      return functionNoSuchMethod(function, arguments, namedArguments);
+    }
+
+    bool acceptsPositionalArguments =
+        JS('bool', '# instanceof Array', defaultValues);
+
+    if (acceptsPositionalArguments) {
+      if (namedArguments != null && namedArguments.isNotEmpty) {
+        // Tried to invoke a function that takes optional positional arguments
+        // with named arguments.
+        return functionNoSuchMethod(function, arguments, namedArguments);
+      }
+
+      int defaultsLength = JS('int', "#.length", defaultValues);
+      int maxArguments = requiredParameterCount + defaultsLength;
+      if (argumentCount > maxArguments) {
+        // The function expects fewer arguments.
+        return functionNoSuchMethod(function, arguments, null);
+      }
+      List missingDefaults = JS('JSArray', '#.slice(#)', defaultValues,
+          argumentCount - requiredParameterCount);
+      arguments.addAll(missingDefaults);
+      return JS('var', '#.apply(#, #)', jsFunction, function, arguments);
+    } else {
+      // Handle named arguments.
+
+      if (argumentCount > requiredParameterCount) {
+        // Tried to invoke a function that takes named parameters with
+        // too many positional arguments.
+        return functionNoSuchMethod(function, arguments, namedArguments);
+      }
+
+      List keys = JS('JSArray', r'Object.keys(#)', defaultValues);
+      if (namedArguments == null) {
+        for (String key in keys) {
+          arguments.add(JS('var', '#[#]', defaultValues, key));
+        }
+      } else {
+        int used = 0;
+        for (String key in keys) {
+          if (namedArguments.containsKey(key)) {
+            used++;
+            arguments.add(namedArguments[key]);
+          } else {
+            arguments.add(JS('var', r'#[#]', defaultValues, key));
+          }
+        }
+        if (used != namedArguments.length) {
+          return functionNoSuchMethod(function, arguments, namedArguments);
+        }
       }
       return JS('var', r'#.apply(#, #)', jsFunction, function, arguments);
     }
@@ -2213,8 +2340,11 @@
    *
    * In other words, creates a tear-off closure.
    *
+   * The [propertyName] argument is used by
+   * [JsBuiltin.createDartClosureFromNameOfStaticFunction].
+   *
    * Called from [closureFromTearOff] as well as from reflection when tearing
-   * of a method via [:getField:].
+   * of a method via `getField`.
    *
    * This method assumes that [functions] was created by the JavaScript function
    * `addStubs` in `reflection_data_parser.dart`. That is, a list of JavaScript
@@ -2316,7 +2446,8 @@
       trampoline = forwardCallTo(receiver, function, isIntercepted);
       JS('', '#.\$reflectionInfo = #', trampoline, reflectionInfo);
     } else {
-      JS('', '#.\$name = #', prototype, propertyName);
+      JS('', '#[#] = #',
+          prototype, STATIC_FUNCTION_NAME_PROPERTY_NAME, propertyName);
     }
 
     var signatureFunction;
@@ -2629,7 +2760,8 @@
 
 class StaticClosure extends TearOffClosure {
   String toString() {
-    String name = JS('String|Null', '#.\$name', this);
+    String name =
+        JS('String|Null', '#[#]', this, STATIC_FUNCTION_NAME_PROPERTY_NAME);
     if (name == null) return "Closure of unknown static method";
     return "Closure '$name'";
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index e99810a..9b44116c 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -82,8 +82,8 @@
   static makeNative(
       String source, bool multiLine, bool caseSensitive, bool global) {
     checkString(source);
-    String m = multiLine ? 'm' : '';
-    String i = caseSensitive ? '' : 'i';
+    String m = multiLine == true ? 'm' : '';
+    String i = caseSensitive == true ? '' : 'i';
     String g = global ? 'g' : '';
     // We're using the JavaScript's try catch instead of the Dart one
     // to avoid dragging in Dart runtime support just because of using
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index a427996..b08e3a3 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -41,6 +41,12 @@
 /// native class.
 const NATIVE_SUPERCLASS_TAG_NAME = r"$nativeSuperclassTag";
 
+/// The name of the static-function property name.
+///
+/// This property is set for all tear-offs of static functions, and provides
+/// the static function's unique (potentially minified) name.
+const STATIC_FUNCTION_NAME_PROPERTY_NAME = r'$static_name';
+
 
 /// The name of the embedded global for metadata.
 ///
@@ -54,10 +60,6 @@
 /// Use [JsBuiltin.getType] instead of directly accessing this embedded global.
 const TYPES = 'types';
 
-/// An embedded global name that can be used to store a mapping from
-/// static function names to dart-closure getters.
-const GLOBAL_FUNCTIONS = 'globalFunctions';
-
 /// Returns a function that maps a name of a class to its type.
 ///
 /// This embedded global is used by the runtime when computing the internal
@@ -77,8 +79,10 @@
 
 /// A JS map from mangled instance names to their unmangled names.
 ///
-/// If the program does not use reflection, this embedded global may be empty
-/// (but not null or undefined).
+/// This embedded global is mainly used for reflection, but is also used to
+/// map const-symbols (`const Symbol('x')`) to the mangled instance names.
+///
+/// This embedded global may be empty (but not null or undefined).
 const MANGLED_NAMES = 'mangledNames';
 
 /// A JS map from dispatch tags (usually constructor names of DOM classes) to
@@ -235,11 +239,30 @@
 const PRECOMPILED = 'precompiled';
 
 /// An emitter-internal embedded global. This global is not used by the runtime.
+const FINISHED_CLASSES = 'finishedClasses';
+
+/// An emitter-internal embedded global. This global is not used by the runtime.
 ///
 /// The constant remains in this file to make sure that other embedded globals
 /// don't clash with it.
-const FINISHED_CLASSES = 'finishedClasses';
+///
+/// It can be used by the compiler to store a mapping from static function names
+/// to dart-closure getters (which can be useful for
+/// [JsBuiltin.createDartClosureFromNameOfStaticFunction].
+const GLOBAL_FUNCTIONS = 'globalFunctions';
 
+/// An emitter-internal embedded global. This global is not used by the runtime.
+///
+/// The constant remains in this file to make sure that other embedded globals
+/// don't clash with it.
+///
+/// This embedded global stores a function that returns a dart-closure getter
+/// for a given static function name.
+///
+/// This embedded global is used to implement
+/// [JsBuiltin.createDartClosureFromNameOfStaticFunction], and is only
+/// used with isolates.
+const STATIC_FUNCTION_NAME_TO_CLOSURE = 'staticFunctionNameToClosure';
 
 /// A JavaScript object literal that maps the (minified) JavaScript constructor
 /// name (as given by [JsBuiltin.rawRtiToJsConstructorName] to the
@@ -258,6 +281,7 @@
 /// This embedded global is only used by reflection.
 const STATICS = 'statics';
 
+
 /// An array of library descriptors.
 ///
 /// The descriptor contains information such as name, uri, classes, ...
@@ -391,4 +415,16 @@
   ///     JS_BUILTIN('returns:var;effects:none;depends:none',
   ///                JsBuiltin.getType, index);
   getType,
+
+  /// Returns a Dart closure for the global function with the given [name].
+  ///
+  /// The [name] is the globally unique (minified) JavaScript name of the
+  /// function (same as the one stored in [STATIC_FUNCTION_NAME_PROPERTY_NAME])
+  ///
+  /// This builtin is used when a static closure was sent to a different
+  /// isolate.
+  ///
+  ///     JS_BUILTIN('returns:Function',
+  ///                JsBuiltin.createDartClosureFromNameOfStaticFunction, name);
+  createDartClosureFromNameOfStaticFunction,
 }
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 428e878..6eb737e 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -842,7 +842,7 @@
    * the returned stream is listened to.
    */
   Stream<T> take(int count) {
-    return new _TakeStream(this, count);
+    return new _TakeStream<T>(this, count);
   }
 
   /**
@@ -864,7 +864,7 @@
    * the returned stream is listened to.
    */
   Stream<T> takeWhile(bool test(T element)) {
-    return new _TakeWhileStream(this, test);
+    return new _TakeWhileStream<T>(this, test);
   }
 
   /**
@@ -875,7 +875,7 @@
    * the returned stream is listened to.
    */
   Stream<T> skip(int count) {
-    return new _SkipStream(this, count);
+    return new _SkipStream<T>(this, count);
   }
 
   /**
@@ -891,7 +891,7 @@
    * the returned stream is listened to.
    */
   Stream<T> skipWhile(bool test(T element)) {
-    return new _SkipWhileStream(this, test);
+    return new _SkipWhileStream<T>(this, test);
   }
 
   /**
@@ -908,7 +908,7 @@
    * will individually perform the `equals` test.
    */
   Stream<T> distinct([bool equals(T previous, T next)]) {
-    return new _DistinctStream(this, equals);
+    return new _DistinctStream<T>(this, equals);
   }
 
   /**
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 26bbb14..f856b61 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -639,8 +639,8 @@
       throw new StateError("Stream has already been listened to.");
     }
     _ControllerSubscription subscription =
-        new _ControllerSubscription(this, onData, onError, onDone,
-                                    cancelOnError);
+        new _ControllerSubscription<T>(this, onData, onError, onDone,
+                                       cancelOnError);
 
     _PendingEvents pendingEvents = _pendingEvents;
     _state |= _STATE_SUBSCRIBED;
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 19bdb69..c23b0f0 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -512,7 +512,7 @@
       bool cancelOnError) {
     if (_isUsed) throw new StateError("Stream has already been listened to.");
     _isUsed = true;
-    return new _BufferingStreamSubscription(
+    return new _BufferingStreamSubscription<T>(
         onData, onError, onDone, cancelOnError).._setPendingEvents(_pending());
   }
 }
diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart
index 03c75c1..97c449e 100644
--- a/sdk/lib/developer/developer.dart
+++ b/sdk/lib/developer/developer.dart
@@ -11,24 +11,42 @@
 ///
 library dart.developer;
 
+import 'dart:async';
 import 'dart:convert';
 
 part 'profiler.dart';
 
 /// If [when] is true, stop the program as if a breakpoint were hit at the
 /// following statement.
-/// 
-/// Returns the value of [when]. Some debuggers may
-/// display [msg].
-/// 
+///
+/// Returns the value of [when]. Some debuggers may display [message].
+///
 /// NOTE: When invoked, the isolate will not return until a debugger
 /// continues execution. When running in the Dart VM the behaviour is the same
 /// regardless of whether or not a debugger is connected. When compiled to
 /// JavaScript, this uses the "debugger" statement, and behaves exactly as
 /// that does.
-external bool debugger({bool when: true, String msg});
+external bool debugger({bool when: true, String message});
 
 /// Send a reference to [object] to any attached debuggers.
-/// 
+///
 /// Debuggers may open an inspector on the object. Returns the argument.
-external inspect(object);
+external Object inspect(Object object);
+
+/// Emit a log event.
+/// [message] is the log message.
+/// [time] (optional) is the timestamp.
+/// [sequenceNumber] (optional) is a monotonically increasing sequence number.
+/// [level] (optional) is the severity level (value between 0 and 2000).
+/// [name] (optional) is the name of the source of the log message.
+/// [zone] (optional) the zone where the log was emitted
+/// [error] (optional) an error object associated with this log event.
+/// [stackTrace] (optional) a stack trace associated with this log event.
+external log(String message,
+             {DateTime time,
+              int sequenceNumber,
+              int level: 0,
+              String name: '',
+              Zone zone,
+              Object error,
+              StackTrace stackTrace});
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index 78c15fa..89cd586 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -273,18 +273,7 @@
   }
 
   void write(Object obj) {
-    // This comment is copied from runtime/lib/string_buffer_patch.dart.
-    // TODO(srdjan): The following four lines could be replaced by
-    // '$obj', but apparently this is too slow on the Dart VM.
-    String string;
-    if (obj is String) {
-      string = obj;
-    } else {
-      string = obj.toString();
-      if (string is! String) {
-        throw new ArgumentError('toString() did not return a string');
-      }
-    }
+    String string = '$obj';
     if (string.isEmpty) return;
     add(_encoding.encode(string));
   }
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index 9ad7b56..56ddea0 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -53,9 +53,9 @@
  *       String os = Platform.operatingSystem;
  *       // Or, use a predicate getter.
  *       if (Platform.isMacOS) {
- *         Print('is a Mac');
+ *         print('is a Mac');
  *       } else {
- *        print('is not a Mac');
+ *         print('is not a Mac');
  *       }
  *     }
  *
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 9693873..cc68544 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -888,7 +888,7 @@
           if (_readyState == WebSocket.OPEN) {
             _readyState = WebSocket.CLOSING;
             if (!_isReservedStatusCode(transformer.closeCode)) {
-              _close(transformer.closeCode);
+              _close(transformer.closeCode, transformer.closeReason);
             } else {
               _close();
             }
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index f18e7f4..2e60ccc 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -13,6 +13,9 @@
 [ $runtime == vm || $runtime != vm ]
 # Tests that fail everywhere, including the analyzer.
 
+# No longer correct, y#$ now has a meaning. github.com/dart-lang/co19/issues/2
+Language/12_Expressions/30_Identifier_Reference_A01_t03: Skip
+
 LibTest/typed_data/ByteData/buffer_A01_t01: Fail # co19 r736 bug - sent comment.
 LayoutTests/fast/mediastream/getusermedia_t01: Fail # co19 issue 738.
 
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 59d8942c..3434fcf 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -101,75 +101,48 @@
 LibTest/typed_data/ByteData/*Int64*: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/*Uint64*: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/ByteData.view_A01_t02: fail # co19-roll r569: Please triage this failure
-LibTest/typed_data/ByteData/ByteData.view_A01_t02: fail # co19-roll r569: Please triage this failure
-LibTest/typed_data/ByteData/ByteData.view_A03_t01: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/ByteData.view_A03_t01: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/ByteData.view_A04_t01: fail # co19-roll r569: Please triage this failure
-LibTest/typed_data/ByteData/ByteData.view_A04_t01: fail # co19-roll r569: Please triage this failure
-LibTest/typed_data/ByteData/ByteData.view_A05_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/ByteData.view_A05_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/ByteData.view_A05_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/ByteData.view_A05_t02: fail # Issue 12989
 LibTest/typed_data/ByteData/ByteData.view_A05_t03: fail # Issue 12989
-LibTest/typed_data/ByteData/ByteData.view_A05_t03: fail # Issue 12989
-LibTest/typed_data/ByteData/ByteData_A01_t01: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/ByteData_A01_t01: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/ByteData_A02_t01: fail # co19-roll r576: Please triage this failure
 LibTest/typed_data/ByteData/getFloat32_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getFloat32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getFloat32_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getFloat64_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getFloat64_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getFloat64_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getInt16_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getInt16_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getInt16_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getInt32_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getInt32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getInt32_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getInt64_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getInt8_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getInt8_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getInt8_A02_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/getInt8_A02_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/getUint16_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getUint16_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getUint16_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getUint32_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getUint32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getUint32_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getUint64_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/getUint8_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/getUint8_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/getUint8_A02_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/getUint8_A02_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/setFloat32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setFloat32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setFloat32_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setFloat64_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setFloat64_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setFloat64_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setInt16_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setInt16_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setInt16_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setInt32_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setInt32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setInt32_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setInt64_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setInt8_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setInt8_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setInt8_A02_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/setInt8_A02_t02: fail # Issue 12989
-LibTest/typed_data/ByteData/setUint16_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setUint16_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setUint16_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setUint32_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setUint32_A02_t01: fail # Issue 12989
 LibTest/typed_data/ByteData/setUint32_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setUint64_A02_t02: fail # co19-roll r569: Please triage this failure
 LibTest/typed_data/ByteData/setUint8_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setUint8_A02_t01: fail # Issue 12989
-LibTest/typed_data/ByteData/setUint8_A02_t02: fail # Issue 12989
 LibTest/typed_data/ByteData/setUint8_A02_t02: fail # Issue 12989
 LibTest/typed_data/Float32List/Float32List.view_A05_t01: RuntimeError # co19-roll r559: Please triage this failure
 LibTest/typed_data/Float32List/Float32List.view_A05_t02: RuntimeError # co19-roll r559: Please triage this failure
@@ -235,6 +208,7 @@
 WebPlatformTest/dom/nodes/DOMImplementation-createHTMLDocument_t01: CompileTimeError # co19-roll r722: Please triage this failure.
 WebPlatformTest/dom/nodes/Document-createElement_t01: CompileTimeError # co19-roll r722: Please triage this failure.
 WebPlatformTest/dom/nodes/Element-childElementCount-nochild_t01: CompileTimeError # co19-roll r722: Please triage this failure.
+WebPlatformTest/webstorage/storage_session_setitem_quotaexceedederr_t01: Pass, Slow
 LayoutTests/fast/loader/loadInProgress_t01: Skip # Issue 23466
 LayoutTests/fast/dom/css-innerHTML_t01: SkipByDesign # Test is incorrect.
 
@@ -459,7 +433,6 @@
 LayoutTests/fast/url/scheme_t01: RuntimeError
 LayoutTests/fast/url/host-lowercase-per-scheme_t01: RuntimeError
 LayoutTests/fast/url/safari-extension_t01: RuntimeError
-LayoutTests/fast/url/safari-extension_t01: RuntimeError
 LayoutTests/fast/url/port_t01: RuntimeError
 LayoutTests/fast/url/mailto_t01: RuntimeError
 LayoutTests/fast/url/path-url_t01: RuntimeError
@@ -557,7 +530,6 @@
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Please triage this failure.
 Language/12_Expressions/05_Strings_A06_t01: Pass, Slow # Please triage this failure.
-Language/12_Expressions/05_Strings_A06_t01: Pass, Slow # Please triage this failure.
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 22200.
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 22200.
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Issue 22200.
@@ -714,13 +686,22 @@
 LayoutTests/fast/css/add-remove-stylesheets-at-once-minimal-recalc-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/aspect-ratio-inheritance_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/aspect-ratio-parsing-tests_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/css/auto-min-size_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/checked-pseudo-selector_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/collapsed-whitespace-reattach-in-style-recalc_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/content-language-case-insensitivity_t01: RuntimeError # Issue 23506
+LayoutTests/fast/css/content-language-dynamically-added_t01: RuntimeError # Issue 23506
+LayoutTests/fast/css/content-language-dynamically-removed_t01: RuntimeError # Issue 23506
+LayoutTests/fast/css/content-language-mapped-to-webkit-locale_t01: RuntimeError # Issue 23506
+LayoutTests/fast/css/content-language-multiple_t01: RuntimeError # Issue 23506
+LayoutTests/fast/css/content-language-no-content_t01: RuntimeError # Issue 23506
 LayoutTests/fast/css/content/content-none_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-normal_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/counters/complex-before_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/counters/counter-cssText_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/css-properties-case-insensitive_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/css3-nth-tokens-style_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/cssText-shorthand_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/csstext-of-content-string_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/cursor-parsing-quirks_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/deprecated-flexbox-auto-min-size_t01: RuntimeError # Please triage this failure
@@ -734,9 +715,13 @@
 LayoutTests/fast/css/font-face-unicode-range-overlap-load_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/fontfaceset-events_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/fontfaceset-loadingdone_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/css/getComputedStyle/computed-style-properties_t01: RuntimeError # Issue 23506
+LayoutTests/fast/css/getComputedStyle/counterIncrement-without-counter_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/html-attr-case-sensitivity_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/id-or-class-before-stylesheet_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/image-set-setting_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/css/important-js-override_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/inherit-initial-shorthand-values_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-predefined-color_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/link-alternate-stylesheet-1_t01: RuntimeError # Please triage this failure
@@ -746,9 +731,13 @@
 LayoutTests/fast/css/link-alternate-stylesheet-5_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/media-query-recovery_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/modify-ua-rules-from-javascript_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/nested-at-rules_t01: RuntimeError # Issue 23506
 LayoutTests/fast/css/parsing-at-rule-recovery_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/parsing-css-allowed-string-characters_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/parsing-css-nth-child_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/parsing-page-rule_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/parsing-selector-error-recovery_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/parsing-text-rendering_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/pseudo-any_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/pseudo-target-indirect-sibling-001_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/pseudo-target-indirect-sibling-002_t01: Skip # Times out. Please triage this failure
@@ -760,6 +749,7 @@
 LayoutTests/fast/css/readonly-pseudoclass-opera-005_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shadow-current-color_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/sticky/parsing-position-sticky_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/string-quote-binary_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/style-element-process-crash_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/style-scoped/style-scoped-nested_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/style-scoped/style-scoped-with-dom-operation_t01: RuntimeError # Please triage this failure
@@ -855,9 +845,11 @@
 LayoutTests/fast/dom/Window/window-scroll-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/anchor-without-content_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/attribute-namespaces-get-set_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/background-shorthand-csstext_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/blur-contenteditable_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/document-register-svg-extends_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/element-names_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/dataset-xhtml_t01: RuntimeError # Please triage this failure
@@ -877,6 +869,7 @@
 LayoutTests/fast/dom/option-properties_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/partial-layout-overlay-scrollbars_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/set-innerHTML_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/content-reprojection-fallback-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/no-renderers-for-light-children_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/pseudoclass-update-checked-option_t01: RuntimeError # Please triage this failure
@@ -887,6 +880,7 @@
 LayoutTests/fast/dom/shadow/shadow-content-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-disable_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-removechild-and-blur-event_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/shadow-root-js-api_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadowhost-keyframes_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadowroot-keyframes_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dynamic/crash-generated-counter_t01: RuntimeError # Please triage this failure
@@ -969,6 +963,7 @@
 LayoutTests/fast/forms/setrangetext_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textarea-paste-newline_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textfield-focus-out_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/forms/validationMessage_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/html/hidden-attr_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/html/imports/import-element-removed-flag_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/html/imports/import-events_t01: RuntimeError # Please triage this failure
@@ -979,6 +974,7 @@
 LayoutTests/fast/inline/out-of-flow-objects-and-whitespace-after-empty-inline_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/inline/parent-inline-element-padding-contributes-width_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/inline/positioned-element-padding-contributes-width_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/innerHTML/javascript-url_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/layers/normal-flow-hit-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/layers/zindex-hit-test_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/loader/about-blank-hash-change_t01: Skip # Times out. Please triage this failure
@@ -1213,7 +1209,6 @@
 LibTest/html/Node/parent_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Node/previousNode_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Window/animationFrame_A01_t01: Skip # Times out. Please triage this failure
-LibTest/html/Window/close_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Window/document_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Window/find_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Window/find_A03_t01: RuntimeError # Please triage this failure
@@ -1283,11 +1278,13 @@
 WebPlatformTest/html/dom/elements/global-attributes/dataset-set_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/document-metadata/styling/LinkStyle_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/error-codes/error_t01: Skip # Times out. Please triage this failure
+WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/attributes-common-to-form-controls/formaction_t01: RuntimeError # Please triage this failure
+WebPlatformTest/html/semantics/forms/textfieldselection/selection_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/textfieldselection/textfieldselection-setRangeText_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/the-button-element/button-validation_t01: RuntimeError # Please triage this failure
@@ -1309,6 +1306,7 @@
 WebPlatformTest/html/semantics/forms/the-input-element/time_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/the-input-element/time_t02: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/the-input-element/type-change-state_t01: RuntimeError # Please triage this failure
+WebPlatformTest/html/semantics/forms/the-input-element/url_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/the-input-element/valueMode_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/the-input-element/week_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/the-meter-element/meter_t01: RuntimeError # Please triage this failure
@@ -1346,6 +1344,9 @@
 WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-004_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-004_t02: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/elements-and-dom-objects/the-content-html-element/test-004_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/elements-and-dom-objects/the-content-html-element/test-004_t02: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/elements-and-dom-objects/the-content-html-element/test-006_t01: RuntimeError # Please triage this failure
@@ -1372,6 +1373,7 @@
 WebPlatformTest/shadow-dom/shadow-trees/distributed-pseudo-element/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/distributed-pseudo-element/test-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-004_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_constructor_t01: RuntimeError # Please triage this failure
@@ -1379,7 +1381,6 @@
 WebPlatformTest/webstorage/storage_local_setitem_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/storage_session_setitem_t01: RuntimeError # Please triage this failure
 
-
 [ $compiler == dart2js && $runtime == chrome && $checked ]
 LayoutTests/fast/css-intrinsic-dimensions/css-tables_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-absolutes_t01: RuntimeError # Please triage this failure
@@ -1451,36 +1452,17 @@
 WebPlatformTest/html/semantics/forms/textfieldselection/selection_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001_t01: RuntimeError # Please triage this failure
 
-[ $compiler == dart2js && $runtime == chrome && ($system == windows || $system == macos) ]
-# New failures on Chrome 43, linux bots are not yet at that version.
-LayoutTests/fast/css/content-language-case-insensitivity_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/content-language-dynamically-removed_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/content-language-dynamically-added_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/content-language-no-content_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/content-language-multiple_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/content-language-mapped-to-webkit-locale_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/getComputedStyle/computed-style-properties_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/nested-at-rules_t01: RuntimeError # Issue 23506
-LayoutTests/fast/css/getComputedStyle/counterIncrement-without-counter_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/image-set-setting_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/parsing-text-rendering_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/cssText-shorthand_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/background-shorthand-csstext_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/innerHTML/javascript-url_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/forms/textfieldselection/selection_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/forms/the-input-element/url_t01: RuntimeError # Please triage this failure
-WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001_t01: RuntimeError # Please triage this failure
-
 [ $compiler == dart2js && $runtime == chrome && $system == macos ]
 LayoutTests/fast/canvas/webgl/canvas-test_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/dom/MutationObserver/observe-attributes_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-different-writing-modes-left_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-rounded-boxes_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/text/glyph-reordering_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/text/line-break-after-question-mark_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/text/text-combine-shrink-to-fit_t01: RuntimeError # Please triage this failure
+LibTest/async/Timer/Timer.periodic_A01_t01: Skip # Times out. Please triage this failure
 
 [ $compiler == dart2js && $runtime == chrome && $system != macos ]
 LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Please triage this failure
@@ -3081,7 +3063,7 @@
 WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-011_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_constructor_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_constructor_t02: RuntimeError # Please triage this failure
-WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Times out. Please triage this failure
+WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Times out. Please triage this failure. Note that Chrome also requires the Slow flag. (Could just be a slow test).
 WebPlatformTest/webstorage/storage_local_setitem_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/storage_session_setitem_quotaexceedederr_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/webstorage/storage_session_setitem_t01: RuntimeError # Please triage this failure
@@ -9071,6 +9053,7 @@
 LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-before-open_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-sync-request_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xmlhttprequest/xmlhttprequest-set-responsetype_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/xmlhttprequest/xmlhttprequest-withcredentials-before-open_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/4XPath/Borrowed/cz_20030217_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/4XPath/Borrowed/kd_20010423_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/4XPath/Borrowed/namespace-nodes_t01: RuntimeError # Please triage this failure
@@ -9275,6 +9258,7 @@
 LibTest/html/Window/resizeTo_A01_t01: RuntimeError # Please triage this failure
 LibTest/math/sqrt_A02_t02: Skip # Times out. Please triage this failure
 LibTest/typed_data/ByteData/ByteData.view_A01_t01: Pass, RuntimeError # Please triage this failure
+LibTest/typed_data/ByteData/offsetInBytes_A01_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/Float32List/removeWhere_A01_t01: Skip # Times out. Please triage this failure
 LibTest/typed_data/Float32x4List/Float32x4List.view_A06_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/Int32List/lastWhere_A01_t01: Skip # Times out. Please triage this failure
@@ -9600,9 +9584,8 @@
 Language/13_Statements/12_Labels_A03_t04: Crash # (switch (i){L:case 0:flag=true;break;case 2:continue L;}): continue to a labeled switch case
 Language/13_Statements/14_Continue_A02_t12: Crash # (switch (2){L:case 1:flag=true;break;case 2:continue L;}): continue to a labeled switch case
 Language/13_Statements/14_Continue_A02_t13: Crash # (switch (2){case 2:continue L;L:case 1:flag=true;}): continue to a labeled switch case
+Language/15_Types/4_Interface_Types_A12_t09: RuntimeError # Please triage this failure.
 LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: Crash # (lazy.method()): deferred access is not implemented
-LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Stack Overflow
-LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Stack Overflow
 LibTest/core/Invocation/isAccessor_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/isGetter_A01_t01: RuntimeError # Please triage this failure.
 LibTest/core/Invocation/isGetter_A01_t02: RuntimeError # Please triage this failure.
@@ -9612,7 +9595,6 @@
 LibTest/core/Invocation/memberName_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # Please triage this failure.
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # Please triage this failure.
-LibTest/core/List/List_class_A01_t02: Crash # Stack Overflow
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Please triage this failure.
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Please triage this failure.
 LibTest/core/double/INFINITY_A01_t04: Pass # Please triage this failure.
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
index 7636eb2..3ed51d4 100644
--- a/tests/compiler/dart2js/analyze_helper.dart
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -96,10 +96,10 @@
   }
 
   @override
-  void report(Uri uri, int begin, int end, String message,
+  void report(Message message, Uri uri, int begin, int end, String text,
               api.Diagnostic kind) {
     if (kind == api.Diagnostic.WARNING) {
-      if (checkWhiteList(uri, message)) {
+      if (checkWhiteList(uri, text)) {
         // Suppress whitelisted warnings.
         lastWasWhitelisted = true;
         return;
@@ -107,7 +107,7 @@
       hasWarnings = true;
     }
     if (kind == api.Diagnostic.HINT) {
-      if (checkWhiteList(uri, message)) {
+      if (checkWhiteList(uri, text)) {
         // Suppress whitelisted hints.
         lastWasWhitelisted = true;
         return;
@@ -115,7 +115,7 @@
       hasHint = true;
     }
     if (kind == api.Diagnostic.ERROR) {
-      if (checkWhiteList(uri, message)) {
+      if (checkWhiteList(uri, text)) {
         // Suppress whitelisted errors.
         lastWasWhitelisted = true;
         return;
@@ -126,7 +126,7 @@
       return;
     }
     lastWasWhitelisted = false;
-    super.report(uri, begin, end, message, kind);
+    super.report(message, uri, begin, end, text, kind);
   }
 }
 
diff --git a/tests/compiler/dart2js/analyze_only_test.dart b/tests/compiler/dart2js/analyze_only_test.dart
index 785d3f8..ff28085 100644
--- a/tests/compiler/dart2js/analyze_only_test.dart
+++ b/tests/compiler/dart2js/analyze_only_test.dart
@@ -12,8 +12,8 @@
 import '../../utils/dummy_compiler_test.dart' as dummy;
 import 'package:compiler/compiler.dart';
 
-import 'package:compiler/src/dart2jslib.dart' show
-    MessageKind;
+import 'package:compiler/src/warnings.dart' show
+    MessageKind, MessageTemplate;
 
 import 'output_collector.dart';
 
@@ -68,8 +68,10 @@
     (String code, List errors, List warnings) {
       Expect.isNotNull(code);
       Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
+      MessageTemplate template =
+          MessageTemplate.TEMPLATES[MessageKind.MISSING_MAIN];
       Expect.equals(
-          "${MessageKind.MISSING_MAIN.message({'main': 'main'})}",
+          "${template.message({'main': 'main'})}",
           warnings.single);
     });
 
@@ -88,8 +90,10 @@
     (String code, List errors, List warnings) {
       Expect.isNull(code);
       Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
+      MessageTemplate template =
+          MessageTemplate.TEMPLATES[MessageKind.CONSIDER_ANALYZE_ALL];
       Expect.equals(
-          "${MessageKind.CONSIDER_ANALYZE_ALL.message({'main': 'main'})}",
+          "${template.message({'main': 'main'})}",
           warnings.single);
     });
 
@@ -108,8 +112,10 @@
     (String code, List errors, List warnings) {
       Expect.isNull(code);
       Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
+      MessageTemplate template =
+          MessageTemplate.TEMPLATES[MessageKind.CONSIDER_ANALYZE_ALL];
       Expect.equals(
-          "${MessageKind.CONSIDER_ANALYZE_ALL.message({'main': 'main'})}",
+          "${template.message({'main': 'main'})}",
           warnings.single);
     });
 
diff --git a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
index db3923a..dc2aeef 100644
--- a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
+++ b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
@@ -47,6 +47,10 @@
     "accept", "FunctionExpression", "CreateFunction"
   ],
 
+  "lib/src/universe/universe.dart": const [
+      "The method 'getterInvocationsByName' is never called.",
+      "The method 'setterInvocationsByName' is never called."],
+
   "lib/src/cps_ir/": const [
     "accept", "CreateFunction",
   ],
diff --git a/tests/compiler/dart2js/array_tracing_mirror_test.dart b/tests/compiler/dart2js/array_tracing_mirror_test.dart
index fe5324c..2c4c9aa 100644
--- a/tests/compiler/dart2js/array_tracing_mirror_test.dart
+++ b/tests/compiler/dart2js/array_tracing_mirror_test.dart
@@ -31,11 +31,12 @@
 };
 
 main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);  
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    var compiler = result.compiler;
     var element = compiler.mainApp.findExported('main');
     var code = compiler.backend.assembleCode(element);
     Expect.isTrue(code.contains('return 2'));
-  }));
+  });
 }
 
diff --git a/tests/compiler/dart2js/bad_output_io_test.dart b/tests/compiler/dart2js/bad_output_io_test.dart
index ad2b0b9..7815b59 100644
--- a/tests/compiler/dart2js/bad_output_io_test.dart
+++ b/tests/compiler/dart2js/bad_output_io_test.dart
@@ -38,13 +38,13 @@
   }
 
   @override
-  void report(Uri uri, int begin, int end, String message, kind) {
+  void report(var code, Uri uri, int begin, int end, String message, kind) {
     messages.add([message, kind]);
   }
 
   @override
   void call(Uri uri, int begin, int end, String message, kind) {
-    report(uri, begin, end, message, kind);
+    report(null, uri, begin, end, message, kind);
   }
 
   String prefixMessage(String message, Diagnostic kind) {
diff --git a/tests/compiler/dart2js/check_elements_invariants_test.dart b/tests/compiler/dart2js/check_elements_invariants_test.dart
index 471cee4..bc1314f 100644
--- a/tests/compiler/dart2js/check_elements_invariants_test.dart
+++ b/tests/compiler/dart2js/check_elements_invariants_test.dart
@@ -3,13 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/apiimpl.dart';
 import 'package:expect/expect.dart';
 import 'package:compiler/src/elements/elements.dart'
     show ClassElement;
 import 'package:compiler/src/resolution/class_members.dart'
     show ClassMemberMixin;
-import "package:async_helper/async_helper.dart";
 import 'memory_compiler.dart';
 
 
@@ -32,13 +32,12 @@
       "Not all members have been computed for $cls.");
 }
 
-Future checkElementInvariantsAfterCompiling(Uri uri) {
-  var compiler = compilerFor({}, options: DART2JS_OPTIONS);
-   return compiler.run(uri).then((passed) {
-     Expect.isTrue(passed, "Compilation of dart2js failed.");
+Future checkElementInvariantsAfterCompiling(Uri uri) async {
+  CompilationResult result =
+      await runCompiler(entryPoint: uri, options: DART2JS_OPTIONS);
+  Expect.isTrue(result.isSuccess, "Compilation of dart2js failed.");
 
-     computeLiveClasses(compiler).forEach(checkClassInvariants);
-   });
+  computeLiveClasses(result.compiler).forEach(checkClassInvariants);
 }
 
 void main () {
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
new file mode 100644
index 0000000..cd8abdd
--- /dev/null
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -0,0 +1,324 @@
+// 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.
+
+// Test for iterators on for [SubclassNode].
+
+library world_test;
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'type_test_helper.dart';
+import 'package:compiler/src/elements/elements.dart'
+       show Element, ClassElement;
+import 'package:compiler/src/dart2jslib.dart';
+import 'package:compiler/src/universe/class_set.dart';
+import 'package:compiler/src/util/util.dart';
+
+void main() {
+  asyncTest(() => TypeEnvironment.create(r"""
+      ///        A
+      ///       / \
+      ///      B   C
+      ///     /   /|\
+      ///    D   E F G
+      ///
+      class A {}
+      class B extends A {}
+      class C extends A {}
+      class D extends B {}
+      class E extends C {}
+      class F extends C {}
+      class G extends C {}
+      """,
+        mainSource: r"""
+      main() {
+        new A();
+        new C();
+        new D();
+        new E();
+        new F();
+        new G();
+      }
+      """,
+      useMockCompiler: false).then((env) {
+    World world = env.compiler.world;
+
+    ClassElement A = env.getElement("A");
+    ClassElement B = env.getElement("B");
+    ClassElement C = env.getElement("C");
+    ClassElement D = env.getElement("D");
+    ClassElement E = env.getElement("E");
+    ClassElement F = env.getElement("F");
+    ClassElement G = env.getElement("G");
+
+    void checkClass(ClassElement cls,
+                    {bool directlyInstantiated: false,
+                     bool indirectlyInstantiated: false}) {
+      ClassHierarchyNode node = world.classHierarchyNode(cls);
+      Expect.isNotNull(node, "Expected ClassHierarchyNode for $cls.");
+      Expect.equals(
+          directlyInstantiated || indirectlyInstantiated,
+          node.isInstantiated,
+          "Unexpected `isInstantiated` on ClassHierarchyNode for $cls.");
+      Expect.equals(
+          directlyInstantiated,
+          node.isDirectlyInstantiated,
+          "Unexpected `isDirectlyInstantiated` on ClassHierarchyNode for "
+          "$cls.");
+      Expect.equals(
+          indirectlyInstantiated,
+          node.isIndirectlyInstantiated,
+          "Unexpected `isIndirectlyInstantiated` on ClassHierarchyNode for "
+          "$cls.");
+    }
+
+
+    checkClass(A, directlyInstantiated: true, indirectlyInstantiated: true);
+    checkClass(B, indirectlyInstantiated: true);
+    checkClass(C, directlyInstantiated: true, indirectlyInstantiated: true);
+    checkClass(D, directlyInstantiated: true);
+    checkClass(E, directlyInstantiated: true);
+    checkClass(F, directlyInstantiated: true);
+    checkClass(G, directlyInstantiated: true);
+
+    ClassHierarchyNodeIterator iterator;
+
+    void checkState(
+        ClassElement root,
+        {ClassElement currentNode,
+         List<List<ClassElement>> stack}) {
+
+      ClassElement classOf(ClassHierarchyNode node) {
+        return node != null ? node.cls : null;
+      }
+
+      List<ClassElement> classesOf(Link<ClassHierarchyNode> link) {
+        if (link == null) return null;
+        return link.map(classOf).toList();
+      }
+
+      ClassElement foundRoot = iterator.root.cls;
+      ClassElement foundCurrentNode = classOf(iterator.currentNode);
+      List<ClassElement> foundStack = classesOf(iterator.stack);
+
+      StringBuffer sb = new StringBuffer();
+      sb.write('{\n root: $foundRoot');
+      sb.write('\n currentNode: $foundCurrentNode');
+      sb.write('\n stack: $foundStack\n}');
+
+      Expect.equals(root, foundRoot,
+          "Expected root $root in $sb.");
+      if (currentNode == null) {
+        Expect.isNull(iterator.currentNode,
+            "Unexpected non-null currentNode in $sb.");
+      } else {
+        Expect.isNotNull(foundCurrentNode,
+            "Expected non-null currentNode ${currentNode} in $sb.");
+        Expect.equals(currentNode, foundCurrentNode,
+            "Expected currentNode $currentNode in $sb.");
+      }
+      if (stack == null) {
+        Expect.isNull(foundStack,
+            "Unexpected non-null stack in $sb.");
+      } else {
+        Expect.isNotNull(foundStack,
+            "Expected non-null stack ${stack} in $sb.");
+        Expect.listEquals(stack, foundStack,
+            "Expected stack ${stack}, "
+            "found ${foundStack} in $sb.");
+      }
+    }
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(G)).iterator;
+    checkState(G, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(G, currentNode: G, stack: []);
+    Expect.equals(G, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(G, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(G), includeRoot: false).iterator;
+    checkState(G, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(G, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(C)).iterator;
+    checkState(C, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(C, currentNode: C, stack: [E, F, G]);
+    Expect.equals(C, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(C, currentNode: E, stack: [F, G]);
+    Expect.equals(E, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(C, currentNode: F, stack: [G]);
+    Expect.equals(F, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(C, currentNode: G, stack: []);
+    Expect.equals(G, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(C, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(D)).iterator;
+    checkState(D, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(D, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(D, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(B)).iterator;
+    checkState(B, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(B, currentNode: B, stack: [D]);
+    Expect.equals(B, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(B, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(B, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(B), includeRoot: false).iterator;
+    checkState(B, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(B, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(B, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(B), directlyInstantiatedOnly: true).iterator;
+    checkState(B, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(B, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(B, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(A)).iterator;
+    checkState(A, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: A, stack: [C, B]);
+    Expect.equals(A, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: C, stack: [E, F, G, B]);
+    Expect.equals(C, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: E, stack: [F, G, B]);
+    Expect.equals(E, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: F, stack: [G, B]);
+    Expect.equals(F, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: G, stack: [B]);
+    Expect.equals(G, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: B, stack: [D]);
+    Expect.equals(B, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(A, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(A), includeRoot: false).iterator;
+    checkState(A, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: C, stack: [E, F, G, B]);
+    Expect.equals(C, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: E, stack: [F, G, B]);
+    Expect.equals(E, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: F, stack: [G, B]);
+    Expect.equals(F, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: G, stack: [B]);
+    Expect.equals(G, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: B, stack: [D]);
+    Expect.equals(B, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(A, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(A), directlyInstantiatedOnly: true).iterator;
+    checkState(A, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: A, stack: [C, B]);
+    Expect.equals(A, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: C, stack: [E, F, G, B]);
+    Expect.equals(C, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: E, stack: [F, G, B]);
+    Expect.equals(E, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: F, stack: [G, B]);
+    Expect.equals(F, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: G, stack: [B]);
+    Expect.equals(G, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(A, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+
+    iterator = new ClassHierarchyNodeIterable(
+        world.classHierarchyNode(A),
+        includeRoot: false, directlyInstantiatedOnly: true).iterator;
+    checkState(A, currentNode: null, stack: null);
+    Expect.isNull(iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: C, stack: [E, F, G, B]);
+    Expect.equals(C, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: E, stack: [F, G, B]);
+    Expect.equals(E, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: F, stack: [G, B]);
+    Expect.equals(F, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: G, stack: [B]);
+    Expect.equals(G, iterator.current);
+    Expect.isTrue(iterator.moveNext());
+    checkState(A, currentNode: D, stack: []);
+    Expect.equals(D, iterator.current);
+    Expect.isFalse(iterator.moveNext());
+    checkState(A, currentNode: null, stack: []);
+    Expect.isNull(iterator.current);
+  }));
+}
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 90dd441..ce972e5 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -22,6 +22,7 @@
        show Constant,
             Message,
             MessageKind,
+            MessageTemplate,
             Selector,
             TypedSelector,
             SourceSpan,
diff --git a/tests/compiler/dart2js/compiler_test.dart b/tests/compiler/dart2js/compiler_test.dart
index 581489c..6e16da6 100644
--- a/tests/compiler/dart2js/compiler_test.dart
+++ b/tests/compiler/dart2js/compiler_test.dart
@@ -25,7 +25,8 @@
                      MessageKind messageKind,
                      [Map arguments = const {}]) {
     if (onWarning != null) {
-      onWarning(this, node, messageKind.message(arguments));
+      MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
+      onWarning(this, node, template.message(arguments));
     }
     super.reportWarning(node, messageKind, arguments);
   }
@@ -34,7 +35,8 @@
                    MessageKind messageKind,
                    [Map arguments = const {}]) {
     if (onError != null) {
-      onError(this, node, messageKind.message(arguments));
+      MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
+      onError(this, node, template.message(arguments));
     }
     super.reportError(node, messageKind, arguments);
   }
diff --git a/tests/compiler/dart2js/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
index 94a0213e..fba3a20 100644
--- a/tests/compiler/dart2js/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
@@ -10,7 +10,6 @@
 import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/constant_system_dart.dart';
-import 'package:compiler/src/core_types.dart';
 import 'package:compiler/src/dart2jslib.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'memory_compiler.dart';
@@ -204,7 +203,7 @@
   asyncTest(() => Future.forEach(DATA, testData));
 }
 
-Future testData(TestData data) {
+Future testData(TestData data) async {
   StringBuffer sb = new StringBuffer();
   sb.write('${data.declarations}\n');
   Map constants = {};
@@ -215,23 +214,22 @@
   });
   sb.write('main() {}\n');
   String source = sb.toString();
-  Compiler compiler = compilerFor(
-      {'main.dart': source}, options: ['--analyze-all']);
-  return compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
-    var library = compiler.mainApp;
-    constants.forEach((String name, ConstantData data) {
-      FieldElement field = library.localLookup(name);
-      ConstantExpression constant = field.constant;
-      data.expectedValues.forEach(
-          (Map<String, String> env, String expectedText) {
-        Environment environment = new MemoryEnvironment(compiler, env);
-        ConstantValue value =
-            constant.evaluate(environment, DART_CONSTANT_SYSTEM);
-        String valueText = value.toStructuredString();
-        Expect.equals(expectedText, valueText,
-            "Unexpected value '${valueText}' for contant "
-            "`${constant.getText()}`, expected '${expectedText}'.");
-      });
+  CompilationResult result = await runCompiler(
+      memorySourceFiles: {'main.dart': source}, options: ['--analyze-all']);
+  Compiler compiler = result.compiler;
+  var library = compiler.mainApp;
+  constants.forEach((String name, ConstantData data) {
+    FieldElement field = library.localLookup(name);
+    ConstantExpression constant = field.constant;
+    data.expectedValues.forEach(
+        (Map<String, String> env, String expectedText) {
+      Environment environment = new MemoryEnvironment(compiler, env);
+      ConstantValue value =
+          constant.evaluate(environment, DART_CONSTANT_SYSTEM);
+      String valueText = value.toStructuredString();
+      Expect.equals(expectedText, valueText,
+          "Unexpected value '${valueText}' for contant "
+          "`${constant.getText()}`, expected '${expectedText}'.");
     });
   });
 }
diff --git a/tests/compiler/dart2js/constant_expression_test.dart b/tests/compiler/dart2js/constant_expression_test.dart
index d4e9df0..166a0ae 100644
--- a/tests/compiler/dart2js/constant_expression_test.dart
+++ b/tests/compiler/dart2js/constant_expression_test.dart
@@ -197,7 +197,7 @@
   asyncTest(() => Future.forEach(DATA, testData));
 }
 
-Future testData(TestData data) {
+Future testData(TestData data) async {
   StringBuffer sb = new StringBuffer();
   sb.write('${data.declarations}\n');
   Map constants = {};
@@ -208,39 +208,39 @@
   });
   sb.write('main() {}\n');
   String source = sb.toString();
-  Compiler compiler = compilerFor(
-      {'main.dart': source}, options: ['--analyze-all']);
-  return compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
-    var library = compiler.mainApp;
-    constants.forEach((String name, ConstantData data) {
-      FieldElement field = library.localLookup(name);
-      var constant = field.constant;
-      Expect.equals(data.kind, constant.kind,
-          "Unexpected kind '${constant.kind}' for contant "
-          "`${constant.getText()}`, expected '${data.kind}'.");
-      Expect.equals(data.text, constant.getText(),
-          "Unexpected text '${constant.getText()}' for contant, "
-          "expected '${data.text}'.");
-      if (data.type != null) {
-        String instanceType = constant.computeInstanceType().toString();
-        Expect.equals(data.type, instanceType,
-            "Unexpected type '$instanceType' for contant "
-            "`${constant.getText()}`, expected '${data.type}'.");
-      }
-      if (data.fields != null) {
-        Map instanceFields = constant.computeInstanceFields();
-        Expect.equals(data.fields.length, instanceFields.length,
-            "Unexpected field count ${instanceFields.length} for contant "
-            "`${constant.getText()}`, expected '${data.fields.length}'.");
-        instanceFields.forEach((field, expression) {
-          String name = '$field';
-          String expression = instanceFields[field].getText();
-          String expected = data.fields[name];
-          Expect.equals(expected, expression,
-              "Unexpected field expression ${expression} for field '$name' in "
-              "contant `${constant.getText()}`, expected '${expected}'.");
-        });
-      }
-    });
+  CompilationResult result = await runCompiler(
+      memorySourceFiles: {'main.dart': source},
+      options: ['--analyze-all']);
+  Compiler compiler = result.compiler;
+  var library = compiler.mainApp;
+  constants.forEach((String name, ConstantData data) {
+    FieldElement field = library.localLookup(name);
+    var constant = field.constant;
+    Expect.equals(data.kind, constant.kind,
+        "Unexpected kind '${constant.kind}' for contant "
+        "`${constant.getText()}`, expected '${data.kind}'.");
+    Expect.equals(data.text, constant.getText(),
+        "Unexpected text '${constant.getText()}' for contant, "
+        "expected '${data.text}'.");
+    if (data.type != null) {
+      String instanceType = constant.computeInstanceType().toString();
+      Expect.equals(data.type, instanceType,
+          "Unexpected type '$instanceType' for contant "
+          "`${constant.getText()}`, expected '${data.type}'.");
+    }
+    if (data.fields != null) {
+      Map instanceFields = constant.computeInstanceFields();
+      Expect.equals(data.fields.length, instanceFields.length,
+          "Unexpected field count ${instanceFields.length} for contant "
+          "`${constant.getText()}`, expected '${data.fields.length}'.");
+      instanceFields.forEach((field, expression) {
+        String name = '$field';
+        String expression = instanceFields[field].getText();
+        String expected = data.fields[name];
+        Expect.equals(expected, expression,
+            "Unexpected field expression ${expression} for field '$name' in "
+            "contant `${constant.getText()}`, expected '${expected}'.");
+      });
+    }
   });
 }
diff --git a/tests/compiler/dart2js/container_mask_equal_test.dart b/tests/compiler/dart2js/container_mask_equal_test.dart
index 28a7645..96834e9 100644
--- a/tests/compiler/dart2js/container_mask_equal_test.dart
+++ b/tests/compiler/dart2js/container_mask_equal_test.dart
@@ -27,8 +27,9 @@
 };
 
 main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    var compiler = result.compiler;
     var typesInferrer = compiler.typesTask.typesInferrer;
 
     var element = compiler.mainApp.find('a');
@@ -45,5 +46,5 @@
 
     Expect.notEquals(mask1.union(mask2, compiler.world),
                      mask3.union(mask4, compiler.world));
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/deferred_custom_element_test.dart b/tests/compiler/dart2js/deferred_custom_element_test.dart
index 1fa5d12..b1f1b3e 100644
--- a/tests/compiler/dart2js/deferred_custom_element_test.dart
+++ b/tests/compiler/dart2js/deferred_custom_element_test.dart
@@ -12,8 +12,10 @@
 import 'memory_compiler.dart';
 
 void main() {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    Compiler compiler = result.compiler;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
     var lib =
@@ -23,7 +25,7 @@
     Expect.notEquals(mainOutputUnit, outputUnitForElement(foo));
     // Native elements are not deferred
     Expect.equals(mainOutputUnit, outputUnitForElement(customType));
-  }));
+  });
 }
 
 // The main library imports a file defining a custom element.
diff --git a/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart b/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart
index 0cbcc0b..fa9753e 100644
--- a/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart
+++ b/tests/compiler/dart2js/deferred_dont_inline_deferred_constants_test.dart
@@ -12,11 +12,13 @@
 import 'output_collector.dart';
 
 void main() {
-  OutputCollector collector = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  asyncTest(() async {
+    OutputCollector collector = new OutputCollector();
+    CompilationResult result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       outputProvider: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+    Compiler compiler = result.compiler;
+
     lookupLibrary(name) {
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
@@ -78,7 +80,7 @@
     Expect.isTrue(new RegExp(r"= .string4").hasMatch(lib1Output));
     Expect.isTrue(new RegExp(r"= .string4").hasMatch(lib2Output));
     Expect.isFalse(new RegExp(r"= .string4").hasMatch(lib12Output));
-  }));
+  });
 }
 
 // Make sure that deferred constants are not inlined into the main hunk.
diff --git a/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart b/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart
index 4f516e4..1a85a12 100644
--- a/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart
+++ b/tests/compiler/dart2js/deferred_dont_inline_deferred_globals_test.dart
@@ -13,10 +13,11 @@
 
 void main() {
   OutputCollector collector = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
-      outputProvider: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        outputProvider: collector);
+    Compiler compiler = result.compiler;
     lookupLibrary(name) {
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
@@ -40,7 +41,7 @@
     Expect.isTrue(re2.hasMatch(lib1Output));
     Expect.isFalse(re1.hasMatch(mainOutput));
     Expect.isFalse(re2.hasMatch(mainOutput));
-  }));
+  });
 }
 
 // Make sure that deferred constants are not inlined into the main hunk.
diff --git a/tests/compiler/dart2js/deferred_emit_type_checks_test.dart b/tests/compiler/dart2js/deferred_emit_type_checks_test.dart
index 3fe7752..2132fde 100644
--- a/tests/compiler/dart2js/deferred_emit_type_checks_test.dart
+++ b/tests/compiler/dart2js/deferred_emit_type_checks_test.dart
@@ -14,11 +14,12 @@
 import 'output_collector.dart';
 
 void main() {
-  OutputCollector collector = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
-      outputProvider: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    OutputCollector collector = new OutputCollector();
+    CompilationResult result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        outputProvider: collector);
+    Compiler compiler = result.compiler;
     String mainOutput = collector.getOutput('', 'js');
     String deferredOutput =  collector.getOutput('out_1', 'part.js');
     JavaScriptBackend backend = compiler.backend;
@@ -27,7 +28,7 @@
         "Deferred output doesn't contain '${isPrefix}A: 1':\n"
         "$deferredOutput");
     Expect.isFalse(mainOutput.contains('${isPrefix}A: 1'));
-  }));
+  });
 }
 
 // We force additional runtime type support to be output for A by instantiating
diff --git a/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart b/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
index e675f3f..7d2c686 100644
--- a/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
+++ b/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
@@ -11,8 +11,10 @@
 import 'memory_compiler.dart';
 
 void main() {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    Compiler compiler = result.compiler;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
     var outputUnitForConstant = compiler.deferredLoadTask.outputUnitForConstant;
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
@@ -35,7 +37,7 @@
       Expect.notEquals(null, outputUnitForConstant(constant));
       Expect.notEquals(mainOutputUnit, outputUnitForConstant(constant));
     }
-  }));
+  });
 }
 
 // The main library imports lib1 and lib2 deferred and use lib1.foo1 and
diff --git a/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart b/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart
index a300eba..acd0146 100644
--- a/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart
+++ b/tests/compiler/dart2js/deferred_follow_implicit_super_regression_test.dart
@@ -3,23 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
-import 'memory_source_file_helper.dart';
-import "memory_compiler.dart";
-import "dart:async";
+import 'package:async_helper/async_helper.dart';
+import 'memory_compiler.dart';
 
 import 'package:compiler/src/dart2jslib.dart'
        as dart2js;
 
-runTest(String mainScript, test) {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES,
-      outputProvider: new OutputCollector());
-  asyncTest(() => compiler.run(Uri.parse(mainScript))
-      .then((_) => test(compiler)));
-}
-
 void main() {
-  runTest('memory:main.dart', (compiler) {
+  asyncTest(() async {
+    CompilationResult  result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    dart2js.Compiler compiler = result.compiler;
+
     lookupLibrary(name) {
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
diff --git a/tests/compiler/dart2js/deferred_inline_restrictions_test.dart b/tests/compiler/dart2js/deferred_inline_restrictions_test.dart
index 7ae382b..a750587 100644
--- a/tests/compiler/dart2js/deferred_inline_restrictions_test.dart
+++ b/tests/compiler/dart2js/deferred_inline_restrictions_test.dart
@@ -9,14 +9,15 @@
 import 'package:compiler/src/dart2jslib.dart';
 import 'package:expect/expect.dart';
 import 'memory_compiler.dart';
-import 'output_collector.dart';
 
 void main() {
-  OutputCollector collector = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  asyncTest(() async {
+    OutputCollector collector = new OutputCollector();
+    CompilationResult result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       outputProvider: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+    Compiler compiler = result.compiler;
+
     lookupLibrary(name) {
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
@@ -57,7 +58,7 @@
     // Test that inlineSameContext was inlined into lib1.
     Expect.isFalse(re4.hasMatch(lib3Output));
     Expect.isTrue(re4.hasMatch(lib1Output));
-  }));
+  });
 }
 
 // Make sure that empty functions are inlined and that functions from
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart
index 3467d2c..0b79a13 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation2_test.dart
@@ -12,8 +12,10 @@
 import 'memory_compiler.dart';
 
 void main() {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    Compiler compiler = result.compiler;
     var outputUnitForElement = compiler.deferredLoadTask.outputUnitForElement;
     var mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
     var lib =
@@ -22,7 +24,7 @@
     var f2 = lib.find("f2");
     Expect.notEquals(mainOutputUnit, outputUnitForElement(f1));
     Expect.equals(mainOutputUnit, outputUnitForElement(f2));
-  }));
+  });
 }
 
 // The main library imports lib1 and lib2 deferred and use lib1.foo1 and
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index 59b39e3..1fa3534 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -13,8 +13,11 @@
 import 'memory_compiler.dart';
 
 void main() {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    Compiler compiler = result.compiler;
+
     lookupLibrary(name) {
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
@@ -66,7 +69,7 @@
     Expect.listEquals([ou_lib4_1], hunksLib4_1);
     Expect.listEquals([ou_lib4_2], hunksLib4_2);
     Expect.equals(hunksToLoad["main"], null);
-  }));
+  });
 }
 
 // The main library imports lib1 and lib2 deferred and use lib1.foo1 and
diff --git a/tests/compiler/dart2js/deferred_load_mapping_test.dart b/tests/compiler/dart2js/deferred_load_mapping_test.dart
index 6877f4f..4cb51d13 100644
--- a/tests/compiler/dart2js/deferred_load_mapping_test.dart
+++ b/tests/compiler/dart2js/deferred_load_mapping_test.dart
@@ -8,26 +8,26 @@
 import "memory_compiler.dart";
 
 void main() {
-  var collector = new OutputCollector();
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES,
-                                  options: ['--deferred-map=deferred_map.json'],
-                                  outputProvider: collector);
-  asyncTest(() {
-    return compiler.run(Uri.parse('memory:main.dart')).then((success) {
-      // Ensure a mapping file is output.
-      Expect.isNotNull(
-          collector.getOutput("deferred_map.json", "deferred_map"));
+  asyncTest(() async {
+    var collector = new OutputCollector();
+    CompilationResult result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        options: ['--deferred-map=deferred_map.json'],
+        outputProvider: collector);
+    Compiler compiler = result.compiler;
+    // Ensure a mapping file is output.
+    Expect.isNotNull(
+        collector.getOutput("deferred_map.json", "deferred_map"));
 
-      Map mapping = compiler.deferredLoadTask.computeDeferredMap();
-      // Test structure of mapping.
-      Expect.equals("<unnamed>", mapping["main.dart"]["name"]);
-      Expect.equals(2, mapping["main.dart"]["imports"]["lib1"].length);
-      Expect.equals(2, mapping["main.dart"]["imports"]["lib2"].length);
-      Expect.equals(1, mapping["main.dart"]["imports"]["convert"].length);
-      Expect.equals("lib1", mapping["memory:lib1.dart"]["name"]);
-      Expect.equals(1, mapping["memory:lib1.dart"]["imports"]["lib4_1"].length);
-      Expect.equals(1, mapping["memory:lib2.dart"]["imports"]["lib4_2"].length);
-    });
+    Map mapping = compiler.deferredLoadTask.computeDeferredMap();
+    // Test structure of mapping.
+    Expect.equals("<unnamed>", mapping["main.dart"]["name"]);
+    Expect.equals(2, mapping["main.dart"]["imports"]["lib1"].length);
+    Expect.equals(2, mapping["main.dart"]["imports"]["lib2"].length);
+    Expect.equals(1, mapping["main.dart"]["imports"]["convert"].length);
+    Expect.equals("lib1", mapping["memory:lib1.dart"]["name"]);
+    Expect.equals(1, mapping["memory:lib1.dart"]["imports"]["lib4_1"].length);
+    Expect.equals(1, mapping["memory:lib2.dart"]["imports"]["lib4_2"].length);
   });
 }
 
diff --git a/tests/compiler/dart2js/deferred_mirrors_test.dart b/tests/compiler/dart2js/deferred_mirrors_test.dart
index 4f38d5a..c92aaa1 100644
--- a/tests/compiler/dart2js/deferred_mirrors_test.dart
+++ b/tests/compiler/dart2js/deferred_mirrors_test.dart
@@ -6,19 +6,18 @@
 // to determine which elements can be deferred and which libraries
 // much be included in the initial download (loaded eagerly).
 
+import 'dart:async';
 import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
-import 'memory_source_file_helper.dart';
-import "memory_compiler.dart";
-
+import 'package:async_helper/async_helper.dart';
+import 'memory_compiler.dart';
 import 'package:compiler/src/dart2jslib.dart'
        as dart2js;
 
-runTest(String mainScript, test) {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES,
-      outputProvider: new OutputCollector());
-  asyncTest(() => compiler.run(Uri.parse(mainScript))
-      .then((_) => test(compiler)));
+Future runTest(String mainScript, test) async {
+  CompilationResult result = await runCompiler(
+      entryPoint: Uri.parse(mainScript),
+      memorySourceFiles: MEMORY_SOURCE_FILES);
+  test(result.compiler);
 }
 
 lookupLibrary(compiler, name) {
@@ -26,7 +25,11 @@
 }
 
 void main() {
-  runTest('memory:main.dart', (compiler) {
+  asyncTest(runTests);
+}
+
+runTests() async {
+  await runTest('memory:main.dart', (compiler) {
     var main = compiler.mainApp.find(dart2js.Compiler.MAIN);
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(main);
@@ -44,12 +47,12 @@
     Expect.equals(outputUnitForElement(main), outputUnitForElement(sin));
     Expect.equals(outputUnitForElement(foo2), outputUnitForElement(field2));
   });
-  runTest('memory:main2.dart', (compiler) {
+  await runTest('memory:main2.dart', (compiler) {
     // Just check that the compile runs.
     // This is a regression test.
     Expect.isTrue(true);
   });
-  runTest('memory:main3.dart', (compiler) {
+  await runTest('memory:main3.dart', (compiler) {
     var main = compiler.mainApp.find(dart2js.Compiler.MAIN);
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(main);
@@ -64,7 +67,7 @@
     Expect.notEquals(outputUnitForElement(main), outputUnitForElement(foo));
     Expect.equals(outputUnitForElement(main), outputUnitForElement(C));
   });
-  runTest('memory:main4.dart', (compiler) {
+  await runTest('memory:main4.dart', (compiler) {
     var main = compiler.mainApp.find(dart2js.Compiler.MAIN);
     Expect.isNotNull(main, "Could not find 'main'");
     compiler.deferredLoadTask.onResolutionComplete(main);
diff --git a/tests/compiler/dart2js/deferred_not_in_main_test.dart b/tests/compiler/dart2js/deferred_not_in_main_test.dart
index 0b8ef3a..002d9e5 100644
--- a/tests/compiler/dart2js/deferred_not_in_main_test.dart
+++ b/tests/compiler/dart2js/deferred_not_in_main_test.dart
@@ -12,8 +12,11 @@
 import 'memory_compiler.dart';
 
 void main() {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    Compiler compiler = result.compiler;
+
     lookupLibrary(name) {
       return compiler.libraryLoader.lookupLibrary(Uri.parse(name));
     }
@@ -30,7 +33,7 @@
     var foo2 = lib2.find("foo2");
 
     Expect.notEquals(mainOutputUnit, outputUnitForElement(foo2));
-  }));
+  });
 }
 
 // lib1 imports lib2 deferred. But mainlib never uses DeferredLibrary.
diff --git a/tests/compiler/dart2js/diagnose_ambiguous_test.dart b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
index 9d96426..09e8706 100644
--- a/tests/compiler/dart2js/diagnose_ambiguous_test.dart
+++ b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
@@ -5,17 +5,17 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart' show Diagnostic;
-import 'package:compiler/src/dart2jslib.dart';
 import 'package:expect/expect.dart';
 import 'memory_compiler.dart';
 
 void main() {
   DiagnosticCollector collector = new DiagnosticCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  asyncTest(() async {
+    CompilationResult result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       diagnosticHandler: collector,
       options: ['--analyze-all']);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+
     List<String> diagnostics = <String>[];
     collector.messages.forEach((DiagnosticMessage message) {
       if (message.kind == Diagnostic.VERBOSE_INFO) return;
@@ -30,8 +30,8 @@
         "memory:main.dart:86:92:Duplicate import of 'hest'.:warning",
     ];
     Expect.listEquals(expected, diagnostics);
-    Expect.isFalse(compiler.compilationFailed);
-  }));
+    Expect.isTrue(result.isSuccess);
+  });
 }
 
 const Map MEMORY_SOURCE_FILES = const {
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index 7cea785..af56b54 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -103,51 +103,51 @@
 """};
 
 void main() {
-  asyncTest(() =>
-    compileAndTest("AddAll.dart", (types, getType, compiler) {
+  asyncTest(() async {
+    await compileAndTest("AddAll.dart", (types, getType, compiler) {
       Expect.equals(getType('int'), types.uint31Type);
       Expect.equals(getType('anotherInt'), types.uint31Type);
       Expect.equals(getType('dynamic'), types.dynamicType);
       Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-    }));
-  asyncTest(() => compileAndTest("Union.dart", (types, getType, compiler) {
-    Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-    Expect.isTrue(getType('aString').containsOnlyString(compiler.world));
-    Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
-  }));
-  asyncTest(() =>
-    compileAndTest("ValueType.dart", (types, getType, compiler) {
+    });
+    await compileAndTest("Union.dart", (types, getType, compiler) {
+      Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
+      Expect.isTrue(getType('aString').containsOnlyString(compiler.world));
+      Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
+    });
+    await compileAndTest("ValueType.dart", (types, getType, compiler) {
       Expect.equals(getType('knownDouble'), types.doubleType);
       Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
       Expect.equals(getType('justNull'), types.nullType);
-    }));
-  asyncTest(() => compileAndTest("Propagation.dart", (code) {
-    Expect.isFalse(code.contains("J.\$add\$ns"));
-  }, createCode: true));
-  asyncTest(() => compileAndTest("Bailout.dart", (types, getType, compiler) {
-    Expect.equals(getType('notInt'), types.dynamicType);
-    Expect.equals(getType('alsoNotInt'), types.dynamicType);
-    Expect.isFalse(getType('dict').isDictionary);
-  }));
+    });
+    await compileAndTest("Propagation.dart", (code) {
+      Expect.isFalse(code.contains("J.\$add\$ns"));
+    }, createCode: true);
+    await compileAndTest("Bailout.dart", (types, getType, compiler) {
+      Expect.equals(getType('notInt'), types.dynamicType);
+      Expect.equals(getType('alsoNotInt'), types.dynamicType);
+      Expect.isFalse(getType('dict').isDictionary);
+    });
+  });
 }
 
-compileAndTest(source, checker, {createCode: false}) {
-  var compiler = compilerFor(SOURCES);
-  compiler.stopAfterTypeInference = !createCode;
-  var uri = Uri.parse('memory:'+source);
-  return compiler.runCompiler(uri).then((_) {
-    var typesTask = compiler.typesTask;
-    var typesInferrer = typesTask.typesInferrer;
-    getType(String name) {
-      var element = findElement(compiler, name);
-      return typesInferrer.getTypeOfElement(element);
-    }
-    if (!createCode) {
-      checker(typesTask, getType, compiler);
-    } else {
-      var element = compiler.mainApp.findExported('main');
-      var code = compiler.backend.assembleCode(element);
-      checker(code);
-    }
-  });
+compileAndTest(source, checker, {createCode: false}) async {
+  CompilationResult result = await runCompiler(
+      entryPoint: Uri.parse('memory:'+source),
+      memorySourceFiles: SOURCES,
+      beforeRun: (compiler) { compiler.stopAfterTypeInference = !createCode; });
+  var compiler = result.compiler;
+  var typesTask = compiler.typesTask;
+  var typesInferrer = typesTask.typesInferrer;
+  getType(String name) {
+    var element = findElement(compiler, name);
+    return typesInferrer.getTypeOfElement(element);
+  }
+  if (!createCode) {
+    checker(typesTask, getType, compiler);
+  } else {
+    var element = compiler.mainApp.findExported('main');
+    var code = compiler.backend.assembleCode(element);
+    checker(code);
+  }
 }
diff --git a/tests/compiler/dart2js/dump_info_test.dart b/tests/compiler/dart2js/dump_info_test.dart
index bc962c2..c5da18c 100644
--- a/tests/compiler/dart2js/dump_info_test.dart
+++ b/tests/compiler/dart2js/dump_info_test.dart
@@ -97,26 +97,29 @@
 
 typedef void JsonTaking(Map<String, dynamic> json);
 
-void jsonTest(String program, JsonTaking testFn) {
-  var compiler = compilerFor({'main.dart': program}, options: ['--dump-info']);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then(
-    (_) {
-      Expect.isFalse(compiler.compilationFailed);
-      var dumpTask = compiler.dumpInfoTask;
-      dumpTask.collectInfo();
-      var info = dumpTask.infoCollector;
+jsonTest(String program, JsonTaking testFn) async {
+  var result = await runCompiler(
+      memorySourceFiles: {'main.dart': program}, options: ['--dump-info']);
+  var compiler = result.compiler;
+  Expect.isFalse(compiler.compilationFailed);
+  var dumpTask = compiler.dumpInfoTask;
+  dumpTask.collectInfo();
+  var info = dumpTask.infoCollector;
 
-      StringBuffer sb = new StringBuffer();
-      dumpTask.dumpInfoJson(sb);
-      String json = sb.toString();
-      Map<String, dynamic> map = JSON.decode(json);
+  StringBuffer sb = new StringBuffer();
+  dumpTask.dumpInfoJson(sb);
+  String json = sb.toString();
+  Map<String, dynamic> map = JSON.decode(json);
 
-      testFn(map);
-    }));
+  testFn(map);
 }
 
 main() {
-  jsonTest(TEST_BASIC, (map) {
+  asyncTest(runTests);
+}
+
+runTests() async {
+  await jsonTest(TEST_BASIC, (map) {
     Expect.isTrue(map['elements'].isNotEmpty);
     Expect.isTrue(map['elements']['function'].isNotEmpty);
     Expect.isTrue(map['elements']['library'].isNotEmpty);
@@ -131,7 +134,7 @@
     }));
   });
 
-  jsonTest(TEST_CLOSURES, (map) {
+  await jsonTest(TEST_CLOSURES, (map) {
     var functions = map['elements']['function'].values;
     Expect.isTrue(functions.any((fn) {
       return fn['name'] == 'bar' && fn['children'].length == 11;
@@ -141,7 +144,7 @@
     }));
   });
 
-  jsonTest(TEST_STATICS, (map) {
+  await  jsonTest(TEST_STATICS, (map) {
     var functions = map['elements']['function'].values;
     var classes = map['elements']['class'].values;
     Expect.isTrue(functions.any((fn) {
@@ -153,7 +156,7 @@
     }));
   });
 
-  jsonTest(TEST_INLINED_1, (map) {
+  await jsonTest(TEST_INLINED_1, (map) {
     var functions = map['elements']['function'].values;
     var classes = map['elements']['class'].values;
     Expect.isTrue(functions.any((fn) {
@@ -166,7 +169,7 @@
     }));
   });
 
-  jsonTest(TEST_INLINED_2, (map) {
+  await jsonTest(TEST_INLINED_2, (map) {
     var functions = map['elements']['function'].values;
     var deps = map['holding'];
     var main_ = functions.firstWhere((v) => v['name'] == 'main');
diff --git a/tests/compiler/dart2js/duplicate_library_test.dart b/tests/compiler/dart2js/duplicate_library_test.dart
index 43a1deb..8536370 100644
--- a/tests/compiler/dart2js/duplicate_library_test.dart
+++ b/tests/compiler/dart2js/duplicate_library_test.dart
@@ -5,41 +5,46 @@
 // Test that duplicate library names result in different messages depending
 // on whether the libraries are based on the same resource.
 
+import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-
+import 'package:compiler/src/dart2jslib.dart' show MessageKind;
 import 'memory_compiler.dart';
 
 void check(String kind,
            Iterable<DiagnosticMessage> messages,
-           List<String> prefixes) {
-  Expect.equals(messages.length, prefixes.length,
+           List<MessageKind> expectedMessageKinds) {
+  Expect.equals(messages.length, expectedMessageKinds.length,
       "Unexpected $kind count: $messages");
   int i = 0;
   messages.forEach((DiagnosticMessage message) {
-    Expect.isTrue(message.message.startsWith(prefixes[i++]));
+    Expect.equals(expectedMessageKinds[i++], message.message.kind);
   });
 }
 
-void test(Map<String, String> source,
-          {List<String> warnings: const <String>[],
-           List<String> hints: const <String>[]}) {
+Future test(Map<String, String> source,
+            {List<MessageKind> warnings: const <MessageKind>[],
+            List<MessageKind> hints: const <MessageKind>[]}) async {
   DiagnosticCollector collector = new DiagnosticCollector();
-  var compiler = compilerFor(source,
-                             diagnosticHandler: collector,
-                             showDiagnostics: true,
-                             options: ['--analyze-only', '--analyze-all'],
-                             packageRoot: Uri.parse('memory:pkg/'));
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
-    Expect.isTrue(collector.errors.isEmpty);
-    check('warning', collector.warnings, warnings);
-    check('hint', collector.hints, hints);
-    Expect.isTrue(collector.infos.isEmpty);
-  }));
+  await runCompiler(
+      memorySourceFiles: source,
+      diagnosticHandler: collector,
+      showDiagnostics: true,
+      options: ['--analyze-only', '--analyze-all'],
+      packageRoot: Uri.parse('memory:pkg/'));
+
+  Expect.isTrue(collector.errors.isEmpty);
+  check('warning', collector.warnings, warnings);
+  check('hint', collector.hints, hints);
+  Expect.isTrue(collector.infos.isEmpty);
 }
 
 void main() {
-  test({
+  asyncTest(runTests);
+}
+
+Future runTests() async {
+  await test({
     'main.dart': """
 library main;
 
@@ -49,9 +54,9 @@
     'pkg/lib/foo.dart': """
 library lib.foo;
 """},
-    warnings: ["The library 'lib.foo' in 'memory:pkg/lib/foo.dart' is loaded"]);
+    warnings: [MessageKind.DUPLICATED_LIBRARY_RESOURCE]);
 
-  test({
+  await test({
     'main.dart': """
 library main;
 
@@ -66,9 +71,9 @@
     'pkg/lib/bar.dart': """
 library lib.bar;
 """},
-    warnings: ["The library 'lib.bar' in 'memory:pkg/lib/bar.dart' is loaded"]);
+    warnings: [MessageKind.DUPLICATED_LIBRARY_RESOURCE]);
 
-  test({
+  await test({
     'main.dart': """
 library main;
 
@@ -83,9 +88,9 @@
     'pkg/lib/baz.dart': """
 library lib.baz;
 """},
-    warnings: ["The library 'lib.baz' in 'memory:pkg/lib/baz.dart' is loaded"]);
+    warnings: [MessageKind.DUPLICATED_LIBRARY_RESOURCE]);
 
-  test({
+  await test({
     'main.dart': """
 library main;
 
@@ -105,9 +110,9 @@
     'pkg/lib/boz.dart': """
 library lib.boz;
 """},
-    warnings: ["The library 'lib.boz' in 'memory:pkg/lib/boz.dart' is loaded"]);
+    warnings: [MessageKind.DUPLICATED_LIBRARY_RESOURCE]);
 
- test({
+  await test({
     'main.dart': """
 library main;
 
@@ -117,9 +122,9 @@
     'pkg/lib/qux.dart': """
 // No library tag.
 """},
-    hints: ["The resource 'memory:pkg/lib/qux.dart' is loaded"]);
+    hints: [MessageKind.DUPLICATED_RESOURCE]);
 
-  test({
+  await test({
     'main.dart': """
 library main;
 
@@ -132,7 +137,7 @@
     'bar.dart': """
 library lib;
 """},
-    warnings: ["Duplicated library name 'lib'.",
-               "Duplicated library name 'lib'."]);
+    warnings: [MessageKind.DUPLICATED_LIBRARY_NAME,
+               MessageKind.DUPLICATED_LIBRARY_NAME]);
 }
 
diff --git a/tests/compiler/dart2js/expect_annotations2_test.dart b/tests/compiler/dart2js/expect_annotations2_test.dart
index 580ba3a..f0572c5 100644
--- a/tests/compiler/dart2js/expect_annotations2_test.dart
+++ b/tests/compiler/dart2js/expect_annotations2_test.dart
@@ -34,9 +34,11 @@
         }'''};
 
 void main() {
-  OutputCollector collector = new OutputCollector();
-  var compiler = compilerFor(MEMORY_SOURCE_FILES, outputProvider: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    OutputCollector collector = new OutputCollector();
+    CompilationResult result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        outputProvider: collector);
     // Simply check that the constants of the small functions are still in the
     // output, and that we don't see the result of constant folding.
     String jsOutput = collector.getOutput('', 'js');
@@ -48,5 +50,5 @@
     Expect.isFalse(jsOutput.contains('211109'));
     Expect.isFalse(jsOutput.contains('82155031'));
     Expect.isFalse(jsOutput.contains('4712'));
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/expect_annotations_test.dart b/tests/compiler/dart2js/expect_annotations_test.dart
index 8613107..e8ecc40 100644
--- a/tests/compiler/dart2js/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/expect_annotations_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:io';
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/dart2jslib.dart';
@@ -48,8 +47,10 @@
 };
 
 main() {
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    Compiler compiler = result.compiler;
     Expect.isFalse(compiler.compilationFailed, 'Unsuccessful compilation');
     JavaScriptBackend backend = compiler.backend;
     Expect.isNotNull(backend.annotations.expectNoInlineClass,
@@ -123,5 +124,5 @@
          expectTrustTypeAnnotations: true,
          expectedParameterType: coreStringType);
 
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/frontend_checker.dart b/tests/compiler/dart2js/frontend_checker.dart
index 91fb719..67b88d3 100644
--- a/tests/compiler/dart2js/frontend_checker.dart
+++ b/tests/compiler/dart2js/frontend_checker.dart
@@ -40,56 +40,56 @@
     Map<String, Set<String>> testOutcomes = {};
     String fileName = 'tests/$testFile';
     ExtractTestsFromMultitest(new Path(fileName), testSources, testOutcomes);
-    return Future.forEach(testSources.keys, (String testName) {
+    return Future.forEach(testSources.keys, (String testName) async {
       String testFileName = '$fileName/$testName';
       Set<String> expectedOutcome = testOutcomes[testName];
       bool expectFailure = testFiles[testFile].contains(testName);
       DiagnosticCollector collector = new DiagnosticCollector();
-      var compiler = compilerFor(
-           {testFileName: testSources[testName]},
-           diagnosticHandler: collector,
-           options: ['--analyze-only']..addAll(options),
-           showDiagnostics: verbose,
-           cachedCompiler: cachedCompiler);
-      return compiler.run(Uri.parse('memory:$testFileName')).then((_) {
-        bool unexpectedResult = false;
-        if (expectedOutcome.contains('compile-time error')) {
-          if (collector.errors.isEmpty) {
-            print('$testFileName: Missing compile-time error.');
-            unexpectedResult = true;
-          }
-        } else if (expectedOutcome.contains('static type warning')) {
-          if (collector.warnings.isEmpty) {
-            print('$testFileName: Missing static type warning.');
-            unexpectedResult = true;
-          }
-        } else {
-          // Expect ok.
-          if (!collector.errors.isEmpty ||
-              !collector.warnings.isEmpty) {
-            collector.errors.forEach((message) {
-              print('$testFileName: Unexpected error: ${message.message}');
-            });
-            collector.warnings.forEach((message) {
-              print('$testFileName: Unexpected warning: ${message.message}');
-            });
-            unexpectedResult = true;
-          }
+      CompilationResult result = await runCompiler(
+          entryPoint: Uri.parse('memory:$testFileName'),
+          memorySourceFiles: {testFileName: testSources[testName]},
+          diagnosticHandler: collector,
+          options: ['--analyze-only']..addAll(options),
+          showDiagnostics: verbose,
+          cachedCompiler: cachedCompiler);
+      var compiler = result.compiler;
+      bool unexpectedResult = false;
+      if (expectedOutcome.contains('compile-time error')) {
+        if (collector.errors.isEmpty) {
+          print('$testFileName: Missing compile-time error.');
+          unexpectedResult = true;
         }
-        if (expectFailure) {
-          if (unexpectedResult) {
-            unexpectedResult = false;
-          } else {
-            print('$testFileName: The test is white-listed '
-                  'and therefore expected to fail.');
-            unexpectedResult = true;
-          }
+      } else if (expectedOutcome.contains('static type warning')) {
+        if (collector.warnings.isEmpty) {
+          print('$testFileName: Missing static type warning.');
+          unexpectedResult = true;
         }
+      } else {
+        // Expect ok.
+        if (!collector.errors.isEmpty ||
+            !collector.warnings.isEmpty) {
+          collector.errors.forEach((message) {
+            print('$testFileName: Unexpected error: ${message.message}');
+          });
+          collector.warnings.forEach((message) {
+            print('$testFileName: Unexpected warning: ${message.message}');
+          });
+          unexpectedResult = true;
+        }
+      }
+      if (expectFailure) {
         if (unexpectedResult) {
-          outcomeMismatch = true;
+          unexpectedResult = false;
+        } else {
+          print('$testFileName: The test is white-listed '
+                'and therefore expected to fail.');
+          unexpectedResult = true;
         }
-        cachedCompiler = compiler;
-      });
+      }
+      if (unexpectedResult) {
+        outcomeMismatch = true;
+      }
+      cachedCompiler = compiler;
     });
   }).then((_) {
     if (outcomeMismatch) {
diff --git a/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart b/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart
index bf9b86e..1f0ab5d 100644
--- a/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart
+++ b/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart
@@ -5,7 +5,7 @@
 // Test that the compiler can generates code with compile time error according
 // to the compiler options.
 
-library dart2js.test.import;
+library dart2js.test.generate_code_with_compile_time_errors;
 
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
@@ -33,49 +33,46 @@
       bool expectHint: false}) async {
   DiagnosticCollector collector = new DiagnosticCollector();
   OutputCollector outputCollector = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  CompilationResult result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       diagnosticHandler: collector,
       outputProvider: outputCollector,
       options: options);
+  Compiler compiler = result.compiler;
+  Expect.isFalse(
+      result.isSuccess,
+      "Expected compilation failure.");
+  Expect.isTrue(
+      collector.warnings.isEmpty,
+      "Unexpected warnings: ${collector.warnings}");
+  Expect.isFalse(
+      collector.errors.isEmpty,
+      "Expected compile-time errors.");
+  Expect.equals(
+      expectHint,
+      collector.hints.isNotEmpty,
+      "Unexpected hints: ${collector.warnings}");
 
-  return compiler.run(Uri.parse('memory:main.dart')).then(
-      (bool success) {
-    Expect.isFalse(
-        success,
-        "Expected compilation failure.");
-    Expect.isTrue(
-        collector.warnings.isEmpty,
-        "Unexpected warnings: ${collector.warnings}");
-    Expect.isFalse(
-        collector.errors.isEmpty,
-        "Expected compile-time errors.");
-    Expect.equals(
-        expectHint,
-        collector.hints.isNotEmpty,
-        "Unexpected hints: ${collector.warnings}");
-
-    bool isCodeGenerated;
-    if (options.contains('--output-type=dart')) {
-      DartBackend backend = compiler.backend;
-      isCodeGenerated = backend.outputter.libraryInfo != null;
-    } else {
-      JavaScriptBackend backend = compiler.backend;
-      isCodeGenerated = backend.generatedCode.isNotEmpty;
-    }
-    Expect.equals(
-        expectedCodeGenerated,
-        isCodeGenerated,
-        expectedCodeGenerated
-            ? "Expected generated code for options $options."
-            : "Expected no code generated for options $options.");
-    Expect.equals(
-        expectedOutput,
-        outputCollector.outputMap.isNotEmpty,
-        expectedOutput
-            ? "Expected output for options $options."
-            : "Expected no output for options $options.");
-  });
+  bool isCodeGenerated;
+  if (options.contains('--output-type=dart')) {
+    DartBackend backend = compiler.backend;
+    isCodeGenerated = backend.outputter.libraryInfo != null;
+  } else {
+    JavaScriptBackend backend = compiler.backend;
+    isCodeGenerated = backend.generatedCode.isNotEmpty;
+  }
+  Expect.equals(
+      expectedCodeGenerated,
+      isCodeGenerated,
+      expectedCodeGenerated
+          ? "Expected generated code for options $options."
+          : "Expected no code generated for options $options.");
+  Expect.equals(
+      expectedOutput,
+      outputCollector.outputMap.isNotEmpty,
+      expectedOutput
+          ? "Expected output for options $options."
+          : "Expected no output for options $options.");
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/import_mirrors_test.dart b/tests/compiler/dart2js/import_mirrors_test.dart
index 1b16f76..190d414 100644
--- a/tests/compiler/dart2js/import_mirrors_test.dart
+++ b/tests/compiler/dart2js/import_mirrors_test.dart
@@ -10,7 +10,7 @@
 import 'dart:async';
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/dart2jslib.dart' show MessageKind;
+import 'package:compiler/src/warnings.dart' show MessageKind, MessageTemplate;
 import 'memory_compiler.dart';
 
 const DIRECT_IMPORT = const {
@@ -342,7 +342,7 @@
 Future test(Map sourceFiles,
             {expectedPaths,
              bool verbose: false,
-             bool enableExperimentalMirrors: false}) {
+             bool enableExperimentalMirrors: false}) async {
   if (expectedPaths is! List) {
     expectedPaths = [expectedPaths];
   }
@@ -354,24 +354,26 @@
   if (enableExperimentalMirrors) {
     options.add('--enable-experimental-mirrors');
   }
-  var compiler = compilerFor(sourceFiles, diagnosticHandler: collector,
-                             packageRoot: Uri.parse('memory:/pkg/'),
-                             options: options);
-  return compiler.run(Uri.parse('memory:/main.dart')).then((_) {
-    Expect.equals(0, collector.errors.length, 'Errors: ${collector.errors}');
-    if (enableExperimentalMirrors) {
-      Expect.equals(0, collector.warnings.length,
-                    'Warnings: ${collector.errors}');
-    } else {
-      Expect.equals(1, collector.warnings.length,
-                    'Warnings: ${collector.errors}');
-      Expect.equals(
-          MessageKind.IMPORT_EXPERIMENTAL_MIRRORS.message(
-              {'importChain': expectedPaths.join(
-                  MessageKind.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)}).toString(),
-          collector.warnings.first.message);
-    }
-  });
+  CompilationResult result = await runCompiler(
+      entryPoint: Uri.parse('memory:/main.dart'),
+      memorySourceFiles: sourceFiles,
+      diagnosticHandler: collector,
+      packageRoot: Uri.parse('memory:/pkg/'),
+      options: options);
+  Expect.equals(0, collector.errors.length, 'Errors: ${collector.errors}');
+  if (enableExperimentalMirrors) {
+    Expect.equals(0, collector.warnings.length,
+                  'Warnings: ${collector.errors}');
+  } else {
+    Expect.equals(1, collector.warnings.length,
+                  'Warnings: ${collector.errors}');
+    Expect.equals(
+        MessageKind.IMPORT_EXPERIMENTAL_MIRRORS,
+        collector.warnings.first.message.kind);
+    Expect.equals(
+        expectedPaths.join(MessageTemplate.IMPORT_EXPERIMENTAL_MIRRORS_PADDING),
+        collector.warnings.first.message.arguments['importChain']);
+  }
 }
 
 Future checkPaths(Map sourceData) {
diff --git a/tests/compiler/dart2js/import_test.dart b/tests/compiler/dart2js/import_test.dart
index aeaa469..ddd4992 100644
--- a/tests/compiler/dart2js/import_test.dart
+++ b/tests/compiler/dart2js/import_test.dart
@@ -8,7 +8,7 @@
 library dart2js.test.import;
 
 import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
+import 'package:async_helper/async_helper.dart';
 import 'memory_compiler.dart';
 
 const MEMORY_SOURCE_FILES = const {
@@ -28,25 +28,27 @@
 ''',
 };
 
-testMissingImports() {
+testMissingImports() async {
   var collector = new DiagnosticCollector();
-  var compiler = compilerFor(MEMORY_SOURCE_FILES, diagnosticHandler: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
-    Expect.equals(4, collector.errors.length);
-    Expect.equals(1, collector.warnings.length);
-  }));
+  await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
+      diagnosticHandler: collector);
+  Expect.equals(4, collector.errors.length);
+  Expect.equals(1, collector.warnings.length);
 }
 
-testMissingMain() {
+testMissingMain() async {
   var collector = new DiagnosticCollector();
-  var compiler = compilerFor({}, diagnosticHandler: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:missing.dart')).then((_) {
-    Expect.equals(1, collector.errors.length);
-    Expect.equals(0, collector.warnings.length);
-  }));
+  await runCompiler(
+      entryPoint: Uri.parse('memory:missing.dart'),
+      diagnosticHandler: collector);
+  Expect.equals(1, collector.errors.length);
+  Expect.equals(0, collector.warnings.length);
 }
 
 void main() {
-  testMissingImports();
-  testMissingMain();
+  asyncTest(() async {
+    await testMissingImports();
+    await testMissingMain();
+  });
 }
diff --git a/tests/compiler/dart2js/in_user_code_test.dart b/tests/compiler/dart2js/in_user_code_test.dart
index 6684829..00b2549 100644
--- a/tests/compiler/dart2js/in_user_code_test.dart
+++ b/tests/compiler/dart2js/in_user_code_test.dart
@@ -4,9 +4,10 @@
 
 // Test that the helper [Compiler.inUserCode] works as intended.
 
+import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-
+import 'package:compiler/src/dart2jslib.dart' show Compiler;
 import 'memory_compiler.dart';
 
 const SOURCE = const {
@@ -42,56 +43,60 @@
 """,
 };
 
-void test(List<Uri> entryPoints, Map<String, bool> expectedResults) {
-  var compiler = compilerFor(SOURCE,
-                             options: ['--analyze-only', '--analyze-all'],
-                             packageRoot: Uri.parse('memory:pkg/'));
-  Uri mainUri = null;
-  if (entryPoints.length == 1) {
-    mainUri = entryPoints[0];
-  } else {
-    compiler.librariesToAnalyzeWhenRun = entryPoints;
-  }
-  asyncTest(() => compiler.run(mainUri).then((_) {
-    expectedResults.forEach((String uri, bool expectedResult) {
-      var element = compiler.libraryLoader.lookupLibrary(Uri.parse(uri));
-      Expect.isNotNull(element, "Unknown library '$uri'.");
-      Expect.equals(expectedResult, compiler.inUserCode(element),
-          expectedResult ? "Library '$uri' expected to be in user code"
-                         : "Library '$uri' not expected to be in user code");
-    });
-  }));
+Future test(List<Uri> entryPoints, Map<String, bool> expectedResults) async {
+  CompilationResult result = await runCompiler(
+    entryPoints: entryPoints,
+    memorySourceFiles: SOURCE,
+    options: ['--analyze-only', '--analyze-all'],
+    packageRoot: Uri.parse('memory:pkg/'));
+  Compiler compiler = result.compiler;
+  expectedResults.forEach((String uri, bool expectedResult) {
+    var element = compiler.libraryLoader.lookupLibrary(Uri.parse(uri));
+    Expect.isNotNull(element, "Unknown library '$uri'.");
+    Expect.equals(expectedResult, compiler.inUserCode(element),
+        expectedResult ? "Library '$uri' expected to be in user code"
+                       : "Library '$uri' not expected to be in user code");
+  });
 }
 
 void main() {
-  test([Uri.parse('memory:main.dart')],
-       {'memory:main.dart': true,
-        'memory:foo.dart': true,
-        'memory:pkg/sub/bar.dart': true,
-        'memory:pkg/sub/baz.dart': true,
-        'package:sub/bar.dart': false,
-        'package:sub/baz.dart': false,
-        'package:sup/boz.dart': false,
-        'dart:core': false,
-        'dart:async': false});
-  test([Uri.parse('dart:async')],
-       {'dart:core': true,
-        'dart:async': true});
-  test([Uri.parse('package:sub/bar.dart')],
-       {'package:sub/bar.dart': true,
-        'package:sub/baz.dart': true,
-        'package:sup/boz.dart': false,
-        'dart:core': false});
-  test([Uri.parse('package:sub/bar.dart'), Uri.parse('package:sup/boz.dart')],
-       {'package:sub/bar.dart': true,
-        'package:sub/baz.dart': true,
-        'package:sup/boz.dart': true,
-        'dart:core': false});
-  test([Uri.parse('dart:async'), Uri.parse('package:sub/bar.dart')],
-       {'package:sub/bar.dart': true,
-        'package:sub/baz.dart': true,
-        'package:sup/boz.dart': false,
-        'dart:core': true,
-        'dart:async': true});
+  asyncTest(runTests);
+}
+
+Future runTests() async {
+  await test(
+      [Uri.parse('memory:main.dart')],
+      {'memory:main.dart': true,
+       'memory:foo.dart': true,
+       'memory:pkg/sub/bar.dart': true,
+       'memory:pkg/sub/baz.dart': true,
+       'package:sub/bar.dart': false,
+       'package:sub/baz.dart': false,
+       'package:sup/boz.dart': false,
+       'dart:core': false,
+       'dart:async': false});
+  await test(
+      [Uri.parse('dart:async')],
+      {'dart:core': true,
+       'dart:async': true});
+  await test(
+      [Uri.parse('package:sub/bar.dart')],
+      {'package:sub/bar.dart': true,
+       'package:sub/baz.dart': true,
+       'package:sup/boz.dart': false,
+       'dart:core': false});
+  await test(
+      [Uri.parse('package:sub/bar.dart'), Uri.parse('package:sup/boz.dart')],
+      {'package:sub/bar.dart': true,
+       'package:sub/baz.dart': true,
+       'package:sup/boz.dart': true,
+       'dart:core': false});
+  await test(
+      [Uri.parse('dart:async'), Uri.parse('package:sub/bar.dart')],
+      {'package:sub/bar.dart': true,
+       'package:sub/baz.dart': true,
+       'package:sup/boz.dart': false,
+       'dart:core': true,
+       'dart:async': true});
 }
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir.dart b/tests/compiler/dart2js/js_backend_cps_ir.dart
index e3fb44d..f1fd70a 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir.dart
@@ -60,11 +60,15 @@
 runTests(List<TestEntry> tests) {
   for (TestEntry test in tests) {
     Map files = {TEST_MAIN_FILE: test.source};
-    asyncTest(() {
-      Compiler compiler = compilerFor(files, options: <String>['--use-cps-ir']);
+    asyncTest(() async {
       Uri uri = Uri.parse('memory:$TEST_MAIN_FILE');
-      return compiler.run(uri).then((bool success) {
-        Expect.isTrue(success);
+      try {
+        CompilationResult result = await runCompiler(
+            entryPoint: uri,
+            memorySourceFiles: files,
+            options: <String>['--use-cps-ir']);
+        Expect.isTrue(result.isSuccess);
+        Compiler compiler = result.compiler;
         String expectation = test.expectation;
         if (expectation != null) {
           String expected = test.expectation;
@@ -75,11 +79,11 @@
             Expect.fail('Expected:\n$expected\nbut found\n$found');
           }
         }
-      }).catchError((e) {
+      } catch (e) {
         print(e);
         Expect.fail('The following test failed to compile:\n'
                     '${formatTest(files)}');
-      });
+      }
     });
   }
 }
diff --git a/tests/compiler/dart2js/library_resolution_test.dart b/tests/compiler/dart2js/library_resolution_test.dart
index ed41ebe..5eeb342 100644
--- a/tests/compiler/dart2js/library_resolution_test.dart
+++ b/tests/compiler/dart2js/library_resolution_test.dart
@@ -21,7 +21,8 @@
     LibraryElement;
 
 import 'package:compiler/src/dart2jslib.dart' show
-    MessageKind;
+    MessageKind,
+    MessageTemplate;
 
 import 'package:compiler/src/null_compiler_output.dart' show
     NullCompilerOutput;
@@ -92,7 +93,7 @@
   }
 
   String expectedMessage =
-      MessageKind.LIBRARY_NOT_FOUND.message(
+      MessageTemplate.TEMPLATES[MessageKind.LIBRARY_NOT_FOUND].message(
           {'resolvedUri': 'dart:mock2.dart'}).computeMessage();
 
   int actualMessageCount = 0;
diff --git a/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart b/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart
index 1106be3..992aab0 100644
--- a/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart
+++ b/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart
@@ -3,9 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
+import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/types/types.dart'
     show ContainerTypeMask, TypeMask;
+import 'package:compiler/src/dart2jslib.dart';
 
 import 'memory_compiler.dart';
 import 'compiler_helper.dart' show findElement;
@@ -25,8 +26,9 @@
 '''};
 
 void main() {
-  var compiler = compilerFor(TEST);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result = await runCompiler(memorySourceFiles: TEST);
+    Compiler compiler = result.compiler;
     var typesInferrer = compiler.typesTask.typesInferrer;
 
     checkType(String name, type, length) {
@@ -40,5 +42,5 @@
 
     checkType('myList', compiler.typesTask.numType, 42);
     checkType('myOtherList', compiler.typesTask.uint31Type, 32);
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/malformed_uri_test.dart b/tests/compiler/dart2js/malformed_uri_test.dart
index d51e2dd..70ec4a6 100644
--- a/tests/compiler/dart2js/malformed_uri_test.dart
+++ b/tests/compiler/dart2js/malformed_uri_test.dart
@@ -20,11 +20,13 @@
 };
 
 testMalformedUri() {
-  var collector = new DiagnosticCollector();
-  var compiler = compilerFor(MEMORY_SOURCE_FILES, diagnosticHandler: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var collector = new DiagnosticCollector();
+    await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        diagnosticHandler: collector);
     Expect.equals(1, collector.errors.length);
-  }));
+  });
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index 44902d8..4d3c893 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -7,13 +7,17 @@
 import 'memory_source_file_helper.dart';
 
 
-import 'package:compiler/src/null_compiler_output.dart'
-       show NullCompilerOutput;
+import 'package:compiler/src/null_compiler_output.dart' show
+    NullCompilerOutput;
+
+import 'package:compiler/src/dart2jslib.dart' show
+    Message;
 
 import 'package:compiler/compiler.dart' show
     DiagnosticHandler;
 
 import 'package:compiler/compiler_new.dart' show
+    CompilationResult,
     CompilerDiagnostics,
     CompilerOutput,
     Diagnostic,
@@ -27,53 +31,56 @@
 import 'package:compiler/src/library_loader.dart'
     show LoadedLibraries;
 
-import 'package:compiler/src/old_to_new_api.dart';
-
 export 'output_collector.dart';
+export 'package:compiler/compiler_new.dart' show
+    CompilationResult;
 
 class DiagnosticMessage {
+  final Message message;
   final Uri uri;
   final int begin;
   final int end;
-  final String message;
+  final String text;
   final Diagnostic kind;
 
-  DiagnosticMessage(this.uri, this.begin, this.end, this.message, this.kind);
+  DiagnosticMessage(
+      this.message, this.uri, this.begin, this.end, this.text, this.kind);
 
-  String toString() => '$uri:$begin:$end:$message:$kind';
+  String toString() => '$uri:$begin:$end:$text:$kind';
 }
 
 class DiagnosticCollector implements CompilerDiagnostics {
   List<DiagnosticMessage> messages = <DiagnosticMessage>[];
 
   void call(Uri uri, int begin, int end, String message, Diagnostic kind) {
-    report(uri, begin, end, message, kind);
+    report(null, uri, begin, end, message, kind);
   }
 
   @override
-  void report(Uri uri, int begin, int end, String message, Diagnostic kind) {
-    messages.add(new DiagnosticMessage(uri, begin, end, message, kind));
+  void report(Message message,
+              Uri uri, int begin, int end, String text, Diagnostic kind) {
+    messages.add(new DiagnosticMessage(message, uri, begin, end, text, kind));
   }
 
-  Iterable<DiagnosticMessage> filterMessagesByKind(Diagnostic kind) {
+  Iterable<DiagnosticMessage> filterMessagesByKinds(List<Diagnostic> kinds) {
     return messages.where(
-      (DiagnosticMessage message) => message.kind == kind);
+      (DiagnosticMessage message) => kinds.contains(message.kind));
   }
 
   Iterable<DiagnosticMessage> get errors {
-    return filterMessagesByKind(Diagnostic.ERROR);
+    return filterMessagesByKinds([Diagnostic.ERROR]);
   }
 
   Iterable<DiagnosticMessage> get warnings {
-    return filterMessagesByKind(Diagnostic.WARNING);
+    return filterMessagesByKinds([Diagnostic.WARNING]);
   }
 
   Iterable<DiagnosticMessage> get hints {
-    return filterMessagesByKind(Diagnostic.HINT);
+    return filterMessagesByKinds([Diagnostic.HINT]);
   }
 
   Iterable<DiagnosticMessage> get infos {
-    return filterMessagesByKind(Diagnostic.INFO);
+    return filterMessagesByKinds([Diagnostic.INFO]);
   }
 
   /// `true` if non-verbose messages has been collected.
@@ -88,9 +95,10 @@
   const MultiDiagnostics([this.diagnosticsList = const []]);
 
   @override
-  void report(Uri uri, int begin, int end, String message, Diagnostic kind) {
+  void report(Message message, Uri uri, int begin, int end,
+              String text, Diagnostic kind) {
     for (CompilerDiagnostics diagnostics in diagnosticsList) {
-      diagnostics.report(uri, begin, end, message, kind);
+      diagnostics.report(message, uri, begin, end, text, kind);
     }
   }
 }
@@ -116,11 +124,45 @@
 Expando<MemorySourceFileProvider> expando =
     new Expando<MemorySourceFileProvider>();
 
+Future<CompilationResult> runCompiler(
+    {Map<String, String> memorySourceFiles: const <String, String>{},
+     Uri entryPoint,
+     List<Uri> entryPoints,
+     CompilerDiagnostics diagnosticHandler,
+     CompilerOutput outputProvider,
+     List<String> options: const <String>[],
+     Compiler cachedCompiler,
+     bool showDiagnostics: true,
+     Uri packageRoot,
+     Uri packageConfig,
+     PackagesDiscoveryProvider packagesDiscoveryProvider,
+     void beforeRun(Compiler compiler)}) async {
+  if (entryPoint == null) {
+    entryPoint = Uri.parse('memory:main.dart');
+  }
+  Compiler compiler = compilerFor(
+      memorySourceFiles,
+      diagnosticHandler: diagnosticHandler,
+      outputProvider: outputProvider,
+      options: options,
+      cachedCompiler: cachedCompiler,
+      showDiagnostics: showDiagnostics,
+      packageRoot: packageRoot,
+      packageConfig: packageConfig,
+      packagesDiscoveryProvider: packagesDiscoveryProvider);
+  compiler.librariesToAnalyzeWhenRun = entryPoints;
+  if (beforeRun != null) {
+    beforeRun(compiler);
+  }
+  bool isSuccess = await compiler.run(entryPoint);
+  return new CompilationResult(compiler, isSuccess: isSuccess);
+}
+
 Compiler compilerFor(
     Map<String, String> memorySourceFiles,
     {CompilerDiagnostics diagnosticHandler,
      CompilerOutput outputProvider,
-     List<String> options: const [],
+     List<String> options: const <String>[],
      Compiler cachedCompiler,
      bool showDiagnostics: true,
      Uri packageRoot,
diff --git a/tests/compiler/dart2js/message_kind_helper.dart b/tests/compiler/dart2js/message_kind_helper.dart
index 244d5a0..b579e95 100644
--- a/tests/compiler/dart2js/message_kind_helper.dart
+++ b/tests/compiler/dart2js/message_kind_helper.dart
@@ -9,7 +9,8 @@
 
 import 'package:compiler/src/dart2jslib.dart' show
     Compiler,
-    MessageKind;
+    MessageKind,
+    MessageTemplate;
 import 'package:compiler/src/dart_backend/dart_backend.dart' show
     DartBackend;
 import 'package:compiler/src/old_to_new_api.dart' show
@@ -52,11 +53,11 @@
     // If you add something here, please file a *new* bug report.
 ]);
 
-Future<Compiler> check(MessageKind kind, Compiler cachedCompiler) {
-  Expect.isNotNull(kind.howToFix);
-  Expect.isFalse(kind.examples.isEmpty);
+Future<Compiler> check(MessageTemplate template, Compiler cachedCompiler) {
+  Expect.isNotNull(template.howToFix);
+  Expect.isFalse(template.examples.isEmpty);
 
-  return Future.forEach(kind.examples, (example) {
+  return Future.forEach(template.examples, (example) {
     if (example is String) {
       example = {'main.dart': example};
     } else {
@@ -77,13 +78,13 @@
     if (cachedCompiler != null) {
       oldBackendIsDart = cachedCompiler.backend is DartBackend;
     }
-    bool newBackendIsDart = kind.options.contains('--output-type=dart');
+    bool newBackendIsDart = template.options.contains('--output-type=dart');
 
     Compiler compiler = compilerFor(
         example,
         diagnosticHandler: new LegacyCompilerDiagnostics(collect),
         options: ['--analyze-only',
-                  '--enable-experimental-mirrors']..addAll(kind.options),
+                  '--enable-experimental-mirrors']..addAll(template.options),
         cachedCompiler:
              // TODO(johnniwinther): Remove this restriction when constant
              // values can be computed directly from the expressions.
@@ -93,8 +94,8 @@
 
       Expect.isFalse(messages.isEmpty, 'No messages in """$example"""');
 
-      String expectedText = !kind.hasHowToFix
-          ? kind.template : '${kind.template}\n${kind.howToFix}';
+      String expectedText = !template.hasHowToFix
+          ? template.template : '${template.template}\n${template.howToFix}';
       String pattern = expectedText.replaceAllMapped(
           new RegExp(ESCAPE_REGEXP), (m) => '\\${m[0]}');
       pattern = pattern.replaceAll(new RegExp(r'#\\\{[^}]*\\\}'), '.*');
@@ -116,7 +117,7 @@
         for (String message in unexpectedMessages) {
           print("Unexpected message: $message");
         }
-        if (!kindsWithExtraMessages.contains(kind)) {
+        if (!kindsWithExtraMessages.contains(template.kind)) {
           // Try changing the error reporting logic before adding an exception
           // to [kindsWithExtraMessages].
           throw 'Unexpected messages found.';
@@ -136,7 +137,8 @@
             e, MessageKind.GENERIC,
             {'text': 'Pending class to be resolved.'});
       }
-      Expect.isTrue(!pendingStuff || kindsWithPendingClasses.contains(kind));
+      Expect.isTrue(!pendingStuff ||
+                    kindsWithPendingClasses.contains(template));
 
       if (!pendingStuff) {
         // If there is pending stuff, or the compiler was cancelled, we
diff --git a/tests/compiler/dart2js/message_kind_test.dart b/tests/compiler/dart2js/message_kind_test.dart
index 368d51b..9796595 100644
--- a/tests/compiler/dart2js/message_kind_test.dart
+++ b/tests/compiler/dart2js/message_kind_test.dart
@@ -5,58 +5,42 @@
 import 'package:expect/expect.dart';
 import 'dart:async';
 import "package:async_helper/async_helper.dart";
-import 'package:compiler/src/dart2jslib.dart' show
-    DualKind,
-    MessageKind;
+import 'package:compiler/src/warnings.dart' show
+    MessageKind,
+    MessageTemplate;
 
 import 'message_kind_helper.dart';
 
-import 'dart:mirrors';
-
 main(List<String> arguments) {
-  ClassMirror cls = reflectClass(MessageKind);
-  Map<String, MessageKind> kinds = <String, MessageKind>{};
-  cls.declarations.forEach((Symbol name, DeclarationMirror declaration) {
-    if (declaration is! VariableMirror) return;
-    VariableMirror variable = declaration;
-    if (variable.isStatic) {
-      var value = cls.getField(name).reflectee;
-      String variableName = MirrorSystem.getName(name);
-      if (variableName == 'IMPORT_EXPERIMENTAL_MIRRORS_PADDING') {
-        return;
-      }
-      if (value is MessageKind) {
-        kinds[variableName] = value;
-      } else {
-        Expect.fail("Weird static field: '${variableName}'.");
-      }
-    }
-  });
-  List<String> names = kinds.keys.toList()..sort();
-  List<String> examples = <String>[];
-  for (String name in names) {
+  List<MessageTemplate> examples = <MessageTemplate>[];
+  for (MessageKind kind in MessageKind.values) {
+    MessageTemplate template = MessageTemplate.TEMPLATES[kind];
+    Expect.isNotNull(template, "No template for $kind.");
+    Expect.equals(kind, template.kind,
+        "Invalid MessageTemplate.kind for $kind, found ${template.kind}.");
+
+    String name = '${kind.toString()}'.substring('MessageKind.'.length);
     if (!arguments.isEmpty && !arguments.contains(name)) continue;
-    MessageKind kind = kinds[name];
     if (name == 'GENERIC' // Shouldn't be used.
         // We can't provoke a crash.
         || name == 'COMPILER_CRASHED'
         || name == 'PLEASE_REPORT_THE_CRASH'
         // We cannot provide examples for patch errors.
         || name.startsWith('PATCH_')) continue;
-    if (kind.examples != null) {
-      examples.add(name);
+    if (template.examples != null) {
+      examples.add(template);
     } else {
       print("No example in '$name'");
     }
   };
   var cachedCompiler;
-  asyncTest(() => Future.forEach(examples, (String name) {
-    print("Checking '$name'.");
+  asyncTest(() => Future.forEach(examples, (MessageTemplate template) {
+    print("Checking '${template.kind}'.");
     Stopwatch sw = new Stopwatch()..start();
-    return check(kinds[name], cachedCompiler).then((var compiler) {
+    return check(template, cachedCompiler).then((var compiler) {
       cachedCompiler = compiler;
       sw.stop();
-      print("Checked '$name' in ${sw.elapsedMilliseconds}ms.");
+      print("Checked '${template.kind}' in ${sw.elapsedMilliseconds}ms.");
     });
   }));
 }
diff --git a/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart b/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
index 093833e..20411b7 100644
--- a/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
+++ b/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:expect/expect.dart';
 import "package:async_helper/async_helper.dart";
-import 'memory_compiler.dart' show compilerFor;
+import 'memory_compiler.dart' show runCompiler;
 import 'compiler_helper.dart' show findElement;
 import 'type_mask_test_helper.dart';
 
@@ -24,13 +24,14 @@
 };
 
 void main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    var compiler = result.compiler;
     var element = findElement(compiler, 'field');
     var typesTask = compiler.typesTask;
     var typesInferrer = typesTask.typesInferrer;
     Expect.equals(typesTask.uint31Type,
                   simplify(typesInferrer.getTypeOfElement(element), compiler),
                   'field');
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart b/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
index 8395fed..54252ec 100644
--- a/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
+++ b/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:expect/expect.dart';
 import "package:async_helper/async_helper.dart";
-import 'memory_compiler.dart' show compilerFor;
+import 'memory_compiler.dart' show runCompiler;
 import 'compiler_helper.dart' show findElement;
 import 'type_mask_test_helper.dart';
 
@@ -24,13 +24,14 @@
 };
 
 void main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    var compiler = result.compiler;
     var element = findElement(compiler, 'field');
     var typesTask = compiler.typesTask;
     var typesInferrer = typesTask.typesInferrer;
     Expect.equals(typesTask.uint31Type,
                   simplify(typesInferrer.getTypeOfElement(element), compiler),
                   'field');
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/mirror_helper_rename_test.dart b/tests/compiler/dart2js/mirror_helper_rename_test.dart
index 2428dfe..76d3adb 100644
--- a/tests/compiler/dart2js/mirror_helper_rename_test.dart
+++ b/tests/compiler/dart2js/mirror_helper_rename_test.dart
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 import 'dart:async';
 import "package:async_helper/async_helper.dart";
-import 'memory_compiler.dart' show compilerFor, OutputCollector;
+import 'memory_compiler.dart' show runCompiler, OutputCollector;
 import 'package:compiler/src/apiimpl.dart' show
     Compiler;
 import 'package:compiler/src/tree/tree.dart' show
@@ -14,80 +14,81 @@
 import 'package:compiler/src/mirror_renamer/mirror_renamer.dart';
 
 main() {
-  testWithMirrorHelperLibrary(minify: true);
-  testWithMirrorHelperLibrary(minify: false);
-  testWithoutMirrorHelperLibrary(minify: true);
-  testWithoutMirrorHelperLibrary(minify: false);
+  asyncTest(() async {
+    await testWithMirrorHelperLibrary(minify: true);
+    await testWithMirrorHelperLibrary(minify: false);
+    await testWithoutMirrorHelperLibrary(minify: true);
+    await testWithoutMirrorHelperLibrary(minify: false);
+  });
 }
 
-Future<Compiler> runCompiler({OutputCollector outputCollector,
-                              bool useMirrorHelperLibrary: false,
-                              bool minify: false}) {
+Future<Compiler> run({OutputCollector outputCollector,
+                      bool useMirrorHelperLibrary: false,
+                      bool minify: false}) async {
   List<String> options = ['--output-type=dart'];
   if (minify) {
     options.add('--minify');
   }
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES, outputProvider: outputCollector, options: options);
-  DartBackend backend = compiler.backend;
-  backend.useMirrorHelperLibrary = useMirrorHelperLibrary;
-  return
-      compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) => compiler);
+  var result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
+      outputProvider: outputCollector,
+      options: options,
+      beforeRun: (Compiler compiler) {
+        DartBackend backend = compiler.backend;
+        backend.useMirrorHelperLibrary = useMirrorHelperLibrary;
+      });
+  return result.compiler;
 }
 
-void testWithMirrorHelperLibrary({bool minify}) {
+Future testWithMirrorHelperLibrary({bool minify}) async {
   OutputCollector outputCollector = new OutputCollector();
-  asyncTest(() =>
-    runCompiler(outputCollector: outputCollector,
-                useMirrorHelperLibrary: true,
-                minify: minify)
-      .then((Compiler compiler) {
-    DartBackend backend = compiler.backend;
-    MirrorRenamerImpl mirrorRenamer = backend.mirrorRenamer;
-    Map<Node, String> renames = backend.placeholderRenamer.renames;
-    Map<String, String> symbols = mirrorRenamer.symbols;
+  Compiler compiler = await run(
+      outputCollector: outputCollector,
+      useMirrorHelperLibrary: true,
+      minify: minify);
+  DartBackend backend = compiler.backend;
+  MirrorRenamerImpl mirrorRenamer = backend.mirrorRenamer;
+  Map<Node, String> renames = backend.placeholderRenamer.renames;
+  Map<String, String> symbols = mirrorRenamer.symbols;
 
-    Expect.isFalse(null == mirrorRenamer.helperLibrary);
-    Expect.isFalse(null == mirrorRenamer.getNameFunction);
+  Expect.isFalse(null == mirrorRenamer.helperLibrary);
+  Expect.isFalse(null == mirrorRenamer.getNameFunction);
 
-    for (Node n in renames.keys) {
-      if (symbols.containsKey(renames[n])) {
-        if(n.toString() == 'getName') {
-          Expect.equals(
-              MirrorRenamerImpl.MIRROR_HELPER_GET_NAME_FUNCTION,
-              symbols[renames[n]]);
-        } else {
-          Expect.equals(n.toString(), symbols[renames[n]]);
-        }
+  for (Node n in renames.keys) {
+    if (symbols.containsKey(renames[n])) {
+      if(n.toString() == 'getName') {
+        Expect.equals(
+            MirrorRenamerImpl.MIRROR_HELPER_GET_NAME_FUNCTION,
+            symbols[renames[n]]);
+      } else {
+        Expect.equals(n.toString(), symbols[renames[n]]);
       }
     }
+  }
 
-    String output = outputCollector.getOutput('', 'dart');
-    String getNameMatch = MirrorRenamerImpl.MIRROR_HELPER_GET_NAME_FUNCTION;
-    Iterable i = getNameMatch.allMatches(output);
-    print(output);
-    if (minify) {
-      Expect.equals(0, i.length);
-    } else {
-      // Appears twice in code (defined & called).
-      Expect.equals(2, i.length);
-    }
+  String output = outputCollector.getOutput('', 'dart');
+  String getNameMatch = MirrorRenamerImpl.MIRROR_HELPER_GET_NAME_FUNCTION;
+  Iterable i = getNameMatch.allMatches(output);
+  print(output);
+  if (minify) {
+    Expect.equals(0, i.length);
+  } else {
+    // Appears twice in code (defined & called).
+    Expect.equals(2, i.length);
+  }
 
-    RegExp mapMatch = new RegExp('const<String,( )?String>');
-    i = mapMatch.allMatches(output);
-    Expect.equals(1, i.length);
-  }));
+  RegExp mapMatch = new RegExp('const<String,( )?String>');
+  i = mapMatch.allMatches(output);
+  Expect.equals(1, i.length);
 }
 
-void testWithoutMirrorHelperLibrary({bool minify}) {
-  asyncTest(() => runCompiler(useMirrorHelperLibrary: false, minify: minify).
-      then((Compiler compiler) {
-    DartBackend backend = compiler.backend;
-    MirrorRenamer mirrorRenamer = backend.mirrorRenamer;
+Future testWithoutMirrorHelperLibrary({bool minify}) async {
+  Compiler compiler = await run(useMirrorHelperLibrary: false, minify: minify);
+  DartBackend backend = compiler.backend;
+  MirrorRenamer mirrorRenamer = backend.mirrorRenamer;
 
-    Expect.equals(null, mirrorRenamer.helperLibrary);
-    Expect.equals(null, mirrorRenamer.getNameFunction);
-  }));
+  Expect.equals(null, mirrorRenamer.helperLibrary);
+  Expect.equals(null, mirrorRenamer.getNameFunction);
 }
 
 const MEMORY_SOURCE_FILES = const <String, String> {
diff --git a/tests/compiler/dart2js/mirror_helper_test.dart b/tests/compiler/dart2js/mirror_helper_test.dart
index e454c7e..e823b8b 100644
--- a/tests/compiler/dart2js/mirror_helper_test.dart
+++ b/tests/compiler/dart2js/mirror_helper_test.dart
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 import 'dart:async';
 import "package:async_helper/async_helper.dart";
-import 'memory_compiler.dart' show compilerFor;
+import 'memory_compiler.dart' show runCompiler;
 import 'package:compiler/src/apiimpl.dart' show
     Compiler;
 import 'package:compiler/src/elements/elements.dart' show
@@ -18,63 +18,62 @@
     MirrorRenamerImpl;
 
 main() {
-  testWithMirrorRenaming(minify: true);
-  testWithMirrorRenaming(minify: false);
-  testWithoutMirrorRenaming(minify: true);
-  testWithoutMirrorRenaming(minify: false);
+  asyncTest(() async {
+    await testWithMirrorRenaming(minify: true);
+    await testWithMirrorRenaming(minify: false);
+    await testWithoutMirrorRenaming(minify: true);
+    await testWithoutMirrorRenaming(minify: false);
+  });
 }
 
-Future<Compiler> runCompiler({useMirrorHelperLibrary: false, minify: false}) {
+Future<Compiler> run({useMirrorHelperLibrary: false, minify: false}) async {
   List<String> options = ['--output-type=dart'];
   if (minify) {
     options.add('--minify');
   }
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES, options: options);
+  var result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
+      options: options,
+      beforeRun: (Compiler compiler) {
+        DartBackend backend = compiler.backend;
+        backend.useMirrorHelperLibrary = useMirrorHelperLibrary;
+      });
+  return result.compiler;
+}
+
+Future testWithMirrorRenaming({bool minify}) async {
+  Compiler compiler = await run(useMirrorHelperLibrary: true, minify: minify);
   DartBackend backend = compiler.backend;
-  backend.useMirrorHelperLibrary = useMirrorHelperLibrary;
-  return
-      compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) => compiler);
+  MirrorRenamerImpl mirrorRenamer = backend.mirrorRenamer;
+  Map<Node, String> renames = backend.placeholderRenamer.renames;
+  Iterable<LibraryElement> imports =
+      backend.placeholderRenamer.platformImports.keys;
+
+  FunctionExpression node = backend.memberNodes.values.first.first;
+  Block block = node.body;
+  ExpressionStatement getNameFunctionNode = block.statements.nodes.head;
+  Send send = getNameFunctionNode.expression;
+
+  Expect.equals(renames[mirrorRenamer.getNameFunctionNode.name],
+                renames[send.selector]);
+  Expect.equals("",
+                renames[send.receiver]);
+  Expect.equals(1, imports.length);
 }
 
-void testWithMirrorRenaming({bool minify}) {
-  asyncTest(() => runCompiler(useMirrorHelperLibrary: true, minify: minify).
-      then((Compiler compiler) {
+Future testWithoutMirrorRenaming({bool minify}) async {
+  Compiler compiler = await run(useMirrorHelperLibrary: false, minify: minify);
+  DartBackend backend = compiler.backend;
+  Map<Node, String> renames = backend.placeholderRenamer.renames;
+  Iterable<LibraryElement> imports =
+      backend.placeholderRenamer.platformImports.keys;
+  FunctionExpression node = backend.memberNodes.values.first.first;
+  Block block = node.body;
+  ExpressionStatement getNameFunctionNode = block.statements.nodes.head;
+  Send send = getNameFunctionNode.expression;
 
-    DartBackend backend = compiler.backend;
-    MirrorRenamerImpl mirrorRenamer = backend.mirrorRenamer;
-    Map<Node, String> renames = backend.placeholderRenamer.renames;
-    Iterable<LibraryElement> imports =
-        backend.placeholderRenamer.platformImports.keys;
-
-    FunctionExpression node = backend.memberNodes.values.first.first;
-    Block block = node.body;
-    ExpressionStatement getNameFunctionNode = block.statements.nodes.head;
-    Send send = getNameFunctionNode.expression;
-
-    Expect.equals(renames[mirrorRenamer.getNameFunctionNode.name],
-                  renames[send.selector]);
-    Expect.equals("",
-                  renames[send.receiver]);
-    Expect.equals(1, imports.length);
-  }));
-}
-
-void testWithoutMirrorRenaming({bool minify}) {
-  asyncTest(() => runCompiler(useMirrorHelperLibrary: false, minify: minify).
-      then((Compiler compiler) {
-
-    DartBackend backend = compiler.backend;
-    Map<Node, String> renames = backend.placeholderRenamer.renames;
-    Iterable<LibraryElement> imports =
-        backend.placeholderRenamer.platformImports.keys;
-    FunctionExpression node = backend.memberNodes.values.first.first;
-    Block block = node.body;
-    ExpressionStatement getNameFunctionNode = block.statements.nodes.head;
-    Send send = getNameFunctionNode.expression;
-
-    Expect.isFalse(renames.containsKey(send.selector));
-    Expect.equals(1, imports.length);
-  }));
+  Expect.isFalse(renames.containsKey(send.selector));
+  Expect.equals(1, imports.length);
 }
 
 const MEMORY_SOURCE_FILES = const <String, String> {
diff --git a/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart b/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart
index defbf6c..47c8145 100644
--- a/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart
+++ b/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 import 'dart:async';
 import "package:async_helper/async_helper.dart";
-import 'memory_compiler.dart' show compilerFor;
+import 'memory_compiler.dart' show runCompiler;
 import 'package:compiler/src/apiimpl.dart' show
     Compiler;
 import 'package:compiler/src/dart_backend/dart_backend.dart' show
@@ -16,59 +16,60 @@
     MirrorRenamerImpl;
 
 main() {
-  testUniqueMinification();
-  testNoUniqueMinification();
+  asyncTest(() async {
+    await testUniqueMinification();
+    await testNoUniqueMinification();
+  });
 }
 
-Future<Compiler> runCompiler({useMirrorHelperLibrary: false, minify: false}) {
+Future<Compiler> run({useMirrorHelperLibrary: false, minify: false}) async {
   List<String> options = ['--output-type=dart'];
   if (minify) {
     options.add('--minify');
   }
-  Compiler compiler = compilerFor(MEMORY_SOURCE_FILES, options: options);
-  DartBackend backend = compiler.backend;
-  backend.useMirrorHelperLibrary = useMirrorHelperLibrary;
-  return
-      compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) => compiler);
+  var result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
+      options: options,
+      beforeRun: (Compiler compiler) {
+        DartBackend backend = compiler.backend;
+        backend.useMirrorHelperLibrary = useMirrorHelperLibrary;
+      });
+  return result.compiler;
 }
 
-void testUniqueMinification() {
-  asyncTest(() => runCompiler(useMirrorHelperLibrary: true, minify: true).
-      then((Compiler compiler) {
-    DartBackend backend = compiler.backend;
-    MirrorRenamerImpl mirrorRenamer = backend.mirrorRenamer;
-    Map<Node, String> renames = backend.placeholderRenamer.renames;
-    Map<String, String> symbols = mirrorRenamer.symbols;
+Future testUniqueMinification() async {
+  Compiler compiler = await run(useMirrorHelperLibrary: true, minify: true);
+  DartBackend backend = compiler.backend;
+  MirrorRenamerImpl mirrorRenamer = backend.mirrorRenamer;
+  Map<Node, String> renames = backend.placeholderRenamer.renames;
+  Map<String, String> symbols = mirrorRenamer.symbols;
 
-    // Check that no two different source code names get the same mangled name,
-    // with the exception of MirrorSystem.getName that gets renamed to the same
-    // mangled name as the getNameHelper from _mirror_helper.dart.
-    for (Node node in renames.keys) {
-      Identifier identifier = node.asIdentifier();
-      if (identifier != null) {
-        String source = identifier.source;
-        Send send = mirrorRenamer.mirrorSystemGetNameNodes.first;
-        if (send.selector == node)
-          continue;
-        if (symbols.containsKey(renames[node])) {
-          print(node);
-          Expect.equals(source, symbols[renames[node]]);
-        }
+  // Check that no two different source code names get the same mangled name,
+  // with the exception of MirrorSystem.getName that gets renamed to the same
+  // mangled name as the getNameHelper from _mirror_helper.dart.
+  for (Node node in renames.keys) {
+    Identifier identifier = node.asIdentifier();
+    if (identifier != null) {
+      String source = identifier.source;
+      Send send = mirrorRenamer.mirrorSystemGetNameNodes.first;
+      if (send.selector == node)
+        continue;
+      if (symbols.containsKey(renames[node])) {
+        print(node);
+        Expect.equals(source, symbols[renames[node]]);
       }
     }
-  }));
+  }
 }
 
-void testNoUniqueMinification() {
-  asyncTest(() => runCompiler(useMirrorHelperLibrary: false, minify: true).
-      then((Compiler compiler) {
-    DartBackend backend = compiler.backend;
-    Map<Node, String> renames = backend.placeholderRenamer.renames;
+Future testNoUniqueMinification() async {
+  Compiler compiler = await run(useMirrorHelperLibrary: false, minify: true);
+  DartBackend backend = compiler.backend;
+  Map<Node, String> renames = backend.placeholderRenamer.renames;
 
-    // 'Foo' appears twice and 'invocation' and 'hest' get the same mangled
-    // name.
-    Expect.equals(renames.values.toSet().length, renames.values.length - 2);
-  }));
+  // 'Foo' appears twice and 'invocation' and 'hest' get the same mangled
+  // name.
+  Expect.equals(renames.values.toSet().length, renames.values.length - 2);
 }
 
 const MEMORY_SOURCE_FILES = const <String, String> {
diff --git a/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart b/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart
index 6277637..8626b55 100644
--- a/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart
+++ b/tests/compiler/dart2js/mirror_private_name_inheritance_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:expect/expect.dart';
 import "package:async_helper/async_helper.dart";
-import 'memory_compiler.dart' show compilerFor;
+import 'memory_compiler.dart' show runCompiler;
 import 'compiler_helper.dart' show findElement;
 
 const MEMORY_SOURCE_FILES = const <String, String> {
@@ -36,8 +36,9 @@
 };
 
 void main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    var compiler = result.compiler;
 
     var superclass = findElement(compiler, 'Super', Uri.parse('memory:lib.dart'));
     var subclass = findElement(compiler, 'Subclass');
@@ -45,5 +46,5 @@
     print(superclass.lookupMember('_private'));
     Expect.isTrue(oracle(superclass.lookupMember('_private')));
     Expect.isFalse(oracle(subclass.lookupMember('_private')));
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/mirror_tree_shaking_test.dart b/tests/compiler/dart2js/mirror_tree_shaking_test.dart
index 4548a70..87accd5 100644
--- a/tests/compiler/dart2js/mirror_tree_shaking_test.dart
+++ b/tests/compiler/dart2js/mirror_tree_shaking_test.dart
@@ -13,9 +13,10 @@
 
 main() {
   DiagnosticCollector collector = new DiagnosticCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES, diagnosticHandler: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    CompilationResult result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES, diagnosticHandler: collector);
+    Compiler compiler = result.compiler;
     Expect.isTrue(collector.errors.isEmpty);
     Expect.isTrue(collector.infos.isEmpty);
     Expect.isFalse(compiler.compilationFailed);
@@ -27,7 +28,7 @@
     Expect.isFalse(compiler.disableTypeInference);
     JavaScriptBackend backend = compiler.backend;
     Expect.isFalse(backend.hasRetainedMetadata);
-  }));
+  });
 }
 
 const Map MEMORY_SOURCE_FILES = const {
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 2a525c9..c68281f 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -10,7 +10,7 @@
 import "package:async_helper/async_helper.dart";
 
 import 'memory_compiler.dart' show
-    compilerFor;
+    runCompiler;
 
 import 'package:compiler/src/apiimpl.dart' show
     Compiler;
@@ -50,11 +50,12 @@
 }
 
 void main() {
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  asyncTest(() async {
+    var result = await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       diagnosticHandler: new LegacyCompilerDiagnostics(expectOnlyVerboseInfo),
       options: ['--enable-experimental-mirrors']);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
+    Compiler compiler = result.compiler;
     print('');
     List generatedCode =
         Elements.sortedByPosition(compiler.enqueuer.codegen.generatedCode.keys);
@@ -147,7 +148,7 @@
     Expect.equals(
         1, fooConstantCount,
         "The type literal 'Foo' is duplicated or missing.");
-  }));
+  });
 }
 
 const MEMORY_SOURCE_FILES = const <String, String> {
diff --git a/tests/compiler/dart2js/missing_file_test.dart b/tests/compiler/dart2js/missing_file_test.dart
index 7d88eb8..26a4e9b 100644
--- a/tests/compiler/dart2js/missing_file_test.dart
+++ b/tests/compiler/dart2js/missing_file_test.dart
@@ -21,34 +21,28 @@
 ''',
 };
 
-Future runCompiler(Uri main, String expectedMessage) {
+Future runTest(Uri main, MessageKind expectedMessageKind) async {
   print("\n\n\n");
 
   DiagnosticCollector diagnostics = new DiagnosticCollector();
   OutputCollector output = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       diagnosticHandler: diagnostics,
       outputProvider: output);
 
-  return compiler.run(main).then((_) {
-    Expect.isFalse(output.hasExtraOutput);
-    Expect.equals(1, diagnostics.errors.length);
-    Expect.equals(expectedMessage, diagnostics.errors.first.message);
-  });
+  Expect.isFalse(output.hasExtraOutput);
+  Expect.equals(1, diagnostics.errors.length);
+  Expect.equals(expectedMessageKind, diagnostics.errors.first.message.kind);
 }
 
 void main() {
-  asyncTest(() => Future.forEach([
-  () => runCompiler(
-      Uri.parse('memory:main.dart'),
-      "Can't read 'memory:foo.dart' "
-      "(Exception: No such file memory:foo.dart)."),
-  () => runCompiler(
-      Uri.parse('memory:foo.dart'),
-      "Exception: No such file memory:foo.dart"),
-  () => runCompiler(
-      Uri.parse('dart:foo'),
-      "Library not found 'dart:foo'."),
-  ], (f) => f()));
+  asyncTest(() async {
+    await runTest(
+        Uri.parse('memory:main.dart'), MessageKind.READ_SCRIPT_ERROR);
+    await runTest(
+        Uri.parse('memory:foo.dart'), MessageKind.READ_SCRIPT_ERROR);
+    await runTest(
+        Uri.parse('dart:foo'), MessageKind.READ_SCRIPT_ERROR);
+  });
 }
diff --git a/tests/compiler/dart2js/mixin_constructor_default_parameter_values_test.dart b/tests/compiler/dart2js/mixin_constructor_default_parameter_values_test.dart
index 705eece..9d0fc86 100644
--- a/tests/compiler/dart2js/mixin_constructor_default_parameter_values_test.dart
+++ b/tests/compiler/dart2js/mixin_constructor_default_parameter_values_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Ensure that the inferrer looks at default values for parameters in
-// synthetic constructors using the correct context. If the constructor call 
+// synthetic constructors using the correct context. If the constructor call
 // to D without optional parameters is inferred using D's context, the default
 // value `_SECRET` will not be visible and compilation will fail.
 
@@ -42,7 +42,6 @@
 };
 
 main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);  
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')));
+  asyncTest(() => runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES));
 }
 
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 3284514..6f8cb51 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -166,8 +166,9 @@
   // warnings.
   void reportWarning(Spannable node, MessageKind messageKind,
                      [Map arguments = const {}]) {
+    MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
     reportDiagnostic(node,
-                     messageKind.message(arguments, terseDiagnostics),
+                     template.message(arguments, terseDiagnostics),
                      api.Diagnostic.WARNING);
   }
 
diff --git a/tests/compiler/dart2js/mock_libraries.dart b/tests/compiler/dart2js/mock_libraries.dart
index a9f96ef..c823f6b 100644
--- a/tests/compiler/dart2js/mock_libraries.dart
+++ b/tests/compiler/dart2js/mock_libraries.dart
@@ -196,6 +196,7 @@
   'patch': 'const patch = const _Patch(null);',
   'patch_full': 'const patch_full = const _Patch("full");',
   'patch_lazy': 'const patch_lazy = const _Patch("lazy");',
+  'patch_startup': 'const patch_startup = const _Patch("startup");',
   'propertyTypeCast': 'propertyTypeCast(x) {}',
   'propertyTypeCheck': 'propertyTypeCheck(value, property) {}',
   'requiresPreamble': 'requiresPreamble() {}',
diff --git a/tests/compiler/dart2js/number_output_test.dart b/tests/compiler/dart2js/number_output_test.dart
index 6ced21c..6f873a5 100644
--- a/tests/compiler/dart2js/number_output_test.dart
+++ b/tests/compiler/dart2js/number_output_test.dart
@@ -2,8 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "package:expect/expect.dart";
-import "package:async_helper/async_helper.dart";
+import 'dart:async';
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
 import 'memory_compiler.dart';
 
 const MEMORY_SOURCE_FILES = const {
@@ -15,35 +16,37 @@
           print(-22230000);
         }'''};
 
-void test({bool minify}) {
+Future test({bool minify}) async {
   OutputCollector collector = new OutputCollector();
-  var compiler = compilerFor(MEMORY_SOURCE_FILES,
-                             outputProvider: collector,
-                             options: minify ? ['--minify'] : []);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
-    // Check that we use the shorter exponential representations.
-    String jsOutput = collector.getOutput('', 'js');
-    print(jsOutput);
+  await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
+      outputProvider: collector,
+      options: minify ? ['--minify'] : []);
 
-    if (minify) {
-      Expect.isTrue(jsOutput.contains('123e5')); // Shorter than 12300000.
-      Expect.isFalse(jsOutput.contains('12300000'));
-      Expect.isTrue(jsOutput.contains('-2223e4')); // Shorter than -22230000.
-      Expect.isFalse(jsOutput.contains('-22230000'));
-    } else {
-      Expect.isTrue(jsOutput.contains('12300000'));
-      Expect.isTrue(jsOutput.contains('-22230000'));
-    }
-    Expect.isTrue(jsOutput.contains('12345678901234568e8'));
-    Expect.isTrue(jsOutput.contains('17976931348623157e292'));
-    Expect.isFalse(jsOutput.contains('1234567890123456789012345'));
-    // The decimal expansion of double.MAX_FINITE has 308 digits. We only check
-    // for its prefix.
-    Expect.isFalse(jsOutput.contains('179769313486231570814527423731'));
-  }));
+  // Check that we use the shorter exponential representations.
+  String jsOutput = collector.getOutput('', 'js');
+  print(jsOutput);
+
+  if (minify) {
+    Expect.isTrue(jsOutput.contains('123e5')); // Shorter than 12300000.
+    Expect.isFalse(jsOutput.contains('12300000'));
+    Expect.isTrue(jsOutput.contains('-2223e4')); // Shorter than -22230000.
+    Expect.isFalse(jsOutput.contains('-22230000'));
+  } else {
+    Expect.isTrue(jsOutput.contains('12300000'));
+    Expect.isTrue(jsOutput.contains('-22230000'));
+  }
+  Expect.isTrue(jsOutput.contains('12345678901234568e8'));
+  Expect.isTrue(jsOutput.contains('17976931348623157e292'));
+  Expect.isFalse(jsOutput.contains('1234567890123456789012345'));
+  // The decimal expansion of double.MAX_FINITE has 308 digits. We only check
+  // for its prefix.
+  Expect.isFalse(jsOutput.contains('179769313486231570814527423731'));
 }
 
 main() {
-  test(minify: true);
-  test(minify: false);
+  asyncTest(() async {
+    await test(minify: true);
+    await test(minify: false);
+  });
 }
diff --git a/tests/compiler/dart2js/package_root_test.dart b/tests/compiler/dart2js/package_root_test.dart
index f1e6ee6..122170c 100644
--- a/tests/compiler/dart2js/package_root_test.dart
+++ b/tests/compiler/dart2js/package_root_test.dart
@@ -12,6 +12,8 @@
 import 'package:expect/expect.dart';
 import 'package:compiler/compiler.dart'
        show DiagnosticHandler, Diagnostic, PackagesDiscoveryProvider;
+import 'package:compiler/src/dart2jslib.dart'
+       show MessageKind;
 import 'package:package_config/packages.dart';
 
 import 'memory_compiler.dart';
@@ -30,60 +32,58 @@
 
 final Uri PACKAGE_CONFIG_URI = Uri.parse('memory:package.config');
 
-void runCompiler(Uri main,
-                 bool checkError(DiagnosticMessage message),
-                 {Uri packageRoot,
-                  Uri packageConfig,
-                  PackagesDiscoveryProvider packagesDiscoveryProvider}) {
+Future runTest(Uri main,
+               MessageKind expectedMessageKind,
+               {Uri packageRoot,
+                Uri packageConfig,
+                PackagesDiscoveryProvider packagesDiscoveryProvider}) async {
   DiagnosticCollector collector = new DiagnosticCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
+  await runCompiler(
+      entryPoint: main,
+      memorySourceFiles: MEMORY_SOURCE_FILES,
       diagnosticHandler: collector,
       packageRoot: packageRoot,
       packageConfig: packageConfig,
       packagesDiscoveryProvider: packagesDiscoveryProvider);
-
-  asyncTest(() => compiler.run(main).then((_) {
-    Expect.equals(1, collector.errors.length,
-        "Unexpected errors: ${collector.errors}");
-    Expect.isTrue(checkError(collector.errors.first),
-        "Unexpected error: ${collector.errors.first}");
-  }));
+  Expect.equals(1, collector.errors.length,
+      "Unexpected errors: ${collector.errors}");
+  Expect.equals(expectedMessageKind, collector.errors.first.message.kind,
+      "Unexpected error: ${collector.errors.first}");
 }
 
 void main() {
-  Uri script = currentDirectory.resolveUri(Platform.script);
-  Uri packageRoot = script.resolve('./packages/');
+  asyncTest(() async {
+    Uri script = currentDirectory.resolveUri(Platform.script);
+    Uri packageRoot = script.resolve('./packages/');
 
-  PackagesDiscoveryProvider noPackagesDiscovery = (Uri uri) {
-    return new Future.value(Packages.noPackages);
-  };
+    PackagesDiscoveryProvider noPackagesDiscovery = (Uri uri) {
+      return new Future.value(Packages.noPackages);
+    };
 
-  bool containsErrorReading(DiagnosticMessage message) {
-    return message.message.contains("Error reading ");
-  }
+    await runTest(
+        Uri.parse('memory:main.dart'),
+        MessageKind.READ_SCRIPT_ERROR,
+        packageRoot: packageRoot);
+    await runTest(
+        Uri.parse('memory:main.dart'),
+        MessageKind.LIBRARY_NOT_FOUND,
+        packageConfig: PACKAGE_CONFIG_URI);
+    await runTest(
+        Uri.parse('memory:main.dart'),
+        MessageKind.LIBRARY_NOT_FOUND,
+        packagesDiscoveryProvider: noPackagesDiscovery);
 
-  bool isLibraryNotFound(DiagnosticMessage message) {
-    return message.message.startsWith("Library not found ");
-  }
-
-  runCompiler(Uri.parse('memory:main.dart'),
-              containsErrorReading,
-              packageRoot: packageRoot);
-  runCompiler(Uri.parse('memory:main.dart'),
-              isLibraryNotFound,
-              packageConfig: PACKAGE_CONFIG_URI);
-  runCompiler(Uri.parse('memory:main.dart'),
-              isLibraryNotFound,
-              packagesDiscoveryProvider: noPackagesDiscovery);
-
-  runCompiler(Uri.parse('package:foo/foo.dart'),
-              containsErrorReading,
-              packageRoot: packageRoot);
-  runCompiler(Uri.parse('package:foo/foo.dart'),
-              isLibraryNotFound,
-              packageConfig: PACKAGE_CONFIG_URI);
-  runCompiler(Uri.parse('package:foo/foo.dart'),
-              isLibraryNotFound,
-              packagesDiscoveryProvider: noPackagesDiscovery);
+    await runTest(
+        Uri.parse('package:foo/foo.dart'),
+        MessageKind.READ_SELF_ERROR,
+        packageRoot: packageRoot);
+    await runTest(
+        Uri.parse('package:foo/foo.dart'),
+        MessageKind.LIBRARY_NOT_FOUND,
+        packageConfig: PACKAGE_CONFIG_URI);
+    await runTest(
+        Uri.parse('package:foo/foo.dart'),
+        MessageKind.LIBRARY_NOT_FOUND,
+        packagesDiscoveryProvider: noPackagesDiscovery);
+  });
 }
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index ad7550c..4fe8790 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -42,23 +42,23 @@
   void reportFatalError(Spannable node,
                         MessageKind errorCode,
                         [Map arguments]) {
-    log(new Message(errorCode, arguments, false));
+    log(new Message(MessageTemplate.TEMPLATES[errorCode], arguments, false));
   }
 
   void reportError(Spannable node, MessageKind errorCode, [Map arguments]) {
-    log(new Message(errorCode, arguments, false));
+    log(new Message(MessageTemplate.TEMPLATES[errorCode], arguments, false));
   }
 
   void reportWarning(Spannable node, MessageKind errorCode, [Map arguments]) {
-    log(new Message(errorCode, arguments, false));
+    log(new Message(MessageTemplate.TEMPLATES[errorCode], arguments, false));
   }
 
   void reportInfo(Spannable node, MessageKind errorCode, [Map arguments]) {
-    log(new Message(errorCode, arguments, false));
+    log(new Message(MessageTemplate.TEMPLATES[errorCode], arguments, false));
   }
 
   void reportHint(Spannable node, MessageKind errorCode, [Map arguments]) {
-    log(new Message(errorCode, arguments, false));
+    log(new Message(MessageTemplate.TEMPLATES[errorCode], arguments, false));
   }
 
   withCurrentElement(Element element, f()) => f();
diff --git a/tests/compiler/dart2js/preserve_uris_test.dart b/tests/compiler/dart2js/preserve_uris_test.dart
index e0b8f1f..70d1d5e 100644
--- a/tests/compiler/dart2js/preserve_uris_test.dart
+++ b/tests/compiler/dart2js/preserve_uris_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
-import 'memory_compiler.dart' show compilerFor, OutputCollector;
+import 'memory_compiler.dart' show runCompiler, OutputCollector;
 
 const MEMORY_SOURCE_FILES = const <String, String> {
   'main.dart': """
@@ -39,24 +39,22 @@
 """
 };
 
-runTest(bool preserveUris) {
+runTest(bool preserveUris) async {
   OutputCollector collector = new OutputCollector();
   var options = ["--minify"];
   if (preserveUris) options.add("--preserve-uris");
-  var compiler = compilerFor(MEMORY_SOURCE_FILES,
-                             outputProvider: collector,
-                             options: options);
-  return compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
-    String jsOutput = collector.getOutput('', 'js');
-    Expect.equals(preserveUris, jsOutput.contains("main.dart"));
-    Expect.equals(preserveUris, jsOutput.contains("lib.dart"));
-  });
+  await runCompiler(
+      memorySourceFiles: MEMORY_SOURCE_FILES,
+      outputProvider: collector,
+      options: options);
+  String jsOutput = collector.getOutput('', 'js');
+  Expect.equals(preserveUris, jsOutput.contains("main.dart"));
+  Expect.equals(preserveUris, jsOutput.contains("lib.dart"));
 }
 
 void main() {
-  asyncStart();
-  new Future.value()
-    .then((_) => runTest(true))
-    .then((_) => runTest(false))
-    .whenComplete(asyncEnd);
+  asyncTest(() async {
+    await runTest(true);
+    await runTest(false);
+  });
 }
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index c25eb93..35c2ded 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -308,7 +308,9 @@
           .then((MockCompiler compiler) {
       Expect.equals(1, compiler.errors.length);
       Expect.equals(
-          new Message(MessageKind.DUPLICATE_DEFINITION, {'name': 'foo'}, false),
+          new Message(
+              MessageTemplate.TEMPLATES[MessageKind.DUPLICATE_DEFINITION],
+              {'name': 'foo'}, false),
           compiler.errors[0].message);
     })], (f) => f());
 }
@@ -491,7 +493,8 @@
 
     Expect.equals(
         new Message(
-            MessageKind.CANNOT_RESOLVE_TYPE,  {'typeName': 'Foo'}, false),
+            MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE],
+            {'typeName': 'Foo'}, false),
         compiler.warnings[0].message);
     VariableDefinitions definition = compiler.parsedTree;
     Expect.equals(warningNode, definition.type);
@@ -516,7 +519,8 @@
       compiler.parseScript("class Foo extends Bar {}");
       compiler.resolveStatement("Foo bar;");
       Expect.equals(1, compiler.errors.length);
-      var cannotResolveBar = new Message(MessageKind.CANNOT_EXTEND_MALFORMED,
+      var cannotResolveBar = new Message(
+          MessageTemplate.TEMPLATES[MessageKind.CANNOT_EXTEND_MALFORMED],
           {'className': 'Foo', 'malformedType': 'Bar'}, false);
       Expect.equals(cannotResolveBar, compiler.errors[0].message);
       compiler.clearMessages();
@@ -544,7 +548,8 @@
     Expect.equals(1, compiler.errors.length);
     Expect.equals(
         new Message(
-            MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'var'}, false),
+            MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE],
+            {'typeName': 'var'}, false),
         compiler.errors[0].message);
     compiler.clearMessages();
   });
@@ -557,7 +562,8 @@
     Expect.equals(1, compiler.errors.length);
     Expect.equals(
         new Message(
-            MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'bar'}, false),
+            MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE],
+            {'typeName': 'bar'}, false),
         compiler.errors[0].message);
     compiler.clearMessages();
 
diff --git a/tests/compiler/dart2js/semantic_visitor_test.dart b/tests/compiler/dart2js/semantic_visitor_test.dart
index 40b36ea..10833d3 100644
--- a/tests/compiler/dart2js/semantic_visitor_test.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test.dart
@@ -46,6 +46,7 @@
   final target;
   final targetType;
   final initializers;
+  final error;
 
   const Visit(this.method,
               {this.element,
@@ -67,7 +68,8 @@
                this.body,
                this.target,
                this.targetType,
-               this.initializers});
+               this.initializers,
+               this.error});
 
   int get hashCode => toString().hashCode;
 
@@ -136,6 +138,9 @@
     if (initializers != null) {
       sb.write(',initializers=$initializers');
     }
+    if (error != null) {
+      sb.write(',error=$error');
+    }
     return sb.toString();
   }
 }
@@ -211,6 +216,12 @@
   // Constant expression are currently not computed during resolution.
   VisitKind.VISIT_CONSTANT_GET,
   VisitKind.VISIT_CONSTANT_INVOKE,
+  // TODO(johnniwinther): Test these when ResolverVisitor.visitSendSet has been
+  // rewritten.
+  VisitKind.ERROR_INVALID_SET,
+  VisitKind.ERROR_INVALID_PREFIX,
+  VisitKind.ERROR_INVALID_POSTFIX,
+  VisitKind.ERROR_INVALID_COMPOUND,
 ];
 
 main(List<String> arguments) {
@@ -265,7 +276,7 @@
 Future test(Set<VisitKind> unvisitedKinds,
             List<String> arguments,
             Map<String, List<Test>> TESTS,
-            SemanticTestVisitor createVisitor(TreeElements elements)) {
+            SemanticTestVisitor createVisitor(TreeElements elements)) async {
   Map<String, String> sourceFiles = {};
   Map<String, Test> testMap = {};
   StringBuffer mainSource = new StringBuffer();
@@ -296,71 +307,71 @@
   mainSource.writeln("main() {}");
   sourceFiles['main.dart'] = mainSource.toString();
 
-  Compiler compiler = compilerFor(sourceFiles,
+  CompilationResult result = await runCompiler(
+      memorySourceFiles: sourceFiles,
       options: ['--analyze-all',
                 '--analyze-only',
                 '--enable-null-aware-operators']);
-  return compiler.run(Uri.parse('memory:main.dart')).then((_) {
-    testMap.forEach((String filename, Test test) {
-      LibraryElement library = compiler.libraryLoader.lookupLibrary(
-          Uri.parse('memory:$filename'));
-      Element element;
-      String cls = test.cls;
-      String method = test.method;
-      if (cls == null) {
-        element = library.find(method);
-      } else {
-        ClassElement classElement = library.find(cls);
-        Expect.isNotNull(classElement,
-                         "Class '$cls' not found in:\n"
-                         "${library.compilationUnit.script.text}");
-        element = classElement.localLookup(method);
-      }
-      var expectedVisits = test.expectedVisits;
-      if (expectedVisits == null) {
-        Expect.isTrue(element.isErroneous,
-            "Element '$method' expected to be have parse errors in:\n"
-            "${library.compilationUnit.script.text}");
-        return;
-      } else if (expectedVisits is! List) {
-        expectedVisits = [expectedVisits];
-      }
-      Expect.isFalse(element.isErroneous,
-          "Element '$method' is not expected to be have parse errors in:\n"
+  Compiler compiler = result.compiler;
+  testMap.forEach((String filename, Test test) {
+    LibraryElement library = compiler.libraryLoader.lookupLibrary(
+        Uri.parse('memory:$filename'));
+    Element element;
+    String cls = test.cls;
+    String method = test.method;
+    if (cls == null) {
+      element = library.find(method);
+    } else {
+      ClassElement classElement = library.find(cls);
+      Expect.isNotNull(classElement,
+                       "Class '$cls' not found in:\n"
+                       "${library.compilationUnit.script.text}");
+      element = classElement.localLookup(method);
+    }
+    var expectedVisits = test.expectedVisits;
+    if (expectedVisits == null) {
+      Expect.isTrue(element.isErroneous,
+          "Element '$method' expected to be have parse errors in:\n"
           "${library.compilationUnit.script.text}");
+      return;
+    } else if (expectedVisits is! List) {
+      expectedVisits = [expectedVisits];
+    }
+    Expect.isFalse(element.isErroneous,
+        "Element '$method' is not expected to be have parse errors in:\n"
+        "${library.compilationUnit.script.text}");
 
-      void testAstElement(AstElement astElement) {
-        Expect.isNotNull(astElement, "Element '$method' not found in:\n"
-                                     "${library.compilationUnit.script.text}");
-        ResolvedAst resolvedAst = astElement.resolvedAst;
-        SemanticTestVisitor visitor = createVisitor(resolvedAst.elements);
-        try {
-          compiler.withCurrentElement(resolvedAst.element, () {
-            //print(resolvedAst.node.toDebugString());
-            resolvedAst.node.accept(visitor);
-          });
-        } catch (e, s) {
-          Expect.fail("$e:\n$s\nIn test:\n"
-                      "${library.compilationUnit.script.text}");
-        }
-        Expect.listEquals(expectedVisits, visitor.visits,
-            "In test:\n"
-            "${library.compilationUnit.script.text}\n\n"
-            "Expected: $expectedVisits\n"
-            "Found: ${visitor.visits}");
-        unvisitedKinds.removeAll(visitor.visits.map((visit) => visit.method));
+    void testAstElement(AstElement astElement) {
+      Expect.isNotNull(astElement, "Element '$method' not found in:\n"
+                                   "${library.compilationUnit.script.text}");
+      ResolvedAst resolvedAst = astElement.resolvedAst;
+      SemanticTestVisitor visitor = createVisitor(resolvedAst.elements);
+      try {
+        compiler.withCurrentElement(resolvedAst.element, () {
+          //print(resolvedAst.node.toDebugString());
+          resolvedAst.node.accept(visitor);
+        });
+      } catch (e, s) {
+        Expect.fail("$e:\n$s\nIn test:\n"
+                    "${library.compilationUnit.script.text}");
       }
-      if (element.isAbstractField) {
-        AbstractFieldElement abstractFieldElement = element;
-        if (abstractFieldElement.getter != null) {
-          testAstElement(abstractFieldElement.getter);
-        } else if (abstractFieldElement.setter != null) {
-          testAstElement(abstractFieldElement.setter);
-        }
-      } else {
-        testAstElement(element);
+      Expect.listEquals(expectedVisits, visitor.visits,
+          "In test:\n"
+          "${library.compilationUnit.script.text}\n\n"
+          "Expected: $expectedVisits\n"
+          "Found: ${visitor.visits}");
+      unvisitedKinds.removeAll(visitor.visits.map((visit) => visit.method));
+    }
+    if (element.isAbstractField) {
+      AbstractFieldElement abstractFieldElement = element;
+      if (abstractFieldElement.getter != null) {
+        testAstElement(abstractFieldElement.getter);
+      } else if (abstractFieldElement.setter != null) {
+        testAstElement(abstractFieldElement.setter);
       }
-    });
+    } else {
+      testAstElement(element);
+    }
   });
 }
 
@@ -706,6 +717,21 @@
   ERROR_INVALID_ASSERT,
   ERROR_UNDEFINED_UNARY_EXPRESSION,
   ERROR_UNDEFINED_BINARY_EXPRESSION,
+  ERROR_INVALID_GET,
+  ERROR_INVALID_INVOKE,
+  ERROR_INVALID_SET,
+  ERROR_INVALID_PREFIX,
+  ERROR_INVALID_POSTFIX,
+  ERROR_INVALID_COMPOUND,
+  ERROR_INVALID_UNARY,
+  ERROR_INVALID_EQUALS,
+  ERROR_INVALID_NOT_EQUALS,
+  ERROR_INVALID_BINARY,
+  ERROR_INVALID_INDEX,
+  ERROR_INVALID_INDEX_SET,
+  ERROR_INVALID_COMPOUND_INDEX_SET,
+  ERROR_INVALID_INDEX_PREFIX,
+  ERROR_INVALID_INDEX_POSTFIX,
 
   VISIT_CONSTANT_GET,
   VISIT_CONSTANT_INVOKE,
diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
index 9a420d6..d1fa072 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
@@ -268,8 +268,8 @@
         class C {}
         m() => C.this(null, 42);
         ''',
-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
-                    name: 'this', arguments: '(null,42)')),
+        const Visit(VisitKind.ERROR_INVALID_INVOKE,
+                    error: MessageKind.THIS_PROPERTY, arguments: '(null,42)')),
     // TODO(johnniwinther): Expect [VISIT_FINAL_STATIC_FIELD_SET] instead.
     const Test(
         '''
@@ -744,6 +744,12 @@
                       name: 'o'),
         ],
         isDeferred: true),
+    const Test.prefix(
+        '''
+        ''',
+        'm() => p;',
+        const Visit(VisitKind.ERROR_INVALID_GET,
+                    error: MessageKind.PREFIX_AS_EXPRESSION)),
     const Test(
         '''
         var o;
@@ -956,6 +962,45 @@
         const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
                     name: 'o',
                     arguments: '(null,42)')),
+    const Test.prefix(
+        '''
+        o(a, b) {}
+        ''',
+        'm() => p.o(null, 42);',
+        const [
+          const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
+                      element: 'prefix(p)'),
+          const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INVOKE,
+                      element: 'function(o)',
+                      arguments: '(null,42)'),
+        ],
+        isDeferred: true),
+    const Test.prefix(
+        '''
+        ''',
+        'm() => p.o(null, 42);',
+        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
+                    name: 'o',
+                    arguments: '(null,42)')),
+    const Test.prefix(
+        '''
+        ''',
+        'm() => p.o(null, 42);',
+        const [
+          const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
+                      element: 'prefix(p)'),
+          const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
+                      name: 'o',
+                      arguments: '(null,42)'),
+        ],
+        isDeferred: true),
+    const Test.prefix(
+        '''
+        ''',
+        'm() => p(null, 42);',
+        const Visit(VisitKind.ERROR_INVALID_INVOKE,
+                    error: MessageKind.PREFIX_AS_EXPRESSION,
+                    arguments: '(null,42)')),
     // TODO(johnniwinther): Expect [VISIT_TOP_LEVEL_FUNCTION_SET] instead.
     const Test(
         '''
@@ -1685,6 +1730,19 @@
         ''',
         const Visit(VisitKind.ERROR_UNDEFINED_BINARY_EXPRESSION,
                     left: '2', operator: '!==', right: '3')),
+    const Test.clazz(
+        '''
+        class B {
+          operator +(_) => null;
+        }
+        class C extends B {
+          static m() => super + 42;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_BINARY,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    operator: '+',
+                    right: '42')),
   ],
   'Index': const [
     // Index
@@ -1732,6 +1790,18 @@
         '''
         class B {
           operator [](_) => null;
+        }
+        class C extends B {
+          static m() => super[42];
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_INDEX,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    index: '42')),
+    const Test.clazz(
+        '''
+        class B {
+          operator [](_) => null;
           operator []=(a, b) {}
         }
         class C extends B {
@@ -1787,6 +1857,20 @@
           operator []=(a, b) {}
         }
         class C extends B {
+          static m() => ++super[42];
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_INDEX_PREFIX,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    index: '42',
+                    operator: '++')),
+    const Test.clazz(
+        '''
+        class B {
+          operator [](_) => null;
+          operator []=(a, b) {}
+        }
+        class C extends B {
           m() => super[42]--;
         }
         ''',
@@ -1832,6 +1916,20 @@
                     getter: 'function(B#[])',
                     index: '42',
                     operator: '--')),
+    const Test.clazz(
+        '''
+        class B {
+          operator [](_) => null;
+          operator []=(a, b) {}
+        }
+        class C extends B {
+          static m() => super[42]--;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_INDEX_POSTFIX,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    index: '42',
+                    operator: '--')),
   ],
   'Equals': const [
     // Equals
@@ -1853,6 +1951,18 @@
         const Visit(VisitKind.VISIT_SUPER_EQUALS,
                     element: 'function(B#==)',
                     right: '42')),
+    const Test.clazz(
+        '''
+        class B {
+          operator ==(_) => null;
+        }
+        class C extends B {
+          static m() => super == 42;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_EQUALS,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    right: '42')),
   ],
   'Not equals': const [
     // Not equals
@@ -1874,6 +1984,18 @@
         const Visit(VisitKind.VISIT_SUPER_NOT_EQUALS,
                     element: 'function(B#==)',
                     right: '42')),
+    const Test.clazz(
+        '''
+        class B {
+          operator ==(_) => null;
+        }
+        class C extends B {
+          static m() => super != 42;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_NOT_EQUALS,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    right: '42')),
   ],
   'Unary expression': const [
     // Unary expression
@@ -1921,6 +2043,18 @@
         ''',
         const Visit(VisitKind.VISIT_SUPER_UNARY,
                     element: 'function(B#~)', operator: '~')),
+    const Test.clazz(
+        '''
+        class B {
+          operator -() => null;
+        }
+        class C extends B {
+          static m() => -super;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_UNARY,
+                    error: MessageKind.NO_SUPER_IN_STATIC,
+                    operator: '-')),
     const Test(
         '''
         m() => !0;
@@ -1964,6 +2098,17 @@
         ''',
         const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_INDEX_SET,
             index: '1', rhs: '2')),
+    const Test.clazz(
+        '''
+        class B {
+          operator []=(a, b) {}
+        }
+        class C extends B {
+          static m() => super[1] = 2;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_INDEX_SET,
+            error: MessageKind.NO_SUPER_IN_STATIC, index: '1', rhs: '2')),
   ],
   'Compound assignment': const [
     // Compound assignment
@@ -2466,6 +2611,19 @@
         const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_COMPOUND_INDEX_SET,
             getter: 'function(B#[])',
             index: '1', operator: '+=', rhs: '42')),
+    const Test.clazz(
+        '''
+        class B {
+          operator [](_) {}
+          operator []=(a, b) {}
+        }
+        class C extends B {
+          static m() => super[1] += 42;
+        }
+        ''',
+        const Visit(VisitKind.ERROR_INVALID_COMPOUND_INDEX_SET,
+            error: MessageKind.NO_SUPER_IN_STATIC,
+            index: '1', operator: '+=', rhs: '42')),
   ],
   'Prefix expression': const [
     // Prefix expression
diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart b/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
index 713a8c3..97531f3 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
@@ -38,6 +38,178 @@
   }
 
   @override
+  errorInvalidCompound(
+      Send node,
+      ErroneousElement error,
+      AssignmentOperator operator,
+      Node rhs,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_COMPOUND,
+        error: error.messageKind, operator: operator, rhs: rhs));
+    super.errorInvalidCompound(node, error, operator, rhs, arg);
+  }
+
+  @override
+  errorInvalidGet(
+      Send node,
+      ErroneousElement error,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_GET,
+        error: error.messageKind));
+    super.errorInvalidGet(node, error, arg);
+  }
+
+  @override
+  errorInvalidInvoke(
+      Send node,
+      ErroneousElement error,
+      NodeList arguments,
+      Selector selector,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_INVOKE,
+        error: error.messageKind, arguments: arguments));
+    super.errorInvalidInvoke(node, error, arguments, selector, arg);
+  }
+
+  @override
+  errorInvalidPostfix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_POSTFIX,
+        error: error.messageKind, operator: operator));
+    super.errorInvalidPostfix(node, error, operator, arg);
+  }
+
+  @override
+  errorInvalidPrefix(
+      Send node,
+      ErroneousElement error,
+      IncDecOperator operator,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_PREFIX,
+        error: error.messageKind, operator: operator));
+    super.errorInvalidPrefix(node, error, operator, arg);
+  }
+
+  @override
+  errorInvalidSet(
+      Send node,
+      ErroneousElement error,
+      Node rhs,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_SET,
+        error: error.messageKind, rhs: rhs));
+    super.errorInvalidSet(node, error, rhs, arg);
+  }
+
+  @override
+  errorInvalidUnary(
+      Send node,
+      UnaryOperator operator,
+      ErroneousElement error,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_UNARY,
+        error: error.messageKind, operator: operator));
+    super.errorInvalidUnary(node, operator, error, arg);
+  }
+
+  @override
+  errorInvalidEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_EQUALS,
+        error: error.messageKind, right: right));
+    super.errorInvalidEquals(node, error, right, arg);
+  }
+
+  @override
+  errorInvalidNotEquals(
+      Send node,
+      ErroneousElement error,
+      Node right,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_NOT_EQUALS,
+        error: error.messageKind, right: right));
+    super.errorInvalidNotEquals(node, error, right, arg);
+  }
+
+  @override
+  errorInvalidBinary(
+      Send node,
+      ErroneousElement error,
+      BinaryOperator operator,
+      Node right,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_BINARY,
+        error: error.messageKind, operator: operator, right: right));
+    super.errorInvalidBinary(node, error, operator, right, arg);
+  }
+
+  @override
+  errorInvalidIndex(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_INDEX,
+        error: error.messageKind, index: index));
+    super.errorInvalidIndex(node, error, index, arg);
+  }
+
+  @override
+  errorInvalidIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      Node rhs,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_INDEX_SET,
+        error: error.messageKind, index: index, rhs: rhs));
+    super.errorInvalidIndexSet(node, error, index, rhs, arg);
+  }
+
+  @override
+  errorInvalidCompoundIndexSet(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      AssignmentOperator operator,
+      Node rhs,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_COMPOUND_INDEX_SET,
+        error: error.messageKind, index: index, operator: operator, rhs: rhs));
+    super.errorInvalidCompoundIndexSet(node, error, index, operator, rhs, arg);
+  }
+
+  @override
+  errorInvalidIndexPrefix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_INDEX_PREFIX,
+        error: error.messageKind, index: index, operator: operator));
+    super.errorInvalidIndexPrefix(node, error, index, operator, arg);
+  }
+
+  @override
+  errorInvalidIndexPostfix(
+      Send node,
+      ErroneousElement error,
+      Node index,
+      IncDecOperator operator,
+      arg) {
+    visits.add(new Visit(VisitKind.ERROR_INVALID_INDEX_POSTFIX,
+        error: error.messageKind, index: index, operator: operator));
+    super.errorInvalidIndexPostfix(node, error, index, operator, arg);
+  }
+
+  @override
   visitBinary(
       Send node,
       Node left,
diff --git a/tests/compiler/dart2js/serialization_analysis_test.dart b/tests/compiler/dart2js/serialization_analysis_test.dart
index 775f6741..147c82b 100644
--- a/tests/compiler/dart2js/serialization_analysis_test.dart
+++ b/tests/compiler/dart2js/serialization_analysis_test.dart
@@ -176,12 +176,15 @@
   Deserializer deserializer = new Deserializer.fromText(
       serializedData, const JsonSerializationDecoder());
   DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
-  Compiler compiler = compilerFor(
-      test != null ? test.sourceFiles : const {},
+  await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: test != null ? test.sourceFiles : const {},
       options: ['--analyze-only', '--output-type=dart'],
-      diagnosticHandler: diagnosticCollector);
-  compiler.serialization.deserializer = new _DeserializerSystem(deserializer);
-  await compiler.runCompiler(entryPoint);
+      diagnosticHandler: diagnosticCollector,
+      beforeRun: (Compiler compiler) {
+        compiler.serialization.deserializer =
+            new _DeserializerSystem(deserializer);
+      });
   if (test != null) {
     Expect.equals(test.expectedErrorCount, diagnosticCollector.errors.length,
         "Unexpected error count.");
diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization_test.dart
index a258c2d..5f4b19b 100644
--- a/tests/compiler/dart2js/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization_test.dart
@@ -43,9 +43,10 @@
   if (entryPoint == null) {
     entryPoint = Uri.parse('dart:core');
   }
-  Compiler compiler = compilerFor({}, options: ['--analyze-all']);
   asyncTest(() async {
-    await compiler.runCompiler(entryPoint);
+    CompilationResult result = await runCompiler(
+        entryPoint: entryPoint, options: ['--analyze-all']);
+    Compiler compiler = result.compiler;
     testSerialization(compiler.libraryLoader.libraries,
                       outPath: outPath,
                       prettyPrint: prettyPrint);
diff --git a/tests/compiler/dart2js/show_package_warnings_test.dart b/tests/compiler/dart2js/show_package_warnings_test.dart
index de518f9..5673032 100644
--- a/tests/compiler/dart2js/show_package_warnings_test.dart
+++ b/tests/compiler/dart2js/show_package_warnings_test.dart
@@ -4,9 +4,9 @@
 
 // Test that the '--show-package-warnings' option works as intended.
 
+import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-
 import 'memory_compiler.dart';
 
 /// Error code that creates 1 warning, 1 hint, and 1 info.
@@ -42,42 +42,36 @@
 import 'package:pkg_error2/pkg_error2.dart';
 """};
 
-void test(List<Uri> entryPoints,
-          {bool showPackageWarnings: false,
-           int warnings: 0,
-           int hints: 0,
-           int infos: 0}) {
+Future test(Uri entryPoint,
+            {bool showPackageWarnings: false,
+             int warnings: 0,
+             int hints: 0,
+             int infos: 0}) async {
   var options = ['--analyze-only', '--analyze-all'];
   if (showPackageWarnings) {
     options.add('--show-package-warnings');
   }
   var collector = new DiagnosticCollector();
-  var compiler = compilerFor(SOURCE,
-                             options: options,
-                             packageRoot: Uri.parse('memory:pkg/'),
-                             diagnosticHandler: collector);
-  Uri mainUri = null;
-  if (entryPoints.length == 1) {
-    mainUri = entryPoints[0];
-  } else {
-    compiler.librariesToAnalyzeWhenRun = entryPoints;
-  }
-  asyncTest(() => compiler.run(mainUri).then((_) {
-    print('==================================================================');
-    print('test: $entryPoints showPackageWarnings=$showPackageWarnings');
-    Expect.equals(0, collector.errors.length,
-                  'Unexpected errors: ${collector.errors}');
-    Expect.equals(warnings, collector.warnings.length,
-                  'Unexpected warnings: ${collector.warnings}');
-    checkUriSchemes(collector.warnings);
-    Expect.equals(hints, collector.hints.length,
-                  'Unexpected hints: ${collector.hints}');
-    checkUriSchemes(collector.hints);
-    Expect.equals(infos, collector.infos.length,
-                  'Unexpected infos: ${collector.infos}');
-    checkUriSchemes(collector.infos);
-    print('==================================================================');
-  }));
+  await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: SOURCE,
+      options: options,
+      packageRoot: Uri.parse('memory:pkg/'),
+      diagnosticHandler: collector);
+  print('==================================================================');
+  print('test: $entryPoint showPackageWarnings=$showPackageWarnings');
+  Expect.equals(0, collector.errors.length,
+                'Unexpected errors: ${collector.errors}');
+  Expect.equals(warnings, collector.warnings.length,
+                'Unexpected warnings: ${collector.warnings}');
+  checkUriSchemes(collector.warnings);
+  Expect.equals(hints, collector.hints.length,
+                'Unexpected hints: ${collector.hints}');
+  checkUriSchemes(collector.hints);
+  Expect.equals(infos, collector.infos.length,
+                'Unexpected infos: ${collector.infos}');
+  checkUriSchemes(collector.infos);
+  print('==================================================================');
 }
 
 void checkUriSchemes(Iterable<DiagnosticMessage> messages) {
@@ -90,28 +84,36 @@
 }
 
 void main() {
-  test([Uri.parse('memory:main.dart')],
-       showPackageWarnings: true,
-       // From error.dart, package:pkg_error1 and package:pkg_error2:
-       warnings: 3, hints: 3, infos: 3);
-  test([Uri.parse('memory:main.dart')],
-       showPackageWarnings: false,
-       // From error.dart only:
-       warnings: 1, hints: 1 + 2 /* from summary */, infos: 1);
-  test([Uri.parse('package:pkg_error1/pkg_error1.dart')],
-       showPackageWarnings: true,
-       // From package:pkg_error1 and package:pkg_error2:
-       warnings: 2, hints: 2, infos: 2);
-  test([Uri.parse('package:pkg_error1/pkg_error1.dart')],
-       showPackageWarnings: false,
-       // From package:pkg_error1/pkg_error1.dart only:
-       warnings: 1, hints: 1 + 1 /* from summary */, infos: 1);
-  test([Uri.parse('package:pkg_noerror/pkg_noerror.dart')],
-       showPackageWarnings: true,
-       // From package:pkg_error1 and package:pkg_error2:
-       warnings: 2, hints: 2, infos: 2);
-  test([Uri.parse('package:pkg_noerror/pkg_noerror.dart')],
-       showPackageWarnings: false,
-       hints: 2 /* from summary */);
+  asyncTest(() async {
+    await test(
+        Uri.parse('memory:main.dart'),
+        showPackageWarnings: true,
+        // From error.dart, package:pkg_error1 and package:pkg_error2:
+        warnings: 3, hints: 3, infos: 3);
+    await test(
+        Uri.parse('memory:main.dart'),
+        showPackageWarnings: false,
+        // From error.dart only:
+        warnings: 1, hints: 1 + 2 /* from summary */, infos: 1);
+    await test(
+        Uri.parse('package:pkg_error1/pkg_error1.dart'),
+        showPackageWarnings: true,
+        // From package:pkg_error1 and package:pkg_error2:
+        warnings: 2, hints: 2, infos: 2);
+    await test(
+        Uri.parse('package:pkg_error1/pkg_error1.dart'),
+        showPackageWarnings: false,
+        // From package:pkg_error1/pkg_error1.dart only:
+        warnings: 1, hints: 1 + 1 /* from summary */, infos: 1);
+    await test(
+        Uri.parse('package:pkg_noerror/pkg_noerror.dart'),
+        showPackageWarnings: true,
+        // From package:pkg_error1 and package:pkg_error2:
+        warnings: 2, hints: 2, infos: 2);
+    await test(
+        Uri.parse('package:pkg_noerror/pkg_noerror.dart'),
+        showPackageWarnings: false,
+        hints: 2 /* from summary */);
+  });
 }
 
diff --git a/tests/compiler/dart2js/source_map_name_test.dart b/tests/compiler/dart2js/source_map_name_test.dart
index 110fff5..46aeb86 100644
--- a/tests/compiler/dart2js/source_map_name_test.dart
+++ b/tests/compiler/dart2js/source_map_name_test.dart
@@ -81,8 +81,9 @@
 
 main() {
   asyncTest(() async {
-    Compiler compiler = compilerFor({'main.dart': SOURCE});
-    await compiler.run(Uri.parse('memory:main.dart'));
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: {'main.dart': SOURCE});
+    Compiler compiler = result.compiler;
 
     Element lookup(String name) {
       Element element;
diff --git a/tests/compiler/dart2js/source_map_test.dart b/tests/compiler/dart2js/source_map_test.dart
index 021eb2e..3d3c2ea 100644
--- a/tests/compiler/dart2js/source_map_test.dart
+++ b/tests/compiler/dart2js/source_map_test.dart
@@ -30,7 +30,7 @@
   }
 }
 
-void test({String out, String sourceMap, String mapping, String file}) {
+test({String out, String sourceMap, String mapping, String file}) async {
   OutputCollector collector = new OutputCollector();
   List<String> options = <String>[];
   if (out != null) {
@@ -39,35 +39,37 @@
   if (sourceMap != null) {
     options.add("--source-map=$sourceMap");
   }
-  var compiler = compilerFor(SOURCE,
-                             showDiagnostics: true,
-                             outputProvider: collector,
-                             options: options);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:/main.dart')).then(
-      (_) {
-    String jsOutput = collector.getOutput('', 'js');
-    Expect.isNotNull(jsOutput);
-    if (mapping != null) {
-      find(jsOutput, '//# sourceMappingURL=$mapping', true);
-    } else {
-      find(jsOutput, '//# sourceMappingURL=', false);
-    }
-    String jsSourceMapOutput = collector.getOutput('', 'js.map');
-    Expect.isNotNull(jsSourceMapOutput);
-    if (file != null) {
-      find(jsSourceMapOutput, '"file": "$file"', true);
-    } else {
-      find(jsSourceMapOutput, '"file": ', false);
-    }
-  }));
+
+  await runCompiler(
+      entryPoint: Uri.parse('memory:/main.dart'),
+      memorySourceFiles: SOURCE,
+      showDiagnostics: true,
+      outputProvider: collector,
+      options: options);
+  String jsOutput = collector.getOutput('', 'js');
+  Expect.isNotNull(jsOutput);
+  if (mapping != null) {
+    find(jsOutput, '//# sourceMappingURL=$mapping', true);
+  } else {
+    find(jsOutput, '//# sourceMappingURL=', false);
+  }
+  String jsSourceMapOutput = collector.getOutput('', 'js.map');
+  Expect.isNotNull(jsSourceMapOutput);
+  if (file != null) {
+    find(jsSourceMapOutput, '"file": "$file"', true);
+  } else {
+    find(jsSourceMapOutput, '"file": ', false);
+  }
 }
 
 void main() {
-  test();
-  test(sourceMap: 'file:/out.js.map');
-  test(out: 'file:/out.js');
-  test(out: 'file:/out.js', sourceMap: 'file:/out.js.map',
-       file: 'out.js', mapping: 'out.js.map');
-  test(out: 'file:/dir/out.js', sourceMap: 'file:/dir/out.js.map',
-       file: 'out.js', mapping: 'out.js.map');
+  asyncTest(() async {
+    await test();
+    await test(sourceMap: 'file:/out.js.map');
+    await test(out: 'file:/out.js');
+    await test(out: 'file:/out.js', sourceMap: 'file:/out.js.map',
+               file: 'out.js', mapping: 'out.js.map');
+    await test(out: 'file:/dir/out.js', sourceMap: 'file:/dir/out.js.map',
+               file: 'out.js', mapping: 'out.js.map');
+  });
 }
\ No newline at end of file
diff --git a/tests/compiler/dart2js/sourcemaps/colors.dart b/tests/compiler/dart2js/sourcemaps/colors.dart
index 8241dd1..10aa511 100644
--- a/tests/compiler/dart2js/sourcemaps/colors.dart
+++ b/tests/compiler/dart2js/sourcemaps/colors.dart
@@ -8,8 +8,8 @@
 
 /// A web color.
 abstract class Color {
-  /// The hexadecimal code for the color, without the prefixed '#'.
-  String get toHex;
+  /// The css code for the color.
+  String get toCss;
 }
 
 /// A web color defined as RGB.
@@ -22,8 +22,9 @@
   /// all in range 0..1.
   const RGB(this.r, this.g, this.b);
 
-  String get toHex {
+  String get toCss {
     StringBuffer sb = new StringBuffer();
+    sb.write('#');
 
     void writeHex(double value) {
       int i = (value * 255.0).round();
@@ -43,6 +44,37 @@
   String toString() => 'rgb($r,$g,$b)';
 }
 
+class RGBA extends RGB {
+  final double a;
+
+  const RGBA(double r, double g, double b, this.a) : super(r, g, b);
+
+  String get toCss {
+    StringBuffer sb = new StringBuffer();
+
+    void writeInt(double value) {
+      int i = (value * 255.0).round();
+      if (i < 16) {
+        sb.write('0');
+      }
+      sb.write(i);
+    }
+
+    sb.write('rgba(');
+    writeInt(r);
+    sb.write(', ');
+    writeInt(g);
+    sb.write(', ');
+    writeInt(b);
+    sb.write(', ');
+    sb.write(a);
+    sb.write(')');
+
+    return sb.toString();
+  }
+
+}
+
 /// A web color defined as HSV.
 class HSV implements Color {
   final double h;
@@ -53,7 +85,7 @@
   /// saturation [s] in range 0..1, and value [v] in range 0..1.
   const HSV(this.h, this.s, this.v);
 
-  String get toHex => toRGB(this).toHex;
+  String get toCss => toRGB(this).toCss;
 
   static RGB toRGB(HSV hsv) {
     double h = hsv.h;
diff --git a/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart b/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
index 83a5ef3..91670bc 100644
--- a/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
+++ b/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
@@ -5,7 +5,6 @@
 // Test file for testing source mappings of invocations.
 
 var counter = 0;
-var bucket;
 
 main(args) {
   counter++;
diff --git a/tests/compiler/dart2js/sourcemaps/operators_test_file.dart b/tests/compiler/dart2js/sourcemaps/operators_test_file.dart
new file mode 100644
index 0000000..bbd85c0
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/operators_test_file.dart
@@ -0,0 +1,60 @@
+// 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.
+
+// Test file for testing source mappings of operations.
+
+var counter = 0;
+
+void record(result) {
+  counter++;
+}
+
+main(args) {
+  counter++;
+  operations(args.length > 0,
+      0, 1.5, args[0], new Complex(0, 1), new Complex(1.5, 2.5));
+  return counter;
+}
+
+void operations(cond, a, b, c, d, e) {
+  if (cond) record(a + a);
+  if (cond) record(a + b);
+  if (cond) record(a + c);
+  if (cond) record(a + d);
+  if (cond) record(a + e);
+  if (cond) record(b + a);
+  if (cond) record(b + b);
+  if (cond) record(b + c);
+  if (cond) record(b + d);
+  if (cond) record(b + e);
+  if (cond) record(c + a);
+  if (cond) record(c + b);
+  if (cond) record(c + c);
+  if (cond) record(c + d);
+  if (cond) record(c + e);
+  if (cond) record(d + a);
+  if (cond) record(d + b);
+  if (cond) record(d + c);
+  if (cond) record(d + d);
+  if (cond) record(d + e);
+  if (cond) record(e + a);
+  if (cond) record(e + b);
+  if (cond) record(e + c);
+  if (cond) record(e + d);
+  if (cond) record(e + e);
+}
+
+class Complex {
+  final num re;
+  final num im;
+
+  const Complex(this.re, this.im);
+
+  operator +(Complex other) => new Complex(re + other.re, im + other.im);
+
+  // TODO(johnniwinther): Support implicit null check in '=='.
+  //operator ==(Complex other) => re == other.re && im == other.im;
+
+  int get hashCode => 13 * re.hashCode + 17 * im.hashCode;
+}
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_invokes_test.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_invokes_test.dart
new file mode 100644
index 0000000..20359e4
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/source_mapping_invokes_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'source_mapping_tester.dart' as tester;
+
+void main() {
+  tester.main(['invokes']);
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_operators_test.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_operators_test.dart
new file mode 100644
index 0000000..908ef87
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/source_mapping_operators_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'source_mapping_tester.dart' as tester;
+
+void main() {
+  tester.main(['operators']);
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart
deleted file mode 100644
index 551bf40..0000000
--- a/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
-import 'sourcemap_helper.dart';
-import 'sourcemap_html_helper.dart';
-import 'package:compiler/src/filenames.dart';
-
-main(List<String> arguments) {
-  bool showAll = false;
-  bool measure = false;
-  Uri outputUri;
-  Set<String> configurations = new Set<String>();
-  for (String argument in arguments) {
-    if (argument.startsWith('-')) {
-      if (argument == '-a') {
-        /// Generate visualization for all user methods.
-        showAll = true;
-      } else if (argument == '-m') {
-        /// Measure instead of reporting the number of missing code points.
-        measure = true;
-      } else if (argument.startsWith('--out=')) {
-        /// Generate visualization for the first configuration.
-        outputUri = Uri.base.resolve(
-            nativeToUriPath(argument.substring('--out='.length)));
-      } else if (argument.startsWith('-o')) {
-        /// Generate visualization for the first configuration.
-        outputUri = Uri.base.resolve(
-            nativeToUriPath(argument.substring('-o'.length)));
-      } else {
-        print("Unknown option '$argument'.");
-        return;
-      }
-    } else {
-      if (TEST_CONFIGURATIONS.containsKey(argument)) {
-        configurations.add(argument);
-      } else {
-        print("Unknown configuration '$argument'. "
-              "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}'");
-        return;
-      }
-    }
-  }
-
-  if (configurations.isEmpty) {
-    configurations.addAll(TEST_CONFIGURATIONS.keys);
-  }
-  String outputConfig = configurations.first;
-
-  asyncTest(() async {
-    List<Measurement> measurements = <Measurement>[];
-    for (String config in configurations) {
-      List<String> options = TEST_CONFIGURATIONS[config];
-      Measurement measurement = await runTests(
-          config,
-          options,
-          showAll: showAll,
-          measure: measure,
-          outputUri: outputConfig == config ? outputUri : null);
-      if (measurement != null) {
-        measurements.add(measurement);
-      }
-    }
-    for (Measurement measurement in measurements) {
-      print(measurement);
-    }
-  });
-}
-
-const Map<String, List<String>> TEST_CONFIGURATIONS = const {
-  'old': const [],
-  'ssa': const ['--use-new-source-info', ],
-  'cps': const ['--use-new-source-info', '--use-cps-ir'],
-};
-
-Future<Measurement> runTests(
-    String config,
-    List<String> options,
-    {bool showAll: false,
-     Uri outputUri,
-     bool measure: false}) async {
-  if (config == 'old' && !measure) return null;
-
-  String filename =
-      'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart';
-  SourceMapProcessor processor = new SourceMapProcessor(filename);
-  List<SourceMapInfo> infoList = await processor.process(
-      ['--csp', '--disable-inlining']
-      ..addAll(options),
-      verbose: !measure);
-  List<SourceMapInfo> userInfoList = <SourceMapInfo>[];
-  List<SourceMapInfo> failureList = <SourceMapInfo>[];
-  Measurement measurement = new Measurement(config);
-  for (SourceMapInfo info in infoList) {
-    if (info.element.library.isPlatformLibrary) continue;
-    userInfoList.add(info);
-    Iterable<CodePoint> missingCodePoints =
-        info.codePoints.where((c) => c.isMissing);
-    measurement.missing += missingCodePoints.length;
-    measurement.count += info.codePoints.length;
-    if (!measure) {
-      if (!missingCodePoints.isEmpty) {
-        print("Missing code points for ${info.element} in '$filename':");
-        for (CodePoint codePoint in missingCodePoints) {
-          print("  $codePoint");
-        }
-        failureList.add(info);
-      }
-    }
-  }
-  if (failureList.isNotEmpty) {
-    if (outputUri == null) {
-      if (!measure) {
-        Expect.fail(
-            "Missing code points found. "
-            "Run the test with a URI option, "
-            "`source_mapping_test --out=<uri> $config`, to "
-            "create a html visualization of the missing code points.");
-      }
-    } else {
-      createTraceSourceMapHtml(outputUri, processor,
-                               showAll ? userInfoList : failureList);
-    }
-  } else if (outputUri != null) {
-    createTraceSourceMapHtml(outputUri, processor, userInfoList);
-  }
-  return measurement;
-}
-
-class Measurement {
-  final String config;
-  int missing = 0;
-  int count = 0;
-
-  Measurement(this.config);
-
-  String toString() {
-    double percentage = 100 * missing / count;
-    return "Config '${config}': $missing of $count ($percentage%) missing";
-  }
-}
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart
new file mode 100644
index 0000000..4691568
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/source_mapping_test_viewer.dart
@@ -0,0 +1,166 @@
+// 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.
+
+/// Visualization of source mappings generated and tested in
+/// 'source_mapping_test.dart'.
+
+library source_mapping.test.viewer;
+
+import 'dart:async';
+import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/util/util.dart';
+import 'source_mapping_tester.dart';
+import 'sourcemap_helper.dart';
+import 'sourcemap_html_helper.dart';
+import 'sourcemap_html_templates.dart';
+
+const String DEFAULT_OUTPUT_PATH = 'out.js.map.html';
+
+main(List<String> arguments) async {
+  bool measure = false;
+  String outputPath = DEFAULT_OUTPUT_PATH;
+  Set<String> configurations = new Set<String>();
+  Set<String> files = new Set<String>();
+  for (String argument in arguments) {
+    if (argument.startsWith('-')) {
+      if (argument == '-m') {
+        /// Measure instead of reporting the number of missing code points.
+        measure = true;
+      } else if (argument.startsWith('--out=')) {
+        /// Generate visualization for the first configuration.
+        outputPath = argument.substring('--out='.length);
+
+      } else if (argument.startsWith('-o')) {
+        /// Generate visualization for the first configuration.
+        outputPath = argument.substring('-o'.length);
+      } else {
+        print("Unknown option '$argument'.");
+        return;
+      }
+    } else {
+      if (!parseArgument(argument, configurations, files)) {
+        return;
+      }
+    }
+  }
+
+  if (configurations.isEmpty) {
+    configurations.addAll(TEST_CONFIGURATIONS.keys);
+    if (!measure) {
+      configurations.remove('old');
+    }
+  }
+  if (files.isEmpty) {
+    files.addAll(TEST_FILES.keys);
+  }
+
+  OutputConfigurations outputConfigurations =
+      new OutputConfigurations(configurations, files);
+  bool generateMultiConfigs = false;
+  if (outputPath != null) {
+    if (configurations.length > 1 || files.length > 1) {
+      for (String config in configurations) {
+        for (String file in files) {
+          String path = '$outputPath.$config.$file';
+          Uri uri = Uri.base.resolve(nativeToUriPath(path));
+          outputConfigurations.registerPathUri(config, file, path, uri);
+        }
+      }
+      generateMultiConfigs = true;
+    } else {
+      outputConfigurations.registerPathUri(
+          configurations.first,
+          files.first,
+          outputPath,
+          Uri.base.resolve(nativeToUriPath(outputPath)));
+    }
+  }
+
+  List<Measurement> measurements = <Measurement>[];
+  for (String config in configurations) {
+    List<String> options = TEST_CONFIGURATIONS[config];
+    for (String file in files) {
+      Measurement measurement = await runTest(
+          config, TEST_FILES[file], options,
+          outputUri: outputConfigurations.getUri(config, file),
+          verbose: !measure);
+      measurements.add(measurement);
+    }
+  }
+  for (Measurement measurement in measurements) {
+    print(measurement);
+  }
+  if (generateMultiConfigs) {
+    outputMultiConfigs(
+        Uri.base.resolve(outputPath),
+        outputConfigurations);
+  }
+}
+
+class OutputConfigurations implements Configurations {
+  final Iterable<String> configs;
+  final Iterable<String> files;
+  final Map<Pair, String> pathMap = {};
+  final Map<Pair, Uri> uriMap = {};
+
+  OutputConfigurations(this.configs, this.files);
+
+  void registerPathUri(String config, String file, String path, Uri uri) {
+    Pair key = new Pair(config, file);
+    pathMap[key] = path;
+    uriMap[key] = uri;
+  }
+
+  Uri getUri(String config, String file) {
+    Pair key = new Pair(config, file);
+    return uriMap[key];
+  }
+
+  @override
+  String getPath(String config, String file) {
+    Pair key = new Pair(config, file);
+    return pathMap[key];
+  }
+}
+
+Future<Measurement> runTest(
+    String config,
+    String filename,
+    List<String> options,
+    {Uri outputUri,
+     bool verbose}) async {
+  TestResult result =
+      await runTests(config, filename, options, verbose: verbose);
+  if (outputUri != null) {
+    if (result.failureMap.isNotEmpty) {
+      result.failureMap.forEach((info, missingCodePoints) {
+        print("Missing code points for ${info.element} in '$filename' "
+              "in config '$config':");
+        for (CodePoint codePoint in missingCodePoints) {
+          print("  $codePoint");
+        }
+      });
+    }
+    createTraceSourceMapHtml(outputUri, result.processor, result.userInfoList);
+  }
+  return new Measurement(config, filename,
+      result.failureMap.values.fold(0, (s, i) => s + i.length),
+      result.userInfoList.fold(0, (s, i) => s + i.codePoints.length));
+}
+
+class Measurement {
+  final String config;
+  final String filename;
+
+  final int missing;
+  final int count;
+
+  Measurement(this.config, this.filename, this.missing, this.count);
+
+  String toString() {
+    double percentage = 100 * missing / count;
+    return "Config '${config}', file: '${filename}': "
+           "$missing of $count ($percentage%) missing";
+  }
+}
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_tester.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_tester.dart
new file mode 100644
index 0000000..9e7d5b6
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/source_mapping_tester.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'sourcemap_helper.dart';
+
+main(List<String> arguments) {
+  Set<String> configurations = new Set<String>();
+  Set<String> files = new Set<String>();
+  for (String argument in arguments) {
+    if (!parseArgument(argument, configurations, files)) {
+      return;
+    }
+  }
+
+  if (configurations.isEmpty) {
+    configurations.addAll(TEST_CONFIGURATIONS.keys);
+    configurations.remove('old');
+  }
+  if (files.isEmpty) {
+    files.addAll(TEST_FILES.keys);
+  }
+
+  asyncTest(() async {
+    bool missingCodePointsFound = false;
+    for (String config in configurations) {
+      List<String> options = TEST_CONFIGURATIONS[config];
+      for (String file in files) {
+        String filename = TEST_FILES[file];
+        TestResult result = await runTests(config, filename, options);
+        if (result.failureMap.isNotEmpty) {
+          result.failureMap.forEach((info, missingCodePoints) {
+            print("Missing code points for ${info.element} in '$filename' "
+                  "in config '$config':");
+            for (CodePoint codePoint in missingCodePoints) {
+              print("  $codePoint");
+            }
+          });
+          missingCodePointsFound = true;
+        }
+      }
+    }
+    Expect.isFalse(missingCodePointsFound,
+        "Missing code points found. "
+        "Run the test with a URI option, "
+        "`source_mapping_test_viewer [--out=<uri>] [configs] [tests]`, to "
+        "create a html visualization of the missing code points.");
+  });
+}
+
+/// Parse [argument] for a valid configuration or test-file option.
+///
+/// On success, the configuration name is added to [configurations] or the
+/// test-file name is added to [files], and `true` is returned.
+/// On failure, a message is printed and `false` is returned.
+///
+bool parseArgument(String argument,
+                   Set<String> configurations,
+                   Set<String> files) {
+  if (TEST_CONFIGURATIONS.containsKey(argument)) {
+    configurations.add(argument);
+  } else if (TEST_FILES.containsKey(argument)) {
+    files.add(argument);
+  } else {
+    print("Unknown configuration or file '$argument'. "
+          "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}' or "
+          "'${TEST_FILES.keys.join("', '")}'.");
+    return false;
+  }
+  return true;
+}
+
+const Map<String, List<String>> TEST_CONFIGURATIONS = const {
+  'ssa': const ['--use-new-source-info', ],
+  'cps': const ['--use-new-source-info', '--use-cps-ir'],
+  'old': const [],
+};
+
+const Map<String, String> TEST_FILES = const <String, String>{
+  'invokes': 'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart',
+  'operators': 'tests/compiler/dart2js/sourcemaps/operators_test_file.dart',
+};
+
+Future<TestResult> runTests(
+    String config,
+    String filename,
+    List<String> options,
+    {bool verbose: true}) async {
+  SourceMapProcessor processor = new SourceMapProcessor(filename);
+  List<SourceMapInfo> infoList = await processor.process(
+      ['--csp', '--disable-inlining']
+      ..addAll(options),
+      verbose: verbose);
+  TestResult result = new TestResult(config, filename, processor);
+  for (SourceMapInfo info in infoList) {
+    if (info.element.library.isPlatformLibrary) continue;
+    result.userInfoList.add(info);
+    Iterable<CodePoint> missingCodePoints =
+        info.codePoints.where((c) => c.isMissing);
+    if (missingCodePoints.isNotEmpty) {
+      result.failureMap[info] = missingCodePoints;
+    }
+  }
+  return result;
+}
+
+class TestResult {
+  final String config;
+  final String file;
+  final SourceMapProcessor processor;
+  List<SourceMapInfo> userInfoList = <SourceMapInfo>[];
+  Map<SourceMapInfo, Iterable<CodePoint>> failureMap =
+      <SourceMapInfo, Iterable<CodePoint>>{};
+
+  TestResult(this.config, this.file, this.processor);
+}
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index 697bf02..1dbbc1f 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -256,7 +256,7 @@
       addLocation(null, nodeToString(node));
     } else {
       locationMap.forEach((int targetOffset, List<SourceLocation> locations) {
-        String jsCode = positionToString(targetOffset);
+        String jsCode = nodeToString(node);
         for (SourceLocation location in locations) {
           addLocation(location, jsCode);
         }
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
index eb1399a..4227fee 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
@@ -18,14 +18,26 @@
 import 'sourcemap_html_templates.dart';
 
 /// Returns the [index]th color for visualization.
-String toColor(int index) {
+HSV toColor(int index) {
   int hueCount = 24;
   double h = 360.0 * (index % hueCount) / hueCount;
   double v = 1.0;
   double s = 0.5;
-  HSV hsv = new HSV(h, s, v);
-  RGB rgb = HSV.toRGB(hsv);
-  return rgb.toHex;
+  return new HSV(h, s, v);
+}
+
+/// Return the CSS color value for the [index]th color.
+String toColorCss(int index) {
+  return toColor(index).toCss;
+}
+
+/// Return the CSS color value for the [index]th span.
+String toPattern(int index) {
+  /// Use gradient on spans to visually identify consecutive spans mapped to the
+  /// same source location.
+  HSV startColor = toColor(index);
+  HSV endColor = new HSV(startColor.h, startColor.s + 0.4, startColor.v - 0.2);
+  return 'linear-gradient(to right, ${startColor.toCss}, ${endColor.toCss})';
 }
 
 /// Return the html for the [index] line number.
@@ -131,7 +143,7 @@
         SourceLocation sourceLocation = lastSourceLocations.single;
         if (sourceLocation != null) {
           index = collection.getIndex(sourceLocation);
-          color = "background:#${toColor(index)};";
+          color = "background:${toPattern(index)};";
           title = sourceLocation.shortText;
           currentLocation = sourceLocation;
         }
@@ -151,7 +163,7 @@
         for (SourceLocation sourceLocation in lastSourceLocations) {
           if (sourceLocation == null) continue;
           int colorIndex = collection.getIndex(sourceLocation);
-          addColor('#${toColor(colorIndex)}');
+          addColor('${toColorCss(colorIndex)}');
           currentLocation = sourceLocation;
         }
         color = 'background: linear-gradient(to right${sb}); '
@@ -363,7 +375,7 @@
           codeBuffer.write(line.substring(0, start));
         }
         codeBuffer.write(
-            '<a name="${index}" style="background:#${toColor(index)};" '
+            '<a name="${index}" style="background:${toPattern(index)};" '
             'title="[${lineIndex + 1},${start + 1}]" '
             'onmouseover="highlight(\'$index\');" '
             'onmouseout="highlight();">');
@@ -393,14 +405,14 @@
       '<th>Dart code @ mapped location</th><th>file:position:name</th></tr>');
   codePoints.forEach((CodePoint codePoint) {
     String jsCode = codePoint.jsCode;
-    if (jsCode.length > 40) {
-      jsCode = jsCode.substring(0, 40);
-    }
     if (codePoint.sourceLocation != null) {
       int index = collection.getIndex(codePoint.sourceLocation);
       if (index != null) {
-
-        buffer.write('<tr style="background:#${toColor(index)};" '
+        String style = '';
+        if (!codePoint.isMissing) {
+          style = 'style="background:${toColorCss(index)};" ';
+        }
+        buffer.write('<tr $style'
                      'name="trace$index" '
                      'onmouseover="highlight([${index}]);"'
                      'onmouseout="highlight([]);">');
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_html_templates.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_html_templates.dart
index 573b902..f4b0f1b 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_html_templates.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_html_templates.dart
@@ -8,6 +8,112 @@
 
 import 'dart:io';
 
+abstract class Configurations {
+  Iterable<String> get configs;
+  Iterable<String> get files;
+  String getPath(String config, String file);
+}
+
+void outputMultiConfigs(Uri uri,
+                        Configurations configurations) {
+  StringBuffer sb = new StringBuffer();
+  String defaultConfig = configurations.configs.first;
+  String defaultFile = configurations.files.first;
+  sb.write('''
+<html>
+<head>
+<style>
+.button {
+  cursor: pointer;
+  padding: 10px;
+  display: inline;
+}
+iframe {
+  border: 0px;
+}
+</style>
+</head>
+<body style="margin:0px;">
+<script>
+function setAll(name, property, value) {
+  var elements = document.getElementsByName(name);
+  for (var i = 0; i < elements.length; i++) {
+    elements[i].style[property] = value;
+  }
+}
+
+var current_config;
+var current_file;
+
+function setConfig(value) {
+  var property = 'text-decoration';
+  var onValue = 'underline';
+  var offValue = 'none';
+  if (current_config != value) {
+    setAll('config:' + current_config, property, offValue);
+    setAll('src:' + current_config + ':' + current_file, 'display', 'none');
+    current_config = value;
+    setAll('config:' + current_config, property, onValue);
+    setAll('src:' + current_config + ':' + current_file, 'display', 'block');
+  }
+}
+
+function setFile(value) {
+  var property = 'text-decoration';
+  var onValue = 'underline';
+  var offValue = 'none';
+  if (current_file != value) {
+    setAll('file:' + current_file, property, offValue);
+    setAll('src:' + current_config + ':' + current_file, 'display', 'none');
+    current_file = value;
+    setAll('file:' + current_file, property, onValue);
+    setAll('src:' + current_config + ':' + current_file, 'display', 'block');
+  }
+}
+</script>
+''');
+  for (String config in configurations.configs) {
+    for (String file in configurations.files) {
+      String uri = configurations.getPath(config, file);
+      sb.write('''
+<div name="src:$config:$file" 
+     style="width:100%;position:absolute;display:none;">
+  <iframe src="$uri" style="width:100%;height:100%;">
+  </iframe>
+</div>
+''');
+    }
+  }
+  sb.write('''  
+<div style="right:0px;height:30px;background-color:#E0E0E0;position:fixed;">
+  file:
+''');
+  for (String file in configurations.files) {
+    sb.write('''
+  <h3 class="button" name="file:$file" 
+      onclick="setFile('$file');">$file</h3>
+''');
+  }
+  sb.write('''
+  config:
+''');
+  for (String config in configurations.configs) {
+    sb.write('''
+  <h3 class="button" name="config:$config" 
+      onclick="setConfig('$config');">$config</h3>
+''');
+  }
+  sb.write('''
+</div>
+<script>
+setConfig('$defaultConfig');
+setFile('$defaultFile');
+</script>
+</body>
+</html>''');
+  output(uri, sb.toString());
+}
+
 /// Outputs JavaScript/Dart source mapping traces into [uri].
 void outputJsDartTrace(
     Uri uri,
diff --git a/tests/compiler/dart2js/trust_type_annotations2_test.dart b/tests/compiler/dart2js/trust_type_annotations2_test.dart
index 0ff5a916..cf8ad8a 100644
--- a/tests/compiler/dart2js/trust_type_annotations2_test.dart
+++ b/tests/compiler/dart2js/trust_type_annotations2_test.dart
@@ -24,11 +24,13 @@
 };
 
 main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES,
-                             options: ['--trust-type-annotations']);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        options: ['--trust-type-annotations']);
+    var compiler = result.compiler;
     var element = compiler.mainApp.findExported('main');
     var code = compiler.backend.assembleCode(element);
     Expect.isTrue(code.contains('+'), code);
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/unneeded_part_js_test.dart b/tests/compiler/dart2js/unneeded_part_js_test.dart
index 2ad0c3e..7a13c83 100644
--- a/tests/compiler/dart2js/unneeded_part_js_test.dart
+++ b/tests/compiler/dart2js/unneeded_part_js_test.dart
@@ -5,23 +5,21 @@
 // Test that no parts are emitted when deferred loading isn't used.
 
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/dart2jslib.dart';
 import 'package:expect/expect.dart';
 import 'memory_compiler.dart';
 
 main() {
-  DiagnosticCollector diagnostics = new DiagnosticCollector();
-  OutputCollector output = new OutputCollector();
-  Compiler compiler = compilerFor(
-      MEMORY_SOURCE_FILES,
-      diagnosticHandler: diagnostics,
-      outputProvider: output);
-
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    DiagnosticCollector diagnostics = new DiagnosticCollector();
+    OutputCollector output = new OutputCollector();
+    CompilationResult result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        diagnosticHandler: diagnostics,
+        outputProvider: output);
     Expect.isFalse(diagnostics.hasRegularMessages);
     Expect.isFalse(output.hasExtraOutput);
-    Expect.isFalse(compiler.compilationFailed);
-  }));
+    Expect.isTrue(result.isSuccess);
+  });
 }
 
 const Map MEMORY_SOURCE_FILES = const {
diff --git a/tests/compiler/dart2js/unused_empty_map_test.dart b/tests/compiler/dart2js/unused_empty_map_test.dart
index dfda62d..5f806bc 100644
--- a/tests/compiler/dart2js/unused_empty_map_test.dart
+++ b/tests/compiler/dart2js/unused_empty_map_test.dart
@@ -18,12 +18,12 @@
 const HASHMAP_EMPTY_CONSTRUCTOR = r"LinkedHashMap_LinkedHashMap$_empty";
 
 main() {
-  var collector = new OutputCollector();
-  var compiler = compilerFor(TEST_SOURCE, outputProvider: collector);
-  asyncTest(() =>
-    compiler.run(Uri.parse('memory:main.dart')).then((_) {
-      String generated = collector.getOutput('', 'js');
-      Expect.isFalse(generated.contains(HASHMAP_EMPTY_CONSTRUCTOR));
-    })
-  );
+  asyncTest(() async {
+    var collector = new OutputCollector();
+    var result = await runCompiler(
+      memorySourceFiles: TEST_SOURCE, outputProvider: collector);
+    var compiler = result.compiler;
+    String generated = collector.getOutput('', 'js');
+    Expect.isFalse(generated.contains(HASHMAP_EMPTY_CONSTRUCTOR));
+  });
 }
diff --git a/tests/compiler/dart2js/uri_retention_test.dart b/tests/compiler/dart2js/uri_retention_test.dart
index ac9d73c..8a7a47f 100644
--- a/tests/compiler/dart2js/uri_retention_test.dart
+++ b/tests/compiler/dart2js/uri_retention_test.dart
@@ -10,18 +10,18 @@
 import "package:async_helper/async_helper.dart";
 
 import 'memory_compiler.dart' show
-    compilerFor, OutputCollector;
+    runCompiler, OutputCollector;
 
-Future<String> compileSources(sources, {bool minify, bool preserveUri}) {
+Future<String> compileSources(sources, {bool minify, bool preserveUri}) async {
   var options = [];
   if (minify) options.add("--minify");
   if (preserveUri) options.add("--preserve-uris");
   OutputCollector outputCollector = new OutputCollector();
-  var compiler = compilerFor(
-      sources, options: options, outputProvider: outputCollector);
-  return compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
-    return outputCollector.getOutput('', 'js');
-  });
+  await runCompiler(
+      memorySourceFiles: sources,
+      options: options,
+      outputProvider: outputCollector);
+  return outputCollector.getOutput('', 'js');
 }
 
 Future test(sources, { bool libName, bool fileName }) {
diff --git a/tests/compiler/dart2js/use_checks_test.dart b/tests/compiler/dart2js/use_checks_test.dart
index 67efbd0..24013ad 100644
--- a/tests/compiler/dart2js/use_checks_test.dart
+++ b/tests/compiler/dart2js/use_checks_test.dart
@@ -23,11 +23,13 @@
 };
 
 main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES,
-                             options: ['--enable-checked-mode']);
-  asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES,
+        options: ['--enable-checked-mode']);
+    var compiler = result.compiler;
     var element = compiler.mainApp.findExported('main');
     var code = compiler.backend.assembleCode(element);
     Expect.isTrue(code.contains('+'), code);
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/use_strict_test.dart b/tests/compiler/dart2js/use_strict_test.dart
index 777c77c..b99bfe0 100644
--- a/tests/compiler/dart2js/use_strict_test.dart
+++ b/tests/compiler/dart2js/use_strict_test.dart
@@ -48,8 +48,9 @@
 
 main() {
   OutputCollector collector = new OutputCollector();
-  var compiler = compilerFor(MEMORY_SOURCE_FILES, outputProvider: collector);
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    await runCompiler(
+        memorySourceFiles: MEMORY_SOURCE_FILES, outputProvider: collector);
     String jsOutput = collector.getOutput('', 'js');
 
     // Skip comments.
@@ -64,5 +65,5 @@
     // 'arguments'.
     RegExp re = new RegExp(r'[^\w$](arguments|eval)[^\w$]');
     Expect.isFalse(re.hasMatch(filtered));
-  }));
+  });
 }
diff --git a/tests/compiler/dart2js/value_range3_test.dart b/tests/compiler/dart2js/value_range3_test.dart
index d2c95c8..5a483ed 100644
--- a/tests/compiler/dart2js/value_range3_test.dart
+++ b/tests/compiler/dart2js/value_range3_test.dart
@@ -23,11 +23,12 @@
 };
 
 main() {
-  var compiler = compilerFor(MEMORY_SOURCE_FILES);  
-  asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+  asyncTest(() async {
+    var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
+    var compiler = result.compiler;
     var element = compiler.mainApp.findExported('main');
     var code = compiler.backend.assembleCode(element);
     Expect.isFalse(code.contains('ioore'));
-  }));
+  });
 }
 
diff --git a/tests/compiler/dart2js/warnings_checker.dart b/tests/compiler/dart2js/warnings_checker.dart
index daaa32d..cf31943 100644
--- a/tests/compiler/dart2js/warnings_checker.dart
+++ b/tests/compiler/dart2js/warnings_checker.dart
@@ -21,7 +21,7 @@
   Uri script = currentDirectory.resolveUri(Platform.script);
   bool warningsMismatch = false;
   bool verbose = arguments != null && arguments.contains('-v');
-  asyncTest(() => Future.forEach(tests.keys, (String test) {
+  asyncTest(() => Future.forEach(tests.keys, (String test) async {
     Uri uri = script.resolve('../../$test');
     String source = UTF8.decode(readAll(uriPathToNative(uri.path)));
     SourceFile file = new StringSourceFile(
@@ -38,45 +38,44 @@
     }
     Set<int> unseenWarnings = new Set<int>.from(expectedWarnings.keys);
     DiagnosticCollector collector = new DiagnosticCollector();
-    var compiler = compilerFor(const {},
-         diagnosticHandler: collector,
-         options: ['--analyze-only'],
-         showDiagnostics: verbose);
-    return compiler.run(uri).then((_) {
-      Map<String, List<int>> statusMap = tests[test];
-      // Line numbers with known unexpected warnings.
-      List<int> unexpectedStatus = [];
-      if (statusMap != null && statusMap.containsKey('unexpected')) {
-        unexpectedStatus = statusMap['unexpected'];
+    await runCompiler(
+        entryPoint: uri,
+        diagnosticHandler: collector,
+        options: ['--analyze-only'],
+        showDiagnostics: verbose);
+    Map<String, List<int>> statusMap = tests[test];
+    // Line numbers with known unexpected warnings.
+    List<int> unexpectedStatus = [];
+    if (statusMap != null && statusMap.containsKey('unexpected')) {
+      unexpectedStatus = statusMap['unexpected'];
+    }
+    // Line numbers with known missing warnings.
+    List<int> missingStatus = [];
+    if (statusMap != null && statusMap.containsKey('missing')) {
+      missingStatus = statusMap['missing'];
+    }
+    for (DiagnosticMessage message in collector.warnings) {
+      Expect.equals(uri, message.uri);
+      int lineNo = file.getLine(message.begin);
+      if (expectedWarnings.containsKey(lineNo)) {
+        unseenWarnings.remove(lineNo);
+      } else if (!unexpectedStatus.contains(lineNo+1)) {
+        warningsMismatch = true;
+        print(file.getLocationMessage(
+            'Unexpected warning: ${message.message}',
+            message.begin, message.end));
       }
-      // Line numbers with known missing warnings.
-      List<int> missingStatus = [];
-      if (statusMap != null && statusMap.containsKey('missing')) {
-        missingStatus = statusMap['missing'];
-      }
-      for (DiagnosticMessage message in collector.warnings) {
-        Expect.equals(uri, message.uri);
-        int lineNo = file.getLine(message.begin);
-        if (expectedWarnings.containsKey(lineNo)) {
-          unseenWarnings.remove(lineNo);
-        } else if (!unexpectedStatus.contains(lineNo+1)) {
+    }
+    if (!unseenWarnings.isEmpty) {
+      for (int lineNo in unseenWarnings) {
+        if (!missingStatus.contains(lineNo+1)) {
           warningsMismatch = true;
-          print(file.getLocationMessage(
-              'Unexpected warning: ${message.message}',
-              message.begin, message.end));
+          String line = expectedWarnings[lineNo];
+          print('$uri [${lineNo+1}]: Missing static type warning.');
+          print(line);
         }
       }
-      if (!unseenWarnings.isEmpty) {
-        for (int lineNo in unseenWarnings) {
-          if (!missingStatus.contains(lineNo+1)) {
-            warningsMismatch = true;
-            String line = expectedWarnings[lineNo];
-            print('$uri [${lineNo+1}]: Missing static type warning.');
-            print(line);
-          }
-        }
-      }
-    });
+    }
   }).then((_) {
     Expect.isFalse(warningsMismatch);
   }));
diff --git a/tests/compiler/dart2js/world_test.dart b/tests/compiler/dart2js/world_test.dart
index 436b3d7..4acd90f 100644
--- a/tests/compiler/dart2js/world_test.dart
+++ b/tests/compiler/dart2js/world_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -15,7 +15,8 @@
   asyncTest(() => TypeEnvironment.create(r"""
       class A {}
       class B {}
-      class C extends A {}
+      class C_Super extends A {}
+      class C extends C_Super {}
       class D implements A {}
       class E extends B implements A {}
       class F extends Object with A implements B {}
@@ -63,6 +64,18 @@
       }
     }
 
+    void testSubclasses(
+        ClassElement cls,
+        List<ClassElement> expectedClasses,
+        {bool exact: true}) {
+      check(
+        'subclassesOf',
+        cls,
+        classWorld.subclassesOf(cls),
+        expectedClasses,
+        exact: exact);
+    }
+
     void testStrictSubclasses(
         ClassElement cls,
         List<ClassElement> expectedClasses,
@@ -99,6 +112,15 @@
         exact: exact);
     }
 
+    testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
+    testSubclasses(A, [A, C]);
+    testSubclasses(B, [B, E]);
+    testSubclasses(C, [C]);
+    testSubclasses(D, [D]);
+    testSubclasses(E, [E]);
+    testSubclasses(F, [F]);
+    testSubclasses(G, [G]);
+
     testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
     testStrictSubclasses(A, [C]);
     testStrictSubclasses(B, [E]);
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index e61053c..635ce98 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -85,3 +85,6 @@
 mirror_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
 reflect_native_types_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
 switch_test/none: Crash # (switch (val){foo:ba...  continue to a labeled switch case
+
+[ $compiler == none && $runtime == vm ]
+invalid_annotation_test/01: MissingCompileTimeError, OK # vm is lazy
diff --git a/tests/compiler/dart2js_extra/invalid_annotation2_test.dart b/tests/compiler/dart2js_extra/invalid_annotation2_test.dart
new file mode 100644
index 0000000..d8dafd5
--- /dev/null
+++ b/tests/compiler/dart2js_extra/invalid_annotation2_test.dart
@@ -0,0 +1,24 @@
+// 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.
+
+// Regression test for http://dartbug.com/23893/
+//
+// Because annotations are parsed lazily, dart2js used to crash when an
+// annotation had a syntax error.
+// This checks the same behavior as invalid_annotation_test.dart, except that we
+// use mirrors to trigger the error in the vm. This also triggers the error in
+// dart2js differently.
+
+@MirrorsUsed(targets: const [A])
+import 'dart:mirrors';
+
+@Deprecated("m"
+,                                /// 01: compile-time error
+)
+class A {
+}
+
+main() {
+  reflectClass(A).metadata;
+}
diff --git a/tests/compiler/dart2js_extra/invalid_annotation_test.dart b/tests/compiler/dart2js_extra/invalid_annotation_test.dart
new file mode 100644
index 0000000..5e0285a8
--- /dev/null
+++ b/tests/compiler/dart2js_extra/invalid_annotation_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// Regression test for http://dartbug.com/23893/
+//
+// Because annotations are parsed lazily, dart2js used to crash when an
+// annotation had a syntax error.
+
+@Deprecated("m"
+,                                /// 01: compile-time error
+)
+class A {}
+
+main() => new A();
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 34e5a50..9ea2884 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -22,7 +22,7 @@
 
 [ $compiler == dart2js && $cps_ir ]
 mirror_intercepted_field_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
-native_exception_test: RuntimeError # J.getInterceptor(...).toString$0 is not a function
+native_exception_test: RuntimeError # value_.toString$0 is not a function
 native_method_inlining_test: RuntimeError # Please triage this failure.
 native_mirror_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
 native_no_such_method_exception3_frog_test: RuntimeError # Please triage this failure.
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index acae7a0..648543c 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -214,13 +214,14 @@
 
 [ $compiler == dart2js && $cps_ir ]
 error_stack_trace1_test: Pass # H.unwrapException(...).get$stackTrace is not a function
-hashcode_test: RuntimeError # Please triage this failure.
 iterable_empty_test: RuntimeError # Please triage this failure.
 iterable_return_type_test/none: RuntimeError # Please triage this failure.
 iterable_to_list_test: RuntimeError # Please triage this failure.
 iterable_to_set_test: RuntimeError # Please triage this failure.
+list_filled_type_argument_test: RuntimeError # Please triage this failure.
 list_test/01: RuntimeError # this.get$length is not a function
 list_test/none: RuntimeError # this.get$length is not a function
+list_unmodifiable_test: RuntimeError # Please triage this failure.
 map_values2_test: RuntimeError # Please triage this failure.
 map_values3_test: RuntimeError # Please triage this failure.
 map_values4_test: RuntimeError # Please triage this failure.
@@ -232,5 +233,4 @@
 symbol_reserved_word_test/06: RuntimeError # Please triage this failure.
 symbol_reserved_word_test/09: RuntimeError # Please triage this failure.
 symbol_reserved_word_test/12: RuntimeError # Please triage this failure.
-symbol_test/none: Crash # The null object does not have a getter '_element'.
-uri_test: Crash # The null object does not have a getter '_element'.
+symbol_test/none: RuntimeError # Expected a NoSuchMethodError or a TypeError
diff --git a/tests/corelib/regexp/default_arguments_test.dart b/tests/corelib/regexp/default_arguments_test.dart
new file mode 100644
index 0000000..5b1d6e8
--- /dev/null
+++ b/tests/corelib/regexp/default_arguments_test.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// Test that `null` is interpreted as `false` when passed as argument to
+// `caseSensitive` and `multiLine`.
+
+import 'package:expect/expect.dart';
+
+main() {
+  testCaseSensitive();
+  testMultiLine();
+}
+
+testCaseSensitive() {
+  var r1 = new RegExp('foo');
+  var r2 = new RegExp('foo', caseSensitive: true);
+  var r3 = new RegExp('foo', caseSensitive: false);
+  var r4 = new RegExp('foo', caseSensitive: null);
+  Expect.isNull(r1.firstMatch('Foo'), "r1.firstMatch('Foo')");
+  Expect.isNull(r2.firstMatch('Foo'), "r2.firstMatch('Foo')");
+  Expect.isNotNull(r3.firstMatch('Foo'), "r3.firstMatch('Foo')");
+  Expect.isNotNull(r4.firstMatch('Foo'), "r4.firstMatch('Foo')");
+}
+
+testMultiLine() {
+  var r1 = new RegExp(r'^foo$');
+  var r2 = new RegExp(r'^foo$', multiLine: true);
+  var r3 = new RegExp(r'^foo$', multiLine: false);
+  var r4 = new RegExp(r'^foo$', multiLine: null);
+  Expect.isNull(r1.firstMatch('\nfoo\n'), "r1.firstMatch('\\nfoo\\n')");
+  Expect.isNotNull(r2.firstMatch('\nfoo\n'), "r2.firstMatch('\\nfoo\\n')");
+  Expect.isNull(r3.firstMatch('\nfoo\n'), "r3.firstMatch('\\nfoo\\n')");
+  Expect.isNull(r4.firstMatch('\nfoo\n'), "r4.firstMatch('\\nfoo\\n')");
+}
\ No newline at end of file
diff --git a/tests/html/html.status b/tests/html/html.status
index 27ea36a..0b02629 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -106,6 +106,8 @@
 
 [ $runtime == chrome ]
 touchevent_test/supported: Fail # Touch events are only supported on touch devices
+element_animate_test/omit_timing: RuntimeError # Also timing out on MacOS. Issue 23507
+element_animate_test/timing_dict: RuntimeError # Also timing out on MacOS. Issue 23507
 
 [ $runtime == chrome && $system == macos ]
 element_animate_test/omit_timing: Skip # Timing out on MacOS. Issue 23507
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index a683b66..41355d7 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -58,9 +58,14 @@
 message3_test/constInstance: RuntimeError # Issue 21817
 browser/issue_12474_test: CompileTimeError # Issue 22529
 enum_const_test/02: RuntimeError # Issue 21817
-error_exit_at_spawn_test: Fail, Timeout  # Issue 23876
-error_at_spawn_test: Fail, Timeout  # Issue 23876
-exit_at_spawn_test: Fail, Timeout  # Issue 23876
+error_exit_at_spawn_test: Fail  # Issue 23876
+error_at_spawn_test: Fail  # Issue 23876
+exit_at_spawn_test: Fail  # Issue 23876
+
+[ $compiler == dart2js && $runtime != d8 ]
+error_exit_at_spawn_test: Skip # Issue 23876
+error_at_spawn_test: Skip # Issue 23876
+exit_at_spawn_test: Skip # Issue 23876
 
 [ $compiler == dart2js && $jscl ]
 spawn_uri_test: SkipByDesign # Loading another file is not supported in JS shell
diff --git a/tests/language/bool_condition_check_test.dart b/tests/language/bool_condition_check_test.dart
new file mode 100644
index 0000000..facab4b
--- /dev/null
+++ b/tests/language/bool_condition_check_test.dart
@@ -0,0 +1,24 @@
+// 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.
+
+// Check that passing `null` for a boolean typed parameter will still cause
+// a boolean conversion error when used in a condition in checked mode.
+
+import 'package:expect/expect.dart';
+
+@NoInline()
+String check({bool a, bool b}) {
+  String a_string = a ? 'a' : '';
+  String b_string = b ? 'b' : '';
+  return '$a_string$b_string';
+}
+
+class Class {
+  final String field;
+  Class({bool a: false, bool b: true}) : this.field = check(a: a, b: b);
+}
+
+main() {
+  Expect.equals('', new Class(a: null, b: null).field); /// 01: dynamic type error
+}
\ No newline at end of file
diff --git a/tests/language/call_function_apply_test.dart b/tests/language/call_function_apply_test.dart
new file mode 100644
index 0000000..935cfaf
--- /dev/null
+++ b/tests/language/call_function_apply_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A {
+  call({a: 42}) {
+    return 499 + a;
+  }
+}
+
+main() {
+  Expect.equals(497, Function.apply(new A(), [], {#a: -2}));
+}
diff --git a/tests/language/classes_static_method_clash_test.dart b/tests/language/classes_static_method_clash_test.dart
new file mode 100644
index 0000000..0822897
--- /dev/null
+++ b/tests/language/classes_static_method_clash_test.dart
@@ -0,0 +1,5464 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// This methods needs a stub method (because it is used in Function.apply, where
+// we can't see all possible uses).
+// The stub-method(s) must not clash with other global names (like classes).
+foo({a:499}) => a;
+
+bar(f) {
+  return f();
+  return null;
+}
+
+int confuse(x) {
+  if (new DateTime.now().millisecondsSinceEpoch == 42) confuse(x + 1);
+  return x;
+}
+
+main() {
+  Expect.equals(42, Function.apply(foo, [], {#a: 42}));
+  Expect.equals(499, Function.apply(foo, [], null));
+  print(objects[confuse(0)]);
+}
+
+/*
+The following code has been generated with the following script:
+
+get chars sync* {
+  for (int i = "a".codeUnitAt(0); i <= "z".codeUnitAt(0); i++) {
+    yield new String.fromCharCodes([i]);
+  }
+  for (int i = "A".codeUnitAt(0); i <= "Z".codeUnitAt(0); i++) {
+    yield new String.fromCharCodes([i]);
+  }
+}
+
+main() {
+  StringBuffer classes = new StringBuffer();
+  print("var objects = [");
+  for (String c1 in chars) {
+    for (String c2 in chars) {
+      print("  new C$c1$c2(),");
+      classes.writeln("class C$c1$c2{}");
+    }
+  }
+  print("];");
+  print(classes.toString());
+}
+*/
+
+var objects = [
+  new Caa(),
+  new Cab(),
+  new Cac(),
+  new Cad(),
+  new Cae(),
+  new Caf(),
+  new Cag(),
+  new Cah(),
+  new Cai(),
+  new Caj(),
+  new Cak(),
+  new Cal(),
+  new Cam(),
+  new Can(),
+  new Cao(),
+  new Cap(),
+  new Caq(),
+  new Car(),
+  new Cas(),
+  new Cat(),
+  new Cau(),
+  new Cav(),
+  new Caw(),
+  new Cax(),
+  new Cay(),
+  new Caz(),
+  new CaA(),
+  new CaB(),
+  new CaC(),
+  new CaD(),
+  new CaE(),
+  new CaF(),
+  new CaG(),
+  new CaH(),
+  new CaI(),
+  new CaJ(),
+  new CaK(),
+  new CaL(),
+  new CaM(),
+  new CaN(),
+  new CaO(),
+  new CaP(),
+  new CaQ(),
+  new CaR(),
+  new CaS(),
+  new CaT(),
+  new CaU(),
+  new CaV(),
+  new CaW(),
+  new CaX(),
+  new CaY(),
+  new CaZ(),
+  new Cba(),
+  new Cbb(),
+  new Cbc(),
+  new Cbd(),
+  new Cbe(),
+  new Cbf(),
+  new Cbg(),
+  new Cbh(),
+  new Cbi(),
+  new Cbj(),
+  new Cbk(),
+  new Cbl(),
+  new Cbm(),
+  new Cbn(),
+  new Cbo(),
+  new Cbp(),
+  new Cbq(),
+  new Cbr(),
+  new Cbs(),
+  new Cbt(),
+  new Cbu(),
+  new Cbv(),
+  new Cbw(),
+  new Cbx(),
+  new Cby(),
+  new Cbz(),
+  new CbA(),
+  new CbB(),
+  new CbC(),
+  new CbD(),
+  new CbE(),
+  new CbF(),
+  new CbG(),
+  new CbH(),
+  new CbI(),
+  new CbJ(),
+  new CbK(),
+  new CbL(),
+  new CbM(),
+  new CbN(),
+  new CbO(),
+  new CbP(),
+  new CbQ(),
+  new CbR(),
+  new CbS(),
+  new CbT(),
+  new CbU(),
+  new CbV(),
+  new CbW(),
+  new CbX(),
+  new CbY(),
+  new CbZ(),
+  new Cca(),
+  new Ccb(),
+  new Ccc(),
+  new Ccd(),
+  new Cce(),
+  new Ccf(),
+  new Ccg(),
+  new Cch(),
+  new Cci(),
+  new Ccj(),
+  new Cck(),
+  new Ccl(),
+  new Ccm(),
+  new Ccn(),
+  new Cco(),
+  new Ccp(),
+  new Ccq(),
+  new Ccr(),
+  new Ccs(),
+  new Cct(),
+  new Ccu(),
+  new Ccv(),
+  new Ccw(),
+  new Ccx(),
+  new Ccy(),
+  new Ccz(),
+  new CcA(),
+  new CcB(),
+  new CcC(),
+  new CcD(),
+  new CcE(),
+  new CcF(),
+  new CcG(),
+  new CcH(),
+  new CcI(),
+  new CcJ(),
+  new CcK(),
+  new CcL(),
+  new CcM(),
+  new CcN(),
+  new CcO(),
+  new CcP(),
+  new CcQ(),
+  new CcR(),
+  new CcS(),
+  new CcT(),
+  new CcU(),
+  new CcV(),
+  new CcW(),
+  new CcX(),
+  new CcY(),
+  new CcZ(),
+  new Cda(),
+  new Cdb(),
+  new Cdc(),
+  new Cdd(),
+  new Cde(),
+  new Cdf(),
+  new Cdg(),
+  new Cdh(),
+  new Cdi(),
+  new Cdj(),
+  new Cdk(),
+  new Cdl(),
+  new Cdm(),
+  new Cdn(),
+  new Cdo(),
+  new Cdp(),
+  new Cdq(),
+  new Cdr(),
+  new Cds(),
+  new Cdt(),
+  new Cdu(),
+  new Cdv(),
+  new Cdw(),
+  new Cdx(),
+  new Cdy(),
+  new Cdz(),
+  new CdA(),
+  new CdB(),
+  new CdC(),
+  new CdD(),
+  new CdE(),
+  new CdF(),
+  new CdG(),
+  new CdH(),
+  new CdI(),
+  new CdJ(),
+  new CdK(),
+  new CdL(),
+  new CdM(),
+  new CdN(),
+  new CdO(),
+  new CdP(),
+  new CdQ(),
+  new CdR(),
+  new CdS(),
+  new CdT(),
+  new CdU(),
+  new CdV(),
+  new CdW(),
+  new CdX(),
+  new CdY(),
+  new CdZ(),
+  new Cea(),
+  new Ceb(),
+  new Cec(),
+  new Ced(),
+  new Cee(),
+  new Cef(),
+  new Ceg(),
+  new Ceh(),
+  new Cei(),
+  new Cej(),
+  new Cek(),
+  new Cel(),
+  new Cem(),
+  new Cen(),
+  new Ceo(),
+  new Cep(),
+  new Ceq(),
+  new Cer(),
+  new Ces(),
+  new Cet(),
+  new Ceu(),
+  new Cev(),
+  new Cew(),
+  new Cex(),
+  new Cey(),
+  new Cez(),
+  new CeA(),
+  new CeB(),
+  new CeC(),
+  new CeD(),
+  new CeE(),
+  new CeF(),
+  new CeG(),
+  new CeH(),
+  new CeI(),
+  new CeJ(),
+  new CeK(),
+  new CeL(),
+  new CeM(),
+  new CeN(),
+  new CeO(),
+  new CeP(),
+  new CeQ(),
+  new CeR(),
+  new CeS(),
+  new CeT(),
+  new CeU(),
+  new CeV(),
+  new CeW(),
+  new CeX(),
+  new CeY(),
+  new CeZ(),
+  new Cfa(),
+  new Cfb(),
+  new Cfc(),
+  new Cfd(),
+  new Cfe(),
+  new Cff(),
+  new Cfg(),
+  new Cfh(),
+  new Cfi(),
+  new Cfj(),
+  new Cfk(),
+  new Cfl(),
+  new Cfm(),
+  new Cfn(),
+  new Cfo(),
+  new Cfp(),
+  new Cfq(),
+  new Cfr(),
+  new Cfs(),
+  new Cft(),
+  new Cfu(),
+  new Cfv(),
+  new Cfw(),
+  new Cfx(),
+  new Cfy(),
+  new Cfz(),
+  new CfA(),
+  new CfB(),
+  new CfC(),
+  new CfD(),
+  new CfE(),
+  new CfF(),
+  new CfG(),
+  new CfH(),
+  new CfI(),
+  new CfJ(),
+  new CfK(),
+  new CfL(),
+  new CfM(),
+  new CfN(),
+  new CfO(),
+  new CfP(),
+  new CfQ(),
+  new CfR(),
+  new CfS(),
+  new CfT(),
+  new CfU(),
+  new CfV(),
+  new CfW(),
+  new CfX(),
+  new CfY(),
+  new CfZ(),
+  new Cga(),
+  new Cgb(),
+  new Cgc(),
+  new Cgd(),
+  new Cge(),
+  new Cgf(),
+  new Cgg(),
+  new Cgh(),
+  new Cgi(),
+  new Cgj(),
+  new Cgk(),
+  new Cgl(),
+  new Cgm(),
+  new Cgn(),
+  new Cgo(),
+  new Cgp(),
+  new Cgq(),
+  new Cgr(),
+  new Cgs(),
+  new Cgt(),
+  new Cgu(),
+  new Cgv(),
+  new Cgw(),
+  new Cgx(),
+  new Cgy(),
+  new Cgz(),
+  new CgA(),
+  new CgB(),
+  new CgC(),
+  new CgD(),
+  new CgE(),
+  new CgF(),
+  new CgG(),
+  new CgH(),
+  new CgI(),
+  new CgJ(),
+  new CgK(),
+  new CgL(),
+  new CgM(),
+  new CgN(),
+  new CgO(),
+  new CgP(),
+  new CgQ(),
+  new CgR(),
+  new CgS(),
+  new CgT(),
+  new CgU(),
+  new CgV(),
+  new CgW(),
+  new CgX(),
+  new CgY(),
+  new CgZ(),
+  new Cha(),
+  new Chb(),
+  new Chc(),
+  new Chd(),
+  new Che(),
+  new Chf(),
+  new Chg(),
+  new Chh(),
+  new Chi(),
+  new Chj(),
+  new Chk(),
+  new Chl(),
+  new Chm(),
+  new Chn(),
+  new Cho(),
+  new Chp(),
+  new Chq(),
+  new Chr(),
+  new Chs(),
+  new Cht(),
+  new Chu(),
+  new Chv(),
+  new Chw(),
+  new Chx(),
+  new Chy(),
+  new Chz(),
+  new ChA(),
+  new ChB(),
+  new ChC(),
+  new ChD(),
+  new ChE(),
+  new ChF(),
+  new ChG(),
+  new ChH(),
+  new ChI(),
+  new ChJ(),
+  new ChK(),
+  new ChL(),
+  new ChM(),
+  new ChN(),
+  new ChO(),
+  new ChP(),
+  new ChQ(),
+  new ChR(),
+  new ChS(),
+  new ChT(),
+  new ChU(),
+  new ChV(),
+  new ChW(),
+  new ChX(),
+  new ChY(),
+  new ChZ(),
+  new Cia(),
+  new Cib(),
+  new Cic(),
+  new Cid(),
+  new Cie(),
+  new Cif(),
+  new Cig(),
+  new Cih(),
+  new Cii(),
+  new Cij(),
+  new Cik(),
+  new Cil(),
+  new Cim(),
+  new Cin(),
+  new Cio(),
+  new Cip(),
+  new Ciq(),
+  new Cir(),
+  new Cis(),
+  new Cit(),
+  new Ciu(),
+  new Civ(),
+  new Ciw(),
+  new Cix(),
+  new Ciy(),
+  new Ciz(),
+  new CiA(),
+  new CiB(),
+  new CiC(),
+  new CiD(),
+  new CiE(),
+  new CiF(),
+  new CiG(),
+  new CiH(),
+  new CiI(),
+  new CiJ(),
+  new CiK(),
+  new CiL(),
+  new CiM(),
+  new CiN(),
+  new CiO(),
+  new CiP(),
+  new CiQ(),
+  new CiR(),
+  new CiS(),
+  new CiT(),
+  new CiU(),
+  new CiV(),
+  new CiW(),
+  new CiX(),
+  new CiY(),
+  new CiZ(),
+  new Cja(),
+  new Cjb(),
+  new Cjc(),
+  new Cjd(),
+  new Cje(),
+  new Cjf(),
+  new Cjg(),
+  new Cjh(),
+  new Cji(),
+  new Cjj(),
+  new Cjk(),
+  new Cjl(),
+  new Cjm(),
+  new Cjn(),
+  new Cjo(),
+  new Cjp(),
+  new Cjq(),
+  new Cjr(),
+  new Cjs(),
+  new Cjt(),
+  new Cju(),
+  new Cjv(),
+  new Cjw(),
+  new Cjx(),
+  new Cjy(),
+  new Cjz(),
+  new CjA(),
+  new CjB(),
+  new CjC(),
+  new CjD(),
+  new CjE(),
+  new CjF(),
+  new CjG(),
+  new CjH(),
+  new CjI(),
+  new CjJ(),
+  new CjK(),
+  new CjL(),
+  new CjM(),
+  new CjN(),
+  new CjO(),
+  new CjP(),
+  new CjQ(),
+  new CjR(),
+  new CjS(),
+  new CjT(),
+  new CjU(),
+  new CjV(),
+  new CjW(),
+  new CjX(),
+  new CjY(),
+  new CjZ(),
+  new Cka(),
+  new Ckb(),
+  new Ckc(),
+  new Ckd(),
+  new Cke(),
+  new Ckf(),
+  new Ckg(),
+  new Ckh(),
+  new Cki(),
+  new Ckj(),
+  new Ckk(),
+  new Ckl(),
+  new Ckm(),
+  new Ckn(),
+  new Cko(),
+  new Ckp(),
+  new Ckq(),
+  new Ckr(),
+  new Cks(),
+  new Ckt(),
+  new Cku(),
+  new Ckv(),
+  new Ckw(),
+  new Ckx(),
+  new Cky(),
+  new Ckz(),
+  new CkA(),
+  new CkB(),
+  new CkC(),
+  new CkD(),
+  new CkE(),
+  new CkF(),
+  new CkG(),
+  new CkH(),
+  new CkI(),
+  new CkJ(),
+  new CkK(),
+  new CkL(),
+  new CkM(),
+  new CkN(),
+  new CkO(),
+  new CkP(),
+  new CkQ(),
+  new CkR(),
+  new CkS(),
+  new CkT(),
+  new CkU(),
+  new CkV(),
+  new CkW(),
+  new CkX(),
+  new CkY(),
+  new CkZ(),
+  new Cla(),
+  new Clb(),
+  new Clc(),
+  new Cld(),
+  new Cle(),
+  new Clf(),
+  new Clg(),
+  new Clh(),
+  new Cli(),
+  new Clj(),
+  new Clk(),
+  new Cll(),
+  new Clm(),
+  new Cln(),
+  new Clo(),
+  new Clp(),
+  new Clq(),
+  new Clr(),
+  new Cls(),
+  new Clt(),
+  new Clu(),
+  new Clv(),
+  new Clw(),
+  new Clx(),
+  new Cly(),
+  new Clz(),
+  new ClA(),
+  new ClB(),
+  new ClC(),
+  new ClD(),
+  new ClE(),
+  new ClF(),
+  new ClG(),
+  new ClH(),
+  new ClI(),
+  new ClJ(),
+  new ClK(),
+  new ClL(),
+  new ClM(),
+  new ClN(),
+  new ClO(),
+  new ClP(),
+  new ClQ(),
+  new ClR(),
+  new ClS(),
+  new ClT(),
+  new ClU(),
+  new ClV(),
+  new ClW(),
+  new ClX(),
+  new ClY(),
+  new ClZ(),
+  new Cma(),
+  new Cmb(),
+  new Cmc(),
+  new Cmd(),
+  new Cme(),
+  new Cmf(),
+  new Cmg(),
+  new Cmh(),
+  new Cmi(),
+  new Cmj(),
+  new Cmk(),
+  new Cml(),
+  new Cmm(),
+  new Cmn(),
+  new Cmo(),
+  new Cmp(),
+  new Cmq(),
+  new Cmr(),
+  new Cms(),
+  new Cmt(),
+  new Cmu(),
+  new Cmv(),
+  new Cmw(),
+  new Cmx(),
+  new Cmy(),
+  new Cmz(),
+  new CmA(),
+  new CmB(),
+  new CmC(),
+  new CmD(),
+  new CmE(),
+  new CmF(),
+  new CmG(),
+  new CmH(),
+  new CmI(),
+  new CmJ(),
+  new CmK(),
+  new CmL(),
+  new CmM(),
+  new CmN(),
+  new CmO(),
+  new CmP(),
+  new CmQ(),
+  new CmR(),
+  new CmS(),
+  new CmT(),
+  new CmU(),
+  new CmV(),
+  new CmW(),
+  new CmX(),
+  new CmY(),
+  new CmZ(),
+  new Cna(),
+  new Cnb(),
+  new Cnc(),
+  new Cnd(),
+  new Cne(),
+  new Cnf(),
+  new Cng(),
+  new Cnh(),
+  new Cni(),
+  new Cnj(),
+  new Cnk(),
+  new Cnl(),
+  new Cnm(),
+  new Cnn(),
+  new Cno(),
+  new Cnp(),
+  new Cnq(),
+  new Cnr(),
+  new Cns(),
+  new Cnt(),
+  new Cnu(),
+  new Cnv(),
+  new Cnw(),
+  new Cnx(),
+  new Cny(),
+  new Cnz(),
+  new CnA(),
+  new CnB(),
+  new CnC(),
+  new CnD(),
+  new CnE(),
+  new CnF(),
+  new CnG(),
+  new CnH(),
+  new CnI(),
+  new CnJ(),
+  new CnK(),
+  new CnL(),
+  new CnM(),
+  new CnN(),
+  new CnO(),
+  new CnP(),
+  new CnQ(),
+  new CnR(),
+  new CnS(),
+  new CnT(),
+  new CnU(),
+  new CnV(),
+  new CnW(),
+  new CnX(),
+  new CnY(),
+  new CnZ(),
+  new Coa(),
+  new Cob(),
+  new Coc(),
+  new Cod(),
+  new Coe(),
+  new Cof(),
+  new Cog(),
+  new Coh(),
+  new Coi(),
+  new Coj(),
+  new Cok(),
+  new Col(),
+  new Com(),
+  new Con(),
+  new Coo(),
+  new Cop(),
+  new Coq(),
+  new Cor(),
+  new Cos(),
+  new Cot(),
+  new Cou(),
+  new Cov(),
+  new Cow(),
+  new Cox(),
+  new Coy(),
+  new Coz(),
+  new CoA(),
+  new CoB(),
+  new CoC(),
+  new CoD(),
+  new CoE(),
+  new CoF(),
+  new CoG(),
+  new CoH(),
+  new CoI(),
+  new CoJ(),
+  new CoK(),
+  new CoL(),
+  new CoM(),
+  new CoN(),
+  new CoO(),
+  new CoP(),
+  new CoQ(),
+  new CoR(),
+  new CoS(),
+  new CoT(),
+  new CoU(),
+  new CoV(),
+  new CoW(),
+  new CoX(),
+  new CoY(),
+  new CoZ(),
+  new Cpa(),
+  new Cpb(),
+  new Cpc(),
+  new Cpd(),
+  new Cpe(),
+  new Cpf(),
+  new Cpg(),
+  new Cph(),
+  new Cpi(),
+  new Cpj(),
+  new Cpk(),
+  new Cpl(),
+  new Cpm(),
+  new Cpn(),
+  new Cpo(),
+  new Cpp(),
+  new Cpq(),
+  new Cpr(),
+  new Cps(),
+  new Cpt(),
+  new Cpu(),
+  new Cpv(),
+  new Cpw(),
+  new Cpx(),
+  new Cpy(),
+  new Cpz(),
+  new CpA(),
+  new CpB(),
+  new CpC(),
+  new CpD(),
+  new CpE(),
+  new CpF(),
+  new CpG(),
+  new CpH(),
+  new CpI(),
+  new CpJ(),
+  new CpK(),
+  new CpL(),
+  new CpM(),
+  new CpN(),
+  new CpO(),
+  new CpP(),
+  new CpQ(),
+  new CpR(),
+  new CpS(),
+  new CpT(),
+  new CpU(),
+  new CpV(),
+  new CpW(),
+  new CpX(),
+  new CpY(),
+  new CpZ(),
+  new Cqa(),
+  new Cqb(),
+  new Cqc(),
+  new Cqd(),
+  new Cqe(),
+  new Cqf(),
+  new Cqg(),
+  new Cqh(),
+  new Cqi(),
+  new Cqj(),
+  new Cqk(),
+  new Cql(),
+  new Cqm(),
+  new Cqn(),
+  new Cqo(),
+  new Cqp(),
+  new Cqq(),
+  new Cqr(),
+  new Cqs(),
+  new Cqt(),
+  new Cqu(),
+  new Cqv(),
+  new Cqw(),
+  new Cqx(),
+  new Cqy(),
+  new Cqz(),
+  new CqA(),
+  new CqB(),
+  new CqC(),
+  new CqD(),
+  new CqE(),
+  new CqF(),
+  new CqG(),
+  new CqH(),
+  new CqI(),
+  new CqJ(),
+  new CqK(),
+  new CqL(),
+  new CqM(),
+  new CqN(),
+  new CqO(),
+  new CqP(),
+  new CqQ(),
+  new CqR(),
+  new CqS(),
+  new CqT(),
+  new CqU(),
+  new CqV(),
+  new CqW(),
+  new CqX(),
+  new CqY(),
+  new CqZ(),
+  new Cra(),
+  new Crb(),
+  new Crc(),
+  new Crd(),
+  new Cre(),
+  new Crf(),
+  new Crg(),
+  new Crh(),
+  new Cri(),
+  new Crj(),
+  new Crk(),
+  new Crl(),
+  new Crm(),
+  new Crn(),
+  new Cro(),
+  new Crp(),
+  new Crq(),
+  new Crr(),
+  new Crs(),
+  new Crt(),
+  new Cru(),
+  new Crv(),
+  new Crw(),
+  new Crx(),
+  new Cry(),
+  new Crz(),
+  new CrA(),
+  new CrB(),
+  new CrC(),
+  new CrD(),
+  new CrE(),
+  new CrF(),
+  new CrG(),
+  new CrH(),
+  new CrI(),
+  new CrJ(),
+  new CrK(),
+  new CrL(),
+  new CrM(),
+  new CrN(),
+  new CrO(),
+  new CrP(),
+  new CrQ(),
+  new CrR(),
+  new CrS(),
+  new CrT(),
+  new CrU(),
+  new CrV(),
+  new CrW(),
+  new CrX(),
+  new CrY(),
+  new CrZ(),
+  new Csa(),
+  new Csb(),
+  new Csc(),
+  new Csd(),
+  new Cse(),
+  new Csf(),
+  new Csg(),
+  new Csh(),
+  new Csi(),
+  new Csj(),
+  new Csk(),
+  new Csl(),
+  new Csm(),
+  new Csn(),
+  new Cso(),
+  new Csp(),
+  new Csq(),
+  new Csr(),
+  new Css(),
+  new Cst(),
+  new Csu(),
+  new Csv(),
+  new Csw(),
+  new Csx(),
+  new Csy(),
+  new Csz(),
+  new CsA(),
+  new CsB(),
+  new CsC(),
+  new CsD(),
+  new CsE(),
+  new CsF(),
+  new CsG(),
+  new CsH(),
+  new CsI(),
+  new CsJ(),
+  new CsK(),
+  new CsL(),
+  new CsM(),
+  new CsN(),
+  new CsO(),
+  new CsP(),
+  new CsQ(),
+  new CsR(),
+  new CsS(),
+  new CsT(),
+  new CsU(),
+  new CsV(),
+  new CsW(),
+  new CsX(),
+  new CsY(),
+  new CsZ(),
+  new Cta(),
+  new Ctb(),
+  new Ctc(),
+  new Ctd(),
+  new Cte(),
+  new Ctf(),
+  new Ctg(),
+  new Cth(),
+  new Cti(),
+  new Ctj(),
+  new Ctk(),
+  new Ctl(),
+  new Ctm(),
+  new Ctn(),
+  new Cto(),
+  new Ctp(),
+  new Ctq(),
+  new Ctr(),
+  new Cts(),
+  new Ctt(),
+  new Ctu(),
+  new Ctv(),
+  new Ctw(),
+  new Ctx(),
+  new Cty(),
+  new Ctz(),
+  new CtA(),
+  new CtB(),
+  new CtC(),
+  new CtD(),
+  new CtE(),
+  new CtF(),
+  new CtG(),
+  new CtH(),
+  new CtI(),
+  new CtJ(),
+  new CtK(),
+  new CtL(),
+  new CtM(),
+  new CtN(),
+  new CtO(),
+  new CtP(),
+  new CtQ(),
+  new CtR(),
+  new CtS(),
+  new CtT(),
+  new CtU(),
+  new CtV(),
+  new CtW(),
+  new CtX(),
+  new CtY(),
+  new CtZ(),
+  new Cua(),
+  new Cub(),
+  new Cuc(),
+  new Cud(),
+  new Cue(),
+  new Cuf(),
+  new Cug(),
+  new Cuh(),
+  new Cui(),
+  new Cuj(),
+  new Cuk(),
+  new Cul(),
+  new Cum(),
+  new Cun(),
+  new Cuo(),
+  new Cup(),
+  new Cuq(),
+  new Cur(),
+  new Cus(),
+  new Cut(),
+  new Cuu(),
+  new Cuv(),
+  new Cuw(),
+  new Cux(),
+  new Cuy(),
+  new Cuz(),
+  new CuA(),
+  new CuB(),
+  new CuC(),
+  new CuD(),
+  new CuE(),
+  new CuF(),
+  new CuG(),
+  new CuH(),
+  new CuI(),
+  new CuJ(),
+  new CuK(),
+  new CuL(),
+  new CuM(),
+  new CuN(),
+  new CuO(),
+  new CuP(),
+  new CuQ(),
+  new CuR(),
+  new CuS(),
+  new CuT(),
+  new CuU(),
+  new CuV(),
+  new CuW(),
+  new CuX(),
+  new CuY(),
+  new CuZ(),
+  new Cva(),
+  new Cvb(),
+  new Cvc(),
+  new Cvd(),
+  new Cve(),
+  new Cvf(),
+  new Cvg(),
+  new Cvh(),
+  new Cvi(),
+  new Cvj(),
+  new Cvk(),
+  new Cvl(),
+  new Cvm(),
+  new Cvn(),
+  new Cvo(),
+  new Cvp(),
+  new Cvq(),
+  new Cvr(),
+  new Cvs(),
+  new Cvt(),
+  new Cvu(),
+  new Cvv(),
+  new Cvw(),
+  new Cvx(),
+  new Cvy(),
+  new Cvz(),
+  new CvA(),
+  new CvB(),
+  new CvC(),
+  new CvD(),
+  new CvE(),
+  new CvF(),
+  new CvG(),
+  new CvH(),
+  new CvI(),
+  new CvJ(),
+  new CvK(),
+  new CvL(),
+  new CvM(),
+  new CvN(),
+  new CvO(),
+  new CvP(),
+  new CvQ(),
+  new CvR(),
+  new CvS(),
+  new CvT(),
+  new CvU(),
+  new CvV(),
+  new CvW(),
+  new CvX(),
+  new CvY(),
+  new CvZ(),
+  new Cwa(),
+  new Cwb(),
+  new Cwc(),
+  new Cwd(),
+  new Cwe(),
+  new Cwf(),
+  new Cwg(),
+  new Cwh(),
+  new Cwi(),
+  new Cwj(),
+  new Cwk(),
+  new Cwl(),
+  new Cwm(),
+  new Cwn(),
+  new Cwo(),
+  new Cwp(),
+  new Cwq(),
+  new Cwr(),
+  new Cws(),
+  new Cwt(),
+  new Cwu(),
+  new Cwv(),
+  new Cww(),
+  new Cwx(),
+  new Cwy(),
+  new Cwz(),
+  new CwA(),
+  new CwB(),
+  new CwC(),
+  new CwD(),
+  new CwE(),
+  new CwF(),
+  new CwG(),
+  new CwH(),
+  new CwI(),
+  new CwJ(),
+  new CwK(),
+  new CwL(),
+  new CwM(),
+  new CwN(),
+  new CwO(),
+  new CwP(),
+  new CwQ(),
+  new CwR(),
+  new CwS(),
+  new CwT(),
+  new CwU(),
+  new CwV(),
+  new CwW(),
+  new CwX(),
+  new CwY(),
+  new CwZ(),
+  new Cxa(),
+  new Cxb(),
+  new Cxc(),
+  new Cxd(),
+  new Cxe(),
+  new Cxf(),
+  new Cxg(),
+  new Cxh(),
+  new Cxi(),
+  new Cxj(),
+  new Cxk(),
+  new Cxl(),
+  new Cxm(),
+  new Cxn(),
+  new Cxo(),
+  new Cxp(),
+  new Cxq(),
+  new Cxr(),
+  new Cxs(),
+  new Cxt(),
+  new Cxu(),
+  new Cxv(),
+  new Cxw(),
+  new Cxx(),
+  new Cxy(),
+  new Cxz(),
+  new CxA(),
+  new CxB(),
+  new CxC(),
+  new CxD(),
+  new CxE(),
+  new CxF(),
+  new CxG(),
+  new CxH(),
+  new CxI(),
+  new CxJ(),
+  new CxK(),
+  new CxL(),
+  new CxM(),
+  new CxN(),
+  new CxO(),
+  new CxP(),
+  new CxQ(),
+  new CxR(),
+  new CxS(),
+  new CxT(),
+  new CxU(),
+  new CxV(),
+  new CxW(),
+  new CxX(),
+  new CxY(),
+  new CxZ(),
+  new Cya(),
+  new Cyb(),
+  new Cyc(),
+  new Cyd(),
+  new Cye(),
+  new Cyf(),
+  new Cyg(),
+  new Cyh(),
+  new Cyi(),
+  new Cyj(),
+  new Cyk(),
+  new Cyl(),
+  new Cym(),
+  new Cyn(),
+  new Cyo(),
+  new Cyp(),
+  new Cyq(),
+  new Cyr(),
+  new Cys(),
+  new Cyt(),
+  new Cyu(),
+  new Cyv(),
+  new Cyw(),
+  new Cyx(),
+  new Cyy(),
+  new Cyz(),
+  new CyA(),
+  new CyB(),
+  new CyC(),
+  new CyD(),
+  new CyE(),
+  new CyF(),
+  new CyG(),
+  new CyH(),
+  new CyI(),
+  new CyJ(),
+  new CyK(),
+  new CyL(),
+  new CyM(),
+  new CyN(),
+  new CyO(),
+  new CyP(),
+  new CyQ(),
+  new CyR(),
+  new CyS(),
+  new CyT(),
+  new CyU(),
+  new CyV(),
+  new CyW(),
+  new CyX(),
+  new CyY(),
+  new CyZ(),
+  new Cza(),
+  new Czb(),
+  new Czc(),
+  new Czd(),
+  new Cze(),
+  new Czf(),
+  new Czg(),
+  new Czh(),
+  new Czi(),
+  new Czj(),
+  new Czk(),
+  new Czl(),
+  new Czm(),
+  new Czn(),
+  new Czo(),
+  new Czp(),
+  new Czq(),
+  new Czr(),
+  new Czs(),
+  new Czt(),
+  new Czu(),
+  new Czv(),
+  new Czw(),
+  new Czx(),
+  new Czy(),
+  new Czz(),
+  new CzA(),
+  new CzB(),
+  new CzC(),
+  new CzD(),
+  new CzE(),
+  new CzF(),
+  new CzG(),
+  new CzH(),
+  new CzI(),
+  new CzJ(),
+  new CzK(),
+  new CzL(),
+  new CzM(),
+  new CzN(),
+  new CzO(),
+  new CzP(),
+  new CzQ(),
+  new CzR(),
+  new CzS(),
+  new CzT(),
+  new CzU(),
+  new CzV(),
+  new CzW(),
+  new CzX(),
+  new CzY(),
+  new CzZ(),
+  new CAa(),
+  new CAb(),
+  new CAc(),
+  new CAd(),
+  new CAe(),
+  new CAf(),
+  new CAg(),
+  new CAh(),
+  new CAi(),
+  new CAj(),
+  new CAk(),
+  new CAl(),
+  new CAm(),
+  new CAn(),
+  new CAo(),
+  new CAp(),
+  new CAq(),
+  new CAr(),
+  new CAs(),
+  new CAt(),
+  new CAu(),
+  new CAv(),
+  new CAw(),
+  new CAx(),
+  new CAy(),
+  new CAz(),
+  new CAA(),
+  new CAB(),
+  new CAC(),
+  new CAD(),
+  new CAE(),
+  new CAF(),
+  new CAG(),
+  new CAH(),
+  new CAI(),
+  new CAJ(),
+  new CAK(),
+  new CAL(),
+  new CAM(),
+  new CAN(),
+  new CAO(),
+  new CAP(),
+  new CAQ(),
+  new CAR(),
+  new CAS(),
+  new CAT(),
+  new CAU(),
+  new CAV(),
+  new CAW(),
+  new CAX(),
+  new CAY(),
+  new CAZ(),
+  new CBa(),
+  new CBb(),
+  new CBc(),
+  new CBd(),
+  new CBe(),
+  new CBf(),
+  new CBg(),
+  new CBh(),
+  new CBi(),
+  new CBj(),
+  new CBk(),
+  new CBl(),
+  new CBm(),
+  new CBn(),
+  new CBo(),
+  new CBp(),
+  new CBq(),
+  new CBr(),
+  new CBs(),
+  new CBt(),
+  new CBu(),
+  new CBv(),
+  new CBw(),
+  new CBx(),
+  new CBy(),
+  new CBz(),
+  new CBA(),
+  new CBB(),
+  new CBC(),
+  new CBD(),
+  new CBE(),
+  new CBF(),
+  new CBG(),
+  new CBH(),
+  new CBI(),
+  new CBJ(),
+  new CBK(),
+  new CBL(),
+  new CBM(),
+  new CBN(),
+  new CBO(),
+  new CBP(),
+  new CBQ(),
+  new CBR(),
+  new CBS(),
+  new CBT(),
+  new CBU(),
+  new CBV(),
+  new CBW(),
+  new CBX(),
+  new CBY(),
+  new CBZ(),
+  new CCa(),
+  new CCb(),
+  new CCc(),
+  new CCd(),
+  new CCe(),
+  new CCf(),
+  new CCg(),
+  new CCh(),
+  new CCi(),
+  new CCj(),
+  new CCk(),
+  new CCl(),
+  new CCm(),
+  new CCn(),
+  new CCo(),
+  new CCp(),
+  new CCq(),
+  new CCr(),
+  new CCs(),
+  new CCt(),
+  new CCu(),
+  new CCv(),
+  new CCw(),
+  new CCx(),
+  new CCy(),
+  new CCz(),
+  new CCA(),
+  new CCB(),
+  new CCC(),
+  new CCD(),
+  new CCE(),
+  new CCF(),
+  new CCG(),
+  new CCH(),
+  new CCI(),
+  new CCJ(),
+  new CCK(),
+  new CCL(),
+  new CCM(),
+  new CCN(),
+  new CCO(),
+  new CCP(),
+  new CCQ(),
+  new CCR(),
+  new CCS(),
+  new CCT(),
+  new CCU(),
+  new CCV(),
+  new CCW(),
+  new CCX(),
+  new CCY(),
+  new CCZ(),
+  new CDa(),
+  new CDb(),
+  new CDc(),
+  new CDd(),
+  new CDe(),
+  new CDf(),
+  new CDg(),
+  new CDh(),
+  new CDi(),
+  new CDj(),
+  new CDk(),
+  new CDl(),
+  new CDm(),
+  new CDn(),
+  new CDo(),
+  new CDp(),
+  new CDq(),
+  new CDr(),
+  new CDs(),
+  new CDt(),
+  new CDu(),
+  new CDv(),
+  new CDw(),
+  new CDx(),
+  new CDy(),
+  new CDz(),
+  new CDA(),
+  new CDB(),
+  new CDC(),
+  new CDD(),
+  new CDE(),
+  new CDF(),
+  new CDG(),
+  new CDH(),
+  new CDI(),
+  new CDJ(),
+  new CDK(),
+  new CDL(),
+  new CDM(),
+  new CDN(),
+  new CDO(),
+  new CDP(),
+  new CDQ(),
+  new CDR(),
+  new CDS(),
+  new CDT(),
+  new CDU(),
+  new CDV(),
+  new CDW(),
+  new CDX(),
+  new CDY(),
+  new CDZ(),
+  new CEa(),
+  new CEb(),
+  new CEc(),
+  new CEd(),
+  new CEe(),
+  new CEf(),
+  new CEg(),
+  new CEh(),
+  new CEi(),
+  new CEj(),
+  new CEk(),
+  new CEl(),
+  new CEm(),
+  new CEn(),
+  new CEo(),
+  new CEp(),
+  new CEq(),
+  new CEr(),
+  new CEs(),
+  new CEt(),
+  new CEu(),
+  new CEv(),
+  new CEw(),
+  new CEx(),
+  new CEy(),
+  new CEz(),
+  new CEA(),
+  new CEB(),
+  new CEC(),
+  new CED(),
+  new CEE(),
+  new CEF(),
+  new CEG(),
+  new CEH(),
+  new CEI(),
+  new CEJ(),
+  new CEK(),
+  new CEL(),
+  new CEM(),
+  new CEN(),
+  new CEO(),
+  new CEP(),
+  new CEQ(),
+  new CER(),
+  new CES(),
+  new CET(),
+  new CEU(),
+  new CEV(),
+  new CEW(),
+  new CEX(),
+  new CEY(),
+  new CEZ(),
+  new CFa(),
+  new CFb(),
+  new CFc(),
+  new CFd(),
+  new CFe(),
+  new CFf(),
+  new CFg(),
+  new CFh(),
+  new CFi(),
+  new CFj(),
+  new CFk(),
+  new CFl(),
+  new CFm(),
+  new CFn(),
+  new CFo(),
+  new CFp(),
+  new CFq(),
+  new CFr(),
+  new CFs(),
+  new CFt(),
+  new CFu(),
+  new CFv(),
+  new CFw(),
+  new CFx(),
+  new CFy(),
+  new CFz(),
+  new CFA(),
+  new CFB(),
+  new CFC(),
+  new CFD(),
+  new CFE(),
+  new CFF(),
+  new CFG(),
+  new CFH(),
+  new CFI(),
+  new CFJ(),
+  new CFK(),
+  new CFL(),
+  new CFM(),
+  new CFN(),
+  new CFO(),
+  new CFP(),
+  new CFQ(),
+  new CFR(),
+  new CFS(),
+  new CFT(),
+  new CFU(),
+  new CFV(),
+  new CFW(),
+  new CFX(),
+  new CFY(),
+  new CFZ(),
+  new CGa(),
+  new CGb(),
+  new CGc(),
+  new CGd(),
+  new CGe(),
+  new CGf(),
+  new CGg(),
+  new CGh(),
+  new CGi(),
+  new CGj(),
+  new CGk(),
+  new CGl(),
+  new CGm(),
+  new CGn(),
+  new CGo(),
+  new CGp(),
+  new CGq(),
+  new CGr(),
+  new CGs(),
+  new CGt(),
+  new CGu(),
+  new CGv(),
+  new CGw(),
+  new CGx(),
+  new CGy(),
+  new CGz(),
+  new CGA(),
+  new CGB(),
+  new CGC(),
+  new CGD(),
+  new CGE(),
+  new CGF(),
+  new CGG(),
+  new CGH(),
+  new CGI(),
+  new CGJ(),
+  new CGK(),
+  new CGL(),
+  new CGM(),
+  new CGN(),
+  new CGO(),
+  new CGP(),
+  new CGQ(),
+  new CGR(),
+  new CGS(),
+  new CGT(),
+  new CGU(),
+  new CGV(),
+  new CGW(),
+  new CGX(),
+  new CGY(),
+  new CGZ(),
+  new CHa(),
+  new CHb(),
+  new CHc(),
+  new CHd(),
+  new CHe(),
+  new CHf(),
+  new CHg(),
+  new CHh(),
+  new CHi(),
+  new CHj(),
+  new CHk(),
+  new CHl(),
+  new CHm(),
+  new CHn(),
+  new CHo(),
+  new CHp(),
+  new CHq(),
+  new CHr(),
+  new CHs(),
+  new CHt(),
+  new CHu(),
+  new CHv(),
+  new CHw(),
+  new CHx(),
+  new CHy(),
+  new CHz(),
+  new CHA(),
+  new CHB(),
+  new CHC(),
+  new CHD(),
+  new CHE(),
+  new CHF(),
+  new CHG(),
+  new CHH(),
+  new CHI(),
+  new CHJ(),
+  new CHK(),
+  new CHL(),
+  new CHM(),
+  new CHN(),
+  new CHO(),
+  new CHP(),
+  new CHQ(),
+  new CHR(),
+  new CHS(),
+  new CHT(),
+  new CHU(),
+  new CHV(),
+  new CHW(),
+  new CHX(),
+  new CHY(),
+  new CHZ(),
+  new CIa(),
+  new CIb(),
+  new CIc(),
+  new CId(),
+  new CIe(),
+  new CIf(),
+  new CIg(),
+  new CIh(),
+  new CIi(),
+  new CIj(),
+  new CIk(),
+  new CIl(),
+  new CIm(),
+  new CIn(),
+  new CIo(),
+  new CIp(),
+  new CIq(),
+  new CIr(),
+  new CIs(),
+  new CIt(),
+  new CIu(),
+  new CIv(),
+  new CIw(),
+  new CIx(),
+  new CIy(),
+  new CIz(),
+  new CIA(),
+  new CIB(),
+  new CIC(),
+  new CID(),
+  new CIE(),
+  new CIF(),
+  new CIG(),
+  new CIH(),
+  new CII(),
+  new CIJ(),
+  new CIK(),
+  new CIL(),
+  new CIM(),
+  new CIN(),
+  new CIO(),
+  new CIP(),
+  new CIQ(),
+  new CIR(),
+  new CIS(),
+  new CIT(),
+  new CIU(),
+  new CIV(),
+  new CIW(),
+  new CIX(),
+  new CIY(),
+  new CIZ(),
+  new CJa(),
+  new CJb(),
+  new CJc(),
+  new CJd(),
+  new CJe(),
+  new CJf(),
+  new CJg(),
+  new CJh(),
+  new CJi(),
+  new CJj(),
+  new CJk(),
+  new CJl(),
+  new CJm(),
+  new CJn(),
+  new CJo(),
+  new CJp(),
+  new CJq(),
+  new CJr(),
+  new CJs(),
+  new CJt(),
+  new CJu(),
+  new CJv(),
+  new CJw(),
+  new CJx(),
+  new CJy(),
+  new CJz(),
+  new CJA(),
+  new CJB(),
+  new CJC(),
+  new CJD(),
+  new CJE(),
+  new CJF(),
+  new CJG(),
+  new CJH(),
+  new CJI(),
+  new CJJ(),
+  new CJK(),
+  new CJL(),
+  new CJM(),
+  new CJN(),
+  new CJO(),
+  new CJP(),
+  new CJQ(),
+  new CJR(),
+  new CJS(),
+  new CJT(),
+  new CJU(),
+  new CJV(),
+  new CJW(),
+  new CJX(),
+  new CJY(),
+  new CJZ(),
+  new CKa(),
+  new CKb(),
+  new CKc(),
+  new CKd(),
+  new CKe(),
+  new CKf(),
+  new CKg(),
+  new CKh(),
+  new CKi(),
+  new CKj(),
+  new CKk(),
+  new CKl(),
+  new CKm(),
+  new CKn(),
+  new CKo(),
+  new CKp(),
+  new CKq(),
+  new CKr(),
+  new CKs(),
+  new CKt(),
+  new CKu(),
+  new CKv(),
+  new CKw(),
+  new CKx(),
+  new CKy(),
+  new CKz(),
+  new CKA(),
+  new CKB(),
+  new CKC(),
+  new CKD(),
+  new CKE(),
+  new CKF(),
+  new CKG(),
+  new CKH(),
+  new CKI(),
+  new CKJ(),
+  new CKK(),
+  new CKL(),
+  new CKM(),
+  new CKN(),
+  new CKO(),
+  new CKP(),
+  new CKQ(),
+  new CKR(),
+  new CKS(),
+  new CKT(),
+  new CKU(),
+  new CKV(),
+  new CKW(),
+  new CKX(),
+  new CKY(),
+  new CKZ(),
+  new CLa(),
+  new CLb(),
+  new CLc(),
+  new CLd(),
+  new CLe(),
+  new CLf(),
+  new CLg(),
+  new CLh(),
+  new CLi(),
+  new CLj(),
+  new CLk(),
+  new CLl(),
+  new CLm(),
+  new CLn(),
+  new CLo(),
+  new CLp(),
+  new CLq(),
+  new CLr(),
+  new CLs(),
+  new CLt(),
+  new CLu(),
+  new CLv(),
+  new CLw(),
+  new CLx(),
+  new CLy(),
+  new CLz(),
+  new CLA(),
+  new CLB(),
+  new CLC(),
+  new CLD(),
+  new CLE(),
+  new CLF(),
+  new CLG(),
+  new CLH(),
+  new CLI(),
+  new CLJ(),
+  new CLK(),
+  new CLL(),
+  new CLM(),
+  new CLN(),
+  new CLO(),
+  new CLP(),
+  new CLQ(),
+  new CLR(),
+  new CLS(),
+  new CLT(),
+  new CLU(),
+  new CLV(),
+  new CLW(),
+  new CLX(),
+  new CLY(),
+  new CLZ(),
+  new CMa(),
+  new CMb(),
+  new CMc(),
+  new CMd(),
+  new CMe(),
+  new CMf(),
+  new CMg(),
+  new CMh(),
+  new CMi(),
+  new CMj(),
+  new CMk(),
+  new CMl(),
+  new CMm(),
+  new CMn(),
+  new CMo(),
+  new CMp(),
+  new CMq(),
+  new CMr(),
+  new CMs(),
+  new CMt(),
+  new CMu(),
+  new CMv(),
+  new CMw(),
+  new CMx(),
+  new CMy(),
+  new CMz(),
+  new CMA(),
+  new CMB(),
+  new CMC(),
+  new CMD(),
+  new CME(),
+  new CMF(),
+  new CMG(),
+  new CMH(),
+  new CMI(),
+  new CMJ(),
+  new CMK(),
+  new CML(),
+  new CMM(),
+  new CMN(),
+  new CMO(),
+  new CMP(),
+  new CMQ(),
+  new CMR(),
+  new CMS(),
+  new CMT(),
+  new CMU(),
+  new CMV(),
+  new CMW(),
+  new CMX(),
+  new CMY(),
+  new CMZ(),
+  new CNa(),
+  new CNb(),
+  new CNc(),
+  new CNd(),
+  new CNe(),
+  new CNf(),
+  new CNg(),
+  new CNh(),
+  new CNi(),
+  new CNj(),
+  new CNk(),
+  new CNl(),
+  new CNm(),
+  new CNn(),
+  new CNo(),
+  new CNp(),
+  new CNq(),
+  new CNr(),
+  new CNs(),
+  new CNt(),
+  new CNu(),
+  new CNv(),
+  new CNw(),
+  new CNx(),
+  new CNy(),
+  new CNz(),
+  new CNA(),
+  new CNB(),
+  new CNC(),
+  new CND(),
+  new CNE(),
+  new CNF(),
+  new CNG(),
+  new CNH(),
+  new CNI(),
+  new CNJ(),
+  new CNK(),
+  new CNL(),
+  new CNM(),
+  new CNN(),
+  new CNO(),
+  new CNP(),
+  new CNQ(),
+  new CNR(),
+  new CNS(),
+  new CNT(),
+  new CNU(),
+  new CNV(),
+  new CNW(),
+  new CNX(),
+  new CNY(),
+  new CNZ(),
+  new COa(),
+  new COb(),
+  new COc(),
+  new COd(),
+  new COe(),
+  new COf(),
+  new COg(),
+  new COh(),
+  new COi(),
+  new COj(),
+  new COk(),
+  new COl(),
+  new COm(),
+  new COn(),
+  new COo(),
+  new COp(),
+  new COq(),
+  new COr(),
+  new COs(),
+  new COt(),
+  new COu(),
+  new COv(),
+  new COw(),
+  new COx(),
+  new COy(),
+  new COz(),
+  new COA(),
+  new COB(),
+  new COC(),
+  new COD(),
+  new COE(),
+  new COF(),
+  new COG(),
+  new COH(),
+  new COI(),
+  new COJ(),
+  new COK(),
+  new COL(),
+  new COM(),
+  new CON(),
+  new COO(),
+  new COP(),
+  new COQ(),
+  new COR(),
+  new COS(),
+  new COT(),
+  new COU(),
+  new COV(),
+  new COW(),
+  new COX(),
+  new COY(),
+  new COZ(),
+  new CPa(),
+  new CPb(),
+  new CPc(),
+  new CPd(),
+  new CPe(),
+  new CPf(),
+  new CPg(),
+  new CPh(),
+  new CPi(),
+  new CPj(),
+  new CPk(),
+  new CPl(),
+  new CPm(),
+  new CPn(),
+  new CPo(),
+  new CPp(),
+  new CPq(),
+  new CPr(),
+  new CPs(),
+  new CPt(),
+  new CPu(),
+  new CPv(),
+  new CPw(),
+  new CPx(),
+  new CPy(),
+  new CPz(),
+  new CPA(),
+  new CPB(),
+  new CPC(),
+  new CPD(),
+  new CPE(),
+  new CPF(),
+  new CPG(),
+  new CPH(),
+  new CPI(),
+  new CPJ(),
+  new CPK(),
+  new CPL(),
+  new CPM(),
+  new CPN(),
+  new CPO(),
+  new CPP(),
+  new CPQ(),
+  new CPR(),
+  new CPS(),
+  new CPT(),
+  new CPU(),
+  new CPV(),
+  new CPW(),
+  new CPX(),
+  new CPY(),
+  new CPZ(),
+  new CQa(),
+  new CQb(),
+  new CQc(),
+  new CQd(),
+  new CQe(),
+  new CQf(),
+  new CQg(),
+  new CQh(),
+  new CQi(),
+  new CQj(),
+  new CQk(),
+  new CQl(),
+  new CQm(),
+  new CQn(),
+  new CQo(),
+  new CQp(),
+  new CQq(),
+  new CQr(),
+  new CQs(),
+  new CQt(),
+  new CQu(),
+  new CQv(),
+  new CQw(),
+  new CQx(),
+  new CQy(),
+  new CQz(),
+  new CQA(),
+  new CQB(),
+  new CQC(),
+  new CQD(),
+  new CQE(),
+  new CQF(),
+  new CQG(),
+  new CQH(),
+  new CQI(),
+  new CQJ(),
+  new CQK(),
+  new CQL(),
+  new CQM(),
+  new CQN(),
+  new CQO(),
+  new CQP(),
+  new CQQ(),
+  new CQR(),
+  new CQS(),
+  new CQT(),
+  new CQU(),
+  new CQV(),
+  new CQW(),
+  new CQX(),
+  new CQY(),
+  new CQZ(),
+  new CRa(),
+  new CRb(),
+  new CRc(),
+  new CRd(),
+  new CRe(),
+  new CRf(),
+  new CRg(),
+  new CRh(),
+  new CRi(),
+  new CRj(),
+  new CRk(),
+  new CRl(),
+  new CRm(),
+  new CRn(),
+  new CRo(),
+  new CRp(),
+  new CRq(),
+  new CRr(),
+  new CRs(),
+  new CRt(),
+  new CRu(),
+  new CRv(),
+  new CRw(),
+  new CRx(),
+  new CRy(),
+  new CRz(),
+  new CRA(),
+  new CRB(),
+  new CRC(),
+  new CRD(),
+  new CRE(),
+  new CRF(),
+  new CRG(),
+  new CRH(),
+  new CRI(),
+  new CRJ(),
+  new CRK(),
+  new CRL(),
+  new CRM(),
+  new CRN(),
+  new CRO(),
+  new CRP(),
+  new CRQ(),
+  new CRR(),
+  new CRS(),
+  new CRT(),
+  new CRU(),
+  new CRV(),
+  new CRW(),
+  new CRX(),
+  new CRY(),
+  new CRZ(),
+  new CSa(),
+  new CSb(),
+  new CSc(),
+  new CSd(),
+  new CSe(),
+  new CSf(),
+  new CSg(),
+  new CSh(),
+  new CSi(),
+  new CSj(),
+  new CSk(),
+  new CSl(),
+  new CSm(),
+  new CSn(),
+  new CSo(),
+  new CSp(),
+  new CSq(),
+  new CSr(),
+  new CSs(),
+  new CSt(),
+  new CSu(),
+  new CSv(),
+  new CSw(),
+  new CSx(),
+  new CSy(),
+  new CSz(),
+  new CSA(),
+  new CSB(),
+  new CSC(),
+  new CSD(),
+  new CSE(),
+  new CSF(),
+  new CSG(),
+  new CSH(),
+  new CSI(),
+  new CSJ(),
+  new CSK(),
+  new CSL(),
+  new CSM(),
+  new CSN(),
+  new CSO(),
+  new CSP(),
+  new CSQ(),
+  new CSR(),
+  new CSS(),
+  new CST(),
+  new CSU(),
+  new CSV(),
+  new CSW(),
+  new CSX(),
+  new CSY(),
+  new CSZ(),
+  new CTa(),
+  new CTb(),
+  new CTc(),
+  new CTd(),
+  new CTe(),
+  new CTf(),
+  new CTg(),
+  new CTh(),
+  new CTi(),
+  new CTj(),
+  new CTk(),
+  new CTl(),
+  new CTm(),
+  new CTn(),
+  new CTo(),
+  new CTp(),
+  new CTq(),
+  new CTr(),
+  new CTs(),
+  new CTt(),
+  new CTu(),
+  new CTv(),
+  new CTw(),
+  new CTx(),
+  new CTy(),
+  new CTz(),
+  new CTA(),
+  new CTB(),
+  new CTC(),
+  new CTD(),
+  new CTE(),
+  new CTF(),
+  new CTG(),
+  new CTH(),
+  new CTI(),
+  new CTJ(),
+  new CTK(),
+  new CTL(),
+  new CTM(),
+  new CTN(),
+  new CTO(),
+  new CTP(),
+  new CTQ(),
+  new CTR(),
+  new CTS(),
+  new CTT(),
+  new CTU(),
+  new CTV(),
+  new CTW(),
+  new CTX(),
+  new CTY(),
+  new CTZ(),
+  new CUa(),
+  new CUb(),
+  new CUc(),
+  new CUd(),
+  new CUe(),
+  new CUf(),
+  new CUg(),
+  new CUh(),
+  new CUi(),
+  new CUj(),
+  new CUk(),
+  new CUl(),
+  new CUm(),
+  new CUn(),
+  new CUo(),
+  new CUp(),
+  new CUq(),
+  new CUr(),
+  new CUs(),
+  new CUt(),
+  new CUu(),
+  new CUv(),
+  new CUw(),
+  new CUx(),
+  new CUy(),
+  new CUz(),
+  new CUA(),
+  new CUB(),
+  new CUC(),
+  new CUD(),
+  new CUE(),
+  new CUF(),
+  new CUG(),
+  new CUH(),
+  new CUI(),
+  new CUJ(),
+  new CUK(),
+  new CUL(),
+  new CUM(),
+  new CUN(),
+  new CUO(),
+  new CUP(),
+  new CUQ(),
+  new CUR(),
+  new CUS(),
+  new CUT(),
+  new CUU(),
+  new CUV(),
+  new CUW(),
+  new CUX(),
+  new CUY(),
+  new CUZ(),
+  new CVa(),
+  new CVb(),
+  new CVc(),
+  new CVd(),
+  new CVe(),
+  new CVf(),
+  new CVg(),
+  new CVh(),
+  new CVi(),
+  new CVj(),
+  new CVk(),
+  new CVl(),
+  new CVm(),
+  new CVn(),
+  new CVo(),
+  new CVp(),
+  new CVq(),
+  new CVr(),
+  new CVs(),
+  new CVt(),
+  new CVu(),
+  new CVv(),
+  new CVw(),
+  new CVx(),
+  new CVy(),
+  new CVz(),
+  new CVA(),
+  new CVB(),
+  new CVC(),
+  new CVD(),
+  new CVE(),
+  new CVF(),
+  new CVG(),
+  new CVH(),
+  new CVI(),
+  new CVJ(),
+  new CVK(),
+  new CVL(),
+  new CVM(),
+  new CVN(),
+  new CVO(),
+  new CVP(),
+  new CVQ(),
+  new CVR(),
+  new CVS(),
+  new CVT(),
+  new CVU(),
+  new CVV(),
+  new CVW(),
+  new CVX(),
+  new CVY(),
+  new CVZ(),
+  new CWa(),
+  new CWb(),
+  new CWc(),
+  new CWd(),
+  new CWe(),
+  new CWf(),
+  new CWg(),
+  new CWh(),
+  new CWi(),
+  new CWj(),
+  new CWk(),
+  new CWl(),
+  new CWm(),
+  new CWn(),
+  new CWo(),
+  new CWp(),
+  new CWq(),
+  new CWr(),
+  new CWs(),
+  new CWt(),
+  new CWu(),
+  new CWv(),
+  new CWw(),
+  new CWx(),
+  new CWy(),
+  new CWz(),
+  new CWA(),
+  new CWB(),
+  new CWC(),
+  new CWD(),
+  new CWE(),
+  new CWF(),
+  new CWG(),
+  new CWH(),
+  new CWI(),
+  new CWJ(),
+  new CWK(),
+  new CWL(),
+  new CWM(),
+  new CWN(),
+  new CWO(),
+  new CWP(),
+  new CWQ(),
+  new CWR(),
+  new CWS(),
+  new CWT(),
+  new CWU(),
+  new CWV(),
+  new CWW(),
+  new CWX(),
+  new CWY(),
+  new CWZ(),
+  new CXa(),
+  new CXb(),
+  new CXc(),
+  new CXd(),
+  new CXe(),
+  new CXf(),
+  new CXg(),
+  new CXh(),
+  new CXi(),
+  new CXj(),
+  new CXk(),
+  new CXl(),
+  new CXm(),
+  new CXn(),
+  new CXo(),
+  new CXp(),
+  new CXq(),
+  new CXr(),
+  new CXs(),
+  new CXt(),
+  new CXu(),
+  new CXv(),
+  new CXw(),
+  new CXx(),
+  new CXy(),
+  new CXz(),
+  new CXA(),
+  new CXB(),
+  new CXC(),
+  new CXD(),
+  new CXE(),
+  new CXF(),
+  new CXG(),
+  new CXH(),
+  new CXI(),
+  new CXJ(),
+  new CXK(),
+  new CXL(),
+  new CXM(),
+  new CXN(),
+  new CXO(),
+  new CXP(),
+  new CXQ(),
+  new CXR(),
+  new CXS(),
+  new CXT(),
+  new CXU(),
+  new CXV(),
+  new CXW(),
+  new CXX(),
+  new CXY(),
+  new CXZ(),
+  new CYa(),
+  new CYb(),
+  new CYc(),
+  new CYd(),
+  new CYe(),
+  new CYf(),
+  new CYg(),
+  new CYh(),
+  new CYi(),
+  new CYj(),
+  new CYk(),
+  new CYl(),
+  new CYm(),
+  new CYn(),
+  new CYo(),
+  new CYp(),
+  new CYq(),
+  new CYr(),
+  new CYs(),
+  new CYt(),
+  new CYu(),
+  new CYv(),
+  new CYw(),
+  new CYx(),
+  new CYy(),
+  new CYz(),
+  new CYA(),
+  new CYB(),
+  new CYC(),
+  new CYD(),
+  new CYE(),
+  new CYF(),
+  new CYG(),
+  new CYH(),
+  new CYI(),
+  new CYJ(),
+  new CYK(),
+  new CYL(),
+  new CYM(),
+  new CYN(),
+  new CYO(),
+  new CYP(),
+  new CYQ(),
+  new CYR(),
+  new CYS(),
+  new CYT(),
+  new CYU(),
+  new CYV(),
+  new CYW(),
+  new CYX(),
+  new CYY(),
+  new CYZ(),
+  new CZa(),
+  new CZb(),
+  new CZc(),
+  new CZd(),
+  new CZe(),
+  new CZf(),
+  new CZg(),
+  new CZh(),
+  new CZi(),
+  new CZj(),
+  new CZk(),
+  new CZl(),
+  new CZm(),
+  new CZn(),
+  new CZo(),
+  new CZp(),
+  new CZq(),
+  new CZr(),
+  new CZs(),
+  new CZt(),
+  new CZu(),
+  new CZv(),
+  new CZw(),
+  new CZx(),
+  new CZy(),
+  new CZz(),
+  new CZA(),
+  new CZB(),
+  new CZC(),
+  new CZD(),
+  new CZE(),
+  new CZF(),
+  new CZG(),
+  new CZH(),
+  new CZI(),
+  new CZJ(),
+  new CZK(),
+  new CZL(),
+  new CZM(),
+  new CZN(),
+  new CZO(),
+  new CZP(),
+  new CZQ(),
+  new CZR(),
+  new CZS(),
+  new CZT(),
+  new CZU(),
+  new CZV(),
+  new CZW(),
+  new CZX(),
+  new CZY(),
+  new CZZ(),
+];
+class Caa{}
+class Cab{}
+class Cac{}
+class Cad{}
+class Cae{}
+class Caf{}
+class Cag{}
+class Cah{}
+class Cai{}
+class Caj{}
+class Cak{}
+class Cal{}
+class Cam{}
+class Can{}
+class Cao{}
+class Cap{}
+class Caq{}
+class Car{}
+class Cas{}
+class Cat{}
+class Cau{}
+class Cav{}
+class Caw{}
+class Cax{}
+class Cay{}
+class Caz{}
+class CaA{}
+class CaB{}
+class CaC{}
+class CaD{}
+class CaE{}
+class CaF{}
+class CaG{}
+class CaH{}
+class CaI{}
+class CaJ{}
+class CaK{}
+class CaL{}
+class CaM{}
+class CaN{}
+class CaO{}
+class CaP{}
+class CaQ{}
+class CaR{}
+class CaS{}
+class CaT{}
+class CaU{}
+class CaV{}
+class CaW{}
+class CaX{}
+class CaY{}
+class CaZ{}
+class Cba{}
+class Cbb{}
+class Cbc{}
+class Cbd{}
+class Cbe{}
+class Cbf{}
+class Cbg{}
+class Cbh{}
+class Cbi{}
+class Cbj{}
+class Cbk{}
+class Cbl{}
+class Cbm{}
+class Cbn{}
+class Cbo{}
+class Cbp{}
+class Cbq{}
+class Cbr{}
+class Cbs{}
+class Cbt{}
+class Cbu{}
+class Cbv{}
+class Cbw{}
+class Cbx{}
+class Cby{}
+class Cbz{}
+class CbA{}
+class CbB{}
+class CbC{}
+class CbD{}
+class CbE{}
+class CbF{}
+class CbG{}
+class CbH{}
+class CbI{}
+class CbJ{}
+class CbK{}
+class CbL{}
+class CbM{}
+class CbN{}
+class CbO{}
+class CbP{}
+class CbQ{}
+class CbR{}
+class CbS{}
+class CbT{}
+class CbU{}
+class CbV{}
+class CbW{}
+class CbX{}
+class CbY{}
+class CbZ{}
+class Cca{}
+class Ccb{}
+class Ccc{}
+class Ccd{}
+class Cce{}
+class Ccf{}
+class Ccg{}
+class Cch{}
+class Cci{}
+class Ccj{}
+class Cck{}
+class Ccl{}
+class Ccm{}
+class Ccn{}
+class Cco{}
+class Ccp{}
+class Ccq{}
+class Ccr{}
+class Ccs{}
+class Cct{}
+class Ccu{}
+class Ccv{}
+class Ccw{}
+class Ccx{}
+class Ccy{}
+class Ccz{}
+class CcA{}
+class CcB{}
+class CcC{}
+class CcD{}
+class CcE{}
+class CcF{}
+class CcG{}
+class CcH{}
+class CcI{}
+class CcJ{}
+class CcK{}
+class CcL{}
+class CcM{}
+class CcN{}
+class CcO{}
+class CcP{}
+class CcQ{}
+class CcR{}
+class CcS{}
+class CcT{}
+class CcU{}
+class CcV{}
+class CcW{}
+class CcX{}
+class CcY{}
+class CcZ{}
+class Cda{}
+class Cdb{}
+class Cdc{}
+class Cdd{}
+class Cde{}
+class Cdf{}
+class Cdg{}
+class Cdh{}
+class Cdi{}
+class Cdj{}
+class Cdk{}
+class Cdl{}
+class Cdm{}
+class Cdn{}
+class Cdo{}
+class Cdp{}
+class Cdq{}
+class Cdr{}
+class Cds{}
+class Cdt{}
+class Cdu{}
+class Cdv{}
+class Cdw{}
+class Cdx{}
+class Cdy{}
+class Cdz{}
+class CdA{}
+class CdB{}
+class CdC{}
+class CdD{}
+class CdE{}
+class CdF{}
+class CdG{}
+class CdH{}
+class CdI{}
+class CdJ{}
+class CdK{}
+class CdL{}
+class CdM{}
+class CdN{}
+class CdO{}
+class CdP{}
+class CdQ{}
+class CdR{}
+class CdS{}
+class CdT{}
+class CdU{}
+class CdV{}
+class CdW{}
+class CdX{}
+class CdY{}
+class CdZ{}
+class Cea{}
+class Ceb{}
+class Cec{}
+class Ced{}
+class Cee{}
+class Cef{}
+class Ceg{}
+class Ceh{}
+class Cei{}
+class Cej{}
+class Cek{}
+class Cel{}
+class Cem{}
+class Cen{}
+class Ceo{}
+class Cep{}
+class Ceq{}
+class Cer{}
+class Ces{}
+class Cet{}
+class Ceu{}
+class Cev{}
+class Cew{}
+class Cex{}
+class Cey{}
+class Cez{}
+class CeA{}
+class CeB{}
+class CeC{}
+class CeD{}
+class CeE{}
+class CeF{}
+class CeG{}
+class CeH{}
+class CeI{}
+class CeJ{}
+class CeK{}
+class CeL{}
+class CeM{}
+class CeN{}
+class CeO{}
+class CeP{}
+class CeQ{}
+class CeR{}
+class CeS{}
+class CeT{}
+class CeU{}
+class CeV{}
+class CeW{}
+class CeX{}
+class CeY{}
+class CeZ{}
+class Cfa{}
+class Cfb{}
+class Cfc{}
+class Cfd{}
+class Cfe{}
+class Cff{}
+class Cfg{}
+class Cfh{}
+class Cfi{}
+class Cfj{}
+class Cfk{}
+class Cfl{}
+class Cfm{}
+class Cfn{}
+class Cfo{}
+class Cfp{}
+class Cfq{}
+class Cfr{}
+class Cfs{}
+class Cft{}
+class Cfu{}
+class Cfv{}
+class Cfw{}
+class Cfx{}
+class Cfy{}
+class Cfz{}
+class CfA{}
+class CfB{}
+class CfC{}
+class CfD{}
+class CfE{}
+class CfF{}
+class CfG{}
+class CfH{}
+class CfI{}
+class CfJ{}
+class CfK{}
+class CfL{}
+class CfM{}
+class CfN{}
+class CfO{}
+class CfP{}
+class CfQ{}
+class CfR{}
+class CfS{}
+class CfT{}
+class CfU{}
+class CfV{}
+class CfW{}
+class CfX{}
+class CfY{}
+class CfZ{}
+class Cga{}
+class Cgb{}
+class Cgc{}
+class Cgd{}
+class Cge{}
+class Cgf{}
+class Cgg{}
+class Cgh{}
+class Cgi{}
+class Cgj{}
+class Cgk{}
+class Cgl{}
+class Cgm{}
+class Cgn{}
+class Cgo{}
+class Cgp{}
+class Cgq{}
+class Cgr{}
+class Cgs{}
+class Cgt{}
+class Cgu{}
+class Cgv{}
+class Cgw{}
+class Cgx{}
+class Cgy{}
+class Cgz{}
+class CgA{}
+class CgB{}
+class CgC{}
+class CgD{}
+class CgE{}
+class CgF{}
+class CgG{}
+class CgH{}
+class CgI{}
+class CgJ{}
+class CgK{}
+class CgL{}
+class CgM{}
+class CgN{}
+class CgO{}
+class CgP{}
+class CgQ{}
+class CgR{}
+class CgS{}
+class CgT{}
+class CgU{}
+class CgV{}
+class CgW{}
+class CgX{}
+class CgY{}
+class CgZ{}
+class Cha{}
+class Chb{}
+class Chc{}
+class Chd{}
+class Che{}
+class Chf{}
+class Chg{}
+class Chh{}
+class Chi{}
+class Chj{}
+class Chk{}
+class Chl{}
+class Chm{}
+class Chn{}
+class Cho{}
+class Chp{}
+class Chq{}
+class Chr{}
+class Chs{}
+class Cht{}
+class Chu{}
+class Chv{}
+class Chw{}
+class Chx{}
+class Chy{}
+class Chz{}
+class ChA{}
+class ChB{}
+class ChC{}
+class ChD{}
+class ChE{}
+class ChF{}
+class ChG{}
+class ChH{}
+class ChI{}
+class ChJ{}
+class ChK{}
+class ChL{}
+class ChM{}
+class ChN{}
+class ChO{}
+class ChP{}
+class ChQ{}
+class ChR{}
+class ChS{}
+class ChT{}
+class ChU{}
+class ChV{}
+class ChW{}
+class ChX{}
+class ChY{}
+class ChZ{}
+class Cia{}
+class Cib{}
+class Cic{}
+class Cid{}
+class Cie{}
+class Cif{}
+class Cig{}
+class Cih{}
+class Cii{}
+class Cij{}
+class Cik{}
+class Cil{}
+class Cim{}
+class Cin{}
+class Cio{}
+class Cip{}
+class Ciq{}
+class Cir{}
+class Cis{}
+class Cit{}
+class Ciu{}
+class Civ{}
+class Ciw{}
+class Cix{}
+class Ciy{}
+class Ciz{}
+class CiA{}
+class CiB{}
+class CiC{}
+class CiD{}
+class CiE{}
+class CiF{}
+class CiG{}
+class CiH{}
+class CiI{}
+class CiJ{}
+class CiK{}
+class CiL{}
+class CiM{}
+class CiN{}
+class CiO{}
+class CiP{}
+class CiQ{}
+class CiR{}
+class CiS{}
+class CiT{}
+class CiU{}
+class CiV{}
+class CiW{}
+class CiX{}
+class CiY{}
+class CiZ{}
+class Cja{}
+class Cjb{}
+class Cjc{}
+class Cjd{}
+class Cje{}
+class Cjf{}
+class Cjg{}
+class Cjh{}
+class Cji{}
+class Cjj{}
+class Cjk{}
+class Cjl{}
+class Cjm{}
+class Cjn{}
+class Cjo{}
+class Cjp{}
+class Cjq{}
+class Cjr{}
+class Cjs{}
+class Cjt{}
+class Cju{}
+class Cjv{}
+class Cjw{}
+class Cjx{}
+class Cjy{}
+class Cjz{}
+class CjA{}
+class CjB{}
+class CjC{}
+class CjD{}
+class CjE{}
+class CjF{}
+class CjG{}
+class CjH{}
+class CjI{}
+class CjJ{}
+class CjK{}
+class CjL{}
+class CjM{}
+class CjN{}
+class CjO{}
+class CjP{}
+class CjQ{}
+class CjR{}
+class CjS{}
+class CjT{}
+class CjU{}
+class CjV{}
+class CjW{}
+class CjX{}
+class CjY{}
+class CjZ{}
+class Cka{}
+class Ckb{}
+class Ckc{}
+class Ckd{}
+class Cke{}
+class Ckf{}
+class Ckg{}
+class Ckh{}
+class Cki{}
+class Ckj{}
+class Ckk{}
+class Ckl{}
+class Ckm{}
+class Ckn{}
+class Cko{}
+class Ckp{}
+class Ckq{}
+class Ckr{}
+class Cks{}
+class Ckt{}
+class Cku{}
+class Ckv{}
+class Ckw{}
+class Ckx{}
+class Cky{}
+class Ckz{}
+class CkA{}
+class CkB{}
+class CkC{}
+class CkD{}
+class CkE{}
+class CkF{}
+class CkG{}
+class CkH{}
+class CkI{}
+class CkJ{}
+class CkK{}
+class CkL{}
+class CkM{}
+class CkN{}
+class CkO{}
+class CkP{}
+class CkQ{}
+class CkR{}
+class CkS{}
+class CkT{}
+class CkU{}
+class CkV{}
+class CkW{}
+class CkX{}
+class CkY{}
+class CkZ{}
+class Cla{}
+class Clb{}
+class Clc{}
+class Cld{}
+class Cle{}
+class Clf{}
+class Clg{}
+class Clh{}
+class Cli{}
+class Clj{}
+class Clk{}
+class Cll{}
+class Clm{}
+class Cln{}
+class Clo{}
+class Clp{}
+class Clq{}
+class Clr{}
+class Cls{}
+class Clt{}
+class Clu{}
+class Clv{}
+class Clw{}
+class Clx{}
+class Cly{}
+class Clz{}
+class ClA{}
+class ClB{}
+class ClC{}
+class ClD{}
+class ClE{}
+class ClF{}
+class ClG{}
+class ClH{}
+class ClI{}
+class ClJ{}
+class ClK{}
+class ClL{}
+class ClM{}
+class ClN{}
+class ClO{}
+class ClP{}
+class ClQ{}
+class ClR{}
+class ClS{}
+class ClT{}
+class ClU{}
+class ClV{}
+class ClW{}
+class ClX{}
+class ClY{}
+class ClZ{}
+class Cma{}
+class Cmb{}
+class Cmc{}
+class Cmd{}
+class Cme{}
+class Cmf{}
+class Cmg{}
+class Cmh{}
+class Cmi{}
+class Cmj{}
+class Cmk{}
+class Cml{}
+class Cmm{}
+class Cmn{}
+class Cmo{}
+class Cmp{}
+class Cmq{}
+class Cmr{}
+class Cms{}
+class Cmt{}
+class Cmu{}
+class Cmv{}
+class Cmw{}
+class Cmx{}
+class Cmy{}
+class Cmz{}
+class CmA{}
+class CmB{}
+class CmC{}
+class CmD{}
+class CmE{}
+class CmF{}
+class CmG{}
+class CmH{}
+class CmI{}
+class CmJ{}
+class CmK{}
+class CmL{}
+class CmM{}
+class CmN{}
+class CmO{}
+class CmP{}
+class CmQ{}
+class CmR{}
+class CmS{}
+class CmT{}
+class CmU{}
+class CmV{}
+class CmW{}
+class CmX{}
+class CmY{}
+class CmZ{}
+class Cna{}
+class Cnb{}
+class Cnc{}
+class Cnd{}
+class Cne{}
+class Cnf{}
+class Cng{}
+class Cnh{}
+class Cni{}
+class Cnj{}
+class Cnk{}
+class Cnl{}
+class Cnm{}
+class Cnn{}
+class Cno{}
+class Cnp{}
+class Cnq{}
+class Cnr{}
+class Cns{}
+class Cnt{}
+class Cnu{}
+class Cnv{}
+class Cnw{}
+class Cnx{}
+class Cny{}
+class Cnz{}
+class CnA{}
+class CnB{}
+class CnC{}
+class CnD{}
+class CnE{}
+class CnF{}
+class CnG{}
+class CnH{}
+class CnI{}
+class CnJ{}
+class CnK{}
+class CnL{}
+class CnM{}
+class CnN{}
+class CnO{}
+class CnP{}
+class CnQ{}
+class CnR{}
+class CnS{}
+class CnT{}
+class CnU{}
+class CnV{}
+class CnW{}
+class CnX{}
+class CnY{}
+class CnZ{}
+class Coa{}
+class Cob{}
+class Coc{}
+class Cod{}
+class Coe{}
+class Cof{}
+class Cog{}
+class Coh{}
+class Coi{}
+class Coj{}
+class Cok{}
+class Col{}
+class Com{}
+class Con{}
+class Coo{}
+class Cop{}
+class Coq{}
+class Cor{}
+class Cos{}
+class Cot{}
+class Cou{}
+class Cov{}
+class Cow{}
+class Cox{}
+class Coy{}
+class Coz{}
+class CoA{}
+class CoB{}
+class CoC{}
+class CoD{}
+class CoE{}
+class CoF{}
+class CoG{}
+class CoH{}
+class CoI{}
+class CoJ{}
+class CoK{}
+class CoL{}
+class CoM{}
+class CoN{}
+class CoO{}
+class CoP{}
+class CoQ{}
+class CoR{}
+class CoS{}
+class CoT{}
+class CoU{}
+class CoV{}
+class CoW{}
+class CoX{}
+class CoY{}
+class CoZ{}
+class Cpa{}
+class Cpb{}
+class Cpc{}
+class Cpd{}
+class Cpe{}
+class Cpf{}
+class Cpg{}
+class Cph{}
+class Cpi{}
+class Cpj{}
+class Cpk{}
+class Cpl{}
+class Cpm{}
+class Cpn{}
+class Cpo{}
+class Cpp{}
+class Cpq{}
+class Cpr{}
+class Cps{}
+class Cpt{}
+class Cpu{}
+class Cpv{}
+class Cpw{}
+class Cpx{}
+class Cpy{}
+class Cpz{}
+class CpA{}
+class CpB{}
+class CpC{}
+class CpD{}
+class CpE{}
+class CpF{}
+class CpG{}
+class CpH{}
+class CpI{}
+class CpJ{}
+class CpK{}
+class CpL{}
+class CpM{}
+class CpN{}
+class CpO{}
+class CpP{}
+class CpQ{}
+class CpR{}
+class CpS{}
+class CpT{}
+class CpU{}
+class CpV{}
+class CpW{}
+class CpX{}
+class CpY{}
+class CpZ{}
+class Cqa{}
+class Cqb{}
+class Cqc{}
+class Cqd{}
+class Cqe{}
+class Cqf{}
+class Cqg{}
+class Cqh{}
+class Cqi{}
+class Cqj{}
+class Cqk{}
+class Cql{}
+class Cqm{}
+class Cqn{}
+class Cqo{}
+class Cqp{}
+class Cqq{}
+class Cqr{}
+class Cqs{}
+class Cqt{}
+class Cqu{}
+class Cqv{}
+class Cqw{}
+class Cqx{}
+class Cqy{}
+class Cqz{}
+class CqA{}
+class CqB{}
+class CqC{}
+class CqD{}
+class CqE{}
+class CqF{}
+class CqG{}
+class CqH{}
+class CqI{}
+class CqJ{}
+class CqK{}
+class CqL{}
+class CqM{}
+class CqN{}
+class CqO{}
+class CqP{}
+class CqQ{}
+class CqR{}
+class CqS{}
+class CqT{}
+class CqU{}
+class CqV{}
+class CqW{}
+class CqX{}
+class CqY{}
+class CqZ{}
+class Cra{}
+class Crb{}
+class Crc{}
+class Crd{}
+class Cre{}
+class Crf{}
+class Crg{}
+class Crh{}
+class Cri{}
+class Crj{}
+class Crk{}
+class Crl{}
+class Crm{}
+class Crn{}
+class Cro{}
+class Crp{}
+class Crq{}
+class Crr{}
+class Crs{}
+class Crt{}
+class Cru{}
+class Crv{}
+class Crw{}
+class Crx{}
+class Cry{}
+class Crz{}
+class CrA{}
+class CrB{}
+class CrC{}
+class CrD{}
+class CrE{}
+class CrF{}
+class CrG{}
+class CrH{}
+class CrI{}
+class CrJ{}
+class CrK{}
+class CrL{}
+class CrM{}
+class CrN{}
+class CrO{}
+class CrP{}
+class CrQ{}
+class CrR{}
+class CrS{}
+class CrT{}
+class CrU{}
+class CrV{}
+class CrW{}
+class CrX{}
+class CrY{}
+class CrZ{}
+class Csa{}
+class Csb{}
+class Csc{}
+class Csd{}
+class Cse{}
+class Csf{}
+class Csg{}
+class Csh{}
+class Csi{}
+class Csj{}
+class Csk{}
+class Csl{}
+class Csm{}
+class Csn{}
+class Cso{}
+class Csp{}
+class Csq{}
+class Csr{}
+class Css{}
+class Cst{}
+class Csu{}
+class Csv{}
+class Csw{}
+class Csx{}
+class Csy{}
+class Csz{}
+class CsA{}
+class CsB{}
+class CsC{}
+class CsD{}
+class CsE{}
+class CsF{}
+class CsG{}
+class CsH{}
+class CsI{}
+class CsJ{}
+class CsK{}
+class CsL{}
+class CsM{}
+class CsN{}
+class CsO{}
+class CsP{}
+class CsQ{}
+class CsR{}
+class CsS{}
+class CsT{}
+class CsU{}
+class CsV{}
+class CsW{}
+class CsX{}
+class CsY{}
+class CsZ{}
+class Cta{}
+class Ctb{}
+class Ctc{}
+class Ctd{}
+class Cte{}
+class Ctf{}
+class Ctg{}
+class Cth{}
+class Cti{}
+class Ctj{}
+class Ctk{}
+class Ctl{}
+class Ctm{}
+class Ctn{}
+class Cto{}
+class Ctp{}
+class Ctq{}
+class Ctr{}
+class Cts{}
+class Ctt{}
+class Ctu{}
+class Ctv{}
+class Ctw{}
+class Ctx{}
+class Cty{}
+class Ctz{}
+class CtA{}
+class CtB{}
+class CtC{}
+class CtD{}
+class CtE{}
+class CtF{}
+class CtG{}
+class CtH{}
+class CtI{}
+class CtJ{}
+class CtK{}
+class CtL{}
+class CtM{}
+class CtN{}
+class CtO{}
+class CtP{}
+class CtQ{}
+class CtR{}
+class CtS{}
+class CtT{}
+class CtU{}
+class CtV{}
+class CtW{}
+class CtX{}
+class CtY{}
+class CtZ{}
+class Cua{}
+class Cub{}
+class Cuc{}
+class Cud{}
+class Cue{}
+class Cuf{}
+class Cug{}
+class Cuh{}
+class Cui{}
+class Cuj{}
+class Cuk{}
+class Cul{}
+class Cum{}
+class Cun{}
+class Cuo{}
+class Cup{}
+class Cuq{}
+class Cur{}
+class Cus{}
+class Cut{}
+class Cuu{}
+class Cuv{}
+class Cuw{}
+class Cux{}
+class Cuy{}
+class Cuz{}
+class CuA{}
+class CuB{}
+class CuC{}
+class CuD{}
+class CuE{}
+class CuF{}
+class CuG{}
+class CuH{}
+class CuI{}
+class CuJ{}
+class CuK{}
+class CuL{}
+class CuM{}
+class CuN{}
+class CuO{}
+class CuP{}
+class CuQ{}
+class CuR{}
+class CuS{}
+class CuT{}
+class CuU{}
+class CuV{}
+class CuW{}
+class CuX{}
+class CuY{}
+class CuZ{}
+class Cva{}
+class Cvb{}
+class Cvc{}
+class Cvd{}
+class Cve{}
+class Cvf{}
+class Cvg{}
+class Cvh{}
+class Cvi{}
+class Cvj{}
+class Cvk{}
+class Cvl{}
+class Cvm{}
+class Cvn{}
+class Cvo{}
+class Cvp{}
+class Cvq{}
+class Cvr{}
+class Cvs{}
+class Cvt{}
+class Cvu{}
+class Cvv{}
+class Cvw{}
+class Cvx{}
+class Cvy{}
+class Cvz{}
+class CvA{}
+class CvB{}
+class CvC{}
+class CvD{}
+class CvE{}
+class CvF{}
+class CvG{}
+class CvH{}
+class CvI{}
+class CvJ{}
+class CvK{}
+class CvL{}
+class CvM{}
+class CvN{}
+class CvO{}
+class CvP{}
+class CvQ{}
+class CvR{}
+class CvS{}
+class CvT{}
+class CvU{}
+class CvV{}
+class CvW{}
+class CvX{}
+class CvY{}
+class CvZ{}
+class Cwa{}
+class Cwb{}
+class Cwc{}
+class Cwd{}
+class Cwe{}
+class Cwf{}
+class Cwg{}
+class Cwh{}
+class Cwi{}
+class Cwj{}
+class Cwk{}
+class Cwl{}
+class Cwm{}
+class Cwn{}
+class Cwo{}
+class Cwp{}
+class Cwq{}
+class Cwr{}
+class Cws{}
+class Cwt{}
+class Cwu{}
+class Cwv{}
+class Cww{}
+class Cwx{}
+class Cwy{}
+class Cwz{}
+class CwA{}
+class CwB{}
+class CwC{}
+class CwD{}
+class CwE{}
+class CwF{}
+class CwG{}
+class CwH{}
+class CwI{}
+class CwJ{}
+class CwK{}
+class CwL{}
+class CwM{}
+class CwN{}
+class CwO{}
+class CwP{}
+class CwQ{}
+class CwR{}
+class CwS{}
+class CwT{}
+class CwU{}
+class CwV{}
+class CwW{}
+class CwX{}
+class CwY{}
+class CwZ{}
+class Cxa{}
+class Cxb{}
+class Cxc{}
+class Cxd{}
+class Cxe{}
+class Cxf{}
+class Cxg{}
+class Cxh{}
+class Cxi{}
+class Cxj{}
+class Cxk{}
+class Cxl{}
+class Cxm{}
+class Cxn{}
+class Cxo{}
+class Cxp{}
+class Cxq{}
+class Cxr{}
+class Cxs{}
+class Cxt{}
+class Cxu{}
+class Cxv{}
+class Cxw{}
+class Cxx{}
+class Cxy{}
+class Cxz{}
+class CxA{}
+class CxB{}
+class CxC{}
+class CxD{}
+class CxE{}
+class CxF{}
+class CxG{}
+class CxH{}
+class CxI{}
+class CxJ{}
+class CxK{}
+class CxL{}
+class CxM{}
+class CxN{}
+class CxO{}
+class CxP{}
+class CxQ{}
+class CxR{}
+class CxS{}
+class CxT{}
+class CxU{}
+class CxV{}
+class CxW{}
+class CxX{}
+class CxY{}
+class CxZ{}
+class Cya{}
+class Cyb{}
+class Cyc{}
+class Cyd{}
+class Cye{}
+class Cyf{}
+class Cyg{}
+class Cyh{}
+class Cyi{}
+class Cyj{}
+class Cyk{}
+class Cyl{}
+class Cym{}
+class Cyn{}
+class Cyo{}
+class Cyp{}
+class Cyq{}
+class Cyr{}
+class Cys{}
+class Cyt{}
+class Cyu{}
+class Cyv{}
+class Cyw{}
+class Cyx{}
+class Cyy{}
+class Cyz{}
+class CyA{}
+class CyB{}
+class CyC{}
+class CyD{}
+class CyE{}
+class CyF{}
+class CyG{}
+class CyH{}
+class CyI{}
+class CyJ{}
+class CyK{}
+class CyL{}
+class CyM{}
+class CyN{}
+class CyO{}
+class CyP{}
+class CyQ{}
+class CyR{}
+class CyS{}
+class CyT{}
+class CyU{}
+class CyV{}
+class CyW{}
+class CyX{}
+class CyY{}
+class CyZ{}
+class Cza{}
+class Czb{}
+class Czc{}
+class Czd{}
+class Cze{}
+class Czf{}
+class Czg{}
+class Czh{}
+class Czi{}
+class Czj{}
+class Czk{}
+class Czl{}
+class Czm{}
+class Czn{}
+class Czo{}
+class Czp{}
+class Czq{}
+class Czr{}
+class Czs{}
+class Czt{}
+class Czu{}
+class Czv{}
+class Czw{}
+class Czx{}
+class Czy{}
+class Czz{}
+class CzA{}
+class CzB{}
+class CzC{}
+class CzD{}
+class CzE{}
+class CzF{}
+class CzG{}
+class CzH{}
+class CzI{}
+class CzJ{}
+class CzK{}
+class CzL{}
+class CzM{}
+class CzN{}
+class CzO{}
+class CzP{}
+class CzQ{}
+class CzR{}
+class CzS{}
+class CzT{}
+class CzU{}
+class CzV{}
+class CzW{}
+class CzX{}
+class CzY{}
+class CzZ{}
+class CAa{}
+class CAb{}
+class CAc{}
+class CAd{}
+class CAe{}
+class CAf{}
+class CAg{}
+class CAh{}
+class CAi{}
+class CAj{}
+class CAk{}
+class CAl{}
+class CAm{}
+class CAn{}
+class CAo{}
+class CAp{}
+class CAq{}
+class CAr{}
+class CAs{}
+class CAt{}
+class CAu{}
+class CAv{}
+class CAw{}
+class CAx{}
+class CAy{}
+class CAz{}
+class CAA{}
+class CAB{}
+class CAC{}
+class CAD{}
+class CAE{}
+class CAF{}
+class CAG{}
+class CAH{}
+class CAI{}
+class CAJ{}
+class CAK{}
+class CAL{}
+class CAM{}
+class CAN{}
+class CAO{}
+class CAP{}
+class CAQ{}
+class CAR{}
+class CAS{}
+class CAT{}
+class CAU{}
+class CAV{}
+class CAW{}
+class CAX{}
+class CAY{}
+class CAZ{}
+class CBa{}
+class CBb{}
+class CBc{}
+class CBd{}
+class CBe{}
+class CBf{}
+class CBg{}
+class CBh{}
+class CBi{}
+class CBj{}
+class CBk{}
+class CBl{}
+class CBm{}
+class CBn{}
+class CBo{}
+class CBp{}
+class CBq{}
+class CBr{}
+class CBs{}
+class CBt{}
+class CBu{}
+class CBv{}
+class CBw{}
+class CBx{}
+class CBy{}
+class CBz{}
+class CBA{}
+class CBB{}
+class CBC{}
+class CBD{}
+class CBE{}
+class CBF{}
+class CBG{}
+class CBH{}
+class CBI{}
+class CBJ{}
+class CBK{}
+class CBL{}
+class CBM{}
+class CBN{}
+class CBO{}
+class CBP{}
+class CBQ{}
+class CBR{}
+class CBS{}
+class CBT{}
+class CBU{}
+class CBV{}
+class CBW{}
+class CBX{}
+class CBY{}
+class CBZ{}
+class CCa{}
+class CCb{}
+class CCc{}
+class CCd{}
+class CCe{}
+class CCf{}
+class CCg{}
+class CCh{}
+class CCi{}
+class CCj{}
+class CCk{}
+class CCl{}
+class CCm{}
+class CCn{}
+class CCo{}
+class CCp{}
+class CCq{}
+class CCr{}
+class CCs{}
+class CCt{}
+class CCu{}
+class CCv{}
+class CCw{}
+class CCx{}
+class CCy{}
+class CCz{}
+class CCA{}
+class CCB{}
+class CCC{}
+class CCD{}
+class CCE{}
+class CCF{}
+class CCG{}
+class CCH{}
+class CCI{}
+class CCJ{}
+class CCK{}
+class CCL{}
+class CCM{}
+class CCN{}
+class CCO{}
+class CCP{}
+class CCQ{}
+class CCR{}
+class CCS{}
+class CCT{}
+class CCU{}
+class CCV{}
+class CCW{}
+class CCX{}
+class CCY{}
+class CCZ{}
+class CDa{}
+class CDb{}
+class CDc{}
+class CDd{}
+class CDe{}
+class CDf{}
+class CDg{}
+class CDh{}
+class CDi{}
+class CDj{}
+class CDk{}
+class CDl{}
+class CDm{}
+class CDn{}
+class CDo{}
+class CDp{}
+class CDq{}
+class CDr{}
+class CDs{}
+class CDt{}
+class CDu{}
+class CDv{}
+class CDw{}
+class CDx{}
+class CDy{}
+class CDz{}
+class CDA{}
+class CDB{}
+class CDC{}
+class CDD{}
+class CDE{}
+class CDF{}
+class CDG{}
+class CDH{}
+class CDI{}
+class CDJ{}
+class CDK{}
+class CDL{}
+class CDM{}
+class CDN{}
+class CDO{}
+class CDP{}
+class CDQ{}
+class CDR{}
+class CDS{}
+class CDT{}
+class CDU{}
+class CDV{}
+class CDW{}
+class CDX{}
+class CDY{}
+class CDZ{}
+class CEa{}
+class CEb{}
+class CEc{}
+class CEd{}
+class CEe{}
+class CEf{}
+class CEg{}
+class CEh{}
+class CEi{}
+class CEj{}
+class CEk{}
+class CEl{}
+class CEm{}
+class CEn{}
+class CEo{}
+class CEp{}
+class CEq{}
+class CEr{}
+class CEs{}
+class CEt{}
+class CEu{}
+class CEv{}
+class CEw{}
+class CEx{}
+class CEy{}
+class CEz{}
+class CEA{}
+class CEB{}
+class CEC{}
+class CED{}
+class CEE{}
+class CEF{}
+class CEG{}
+class CEH{}
+class CEI{}
+class CEJ{}
+class CEK{}
+class CEL{}
+class CEM{}
+class CEN{}
+class CEO{}
+class CEP{}
+class CEQ{}
+class CER{}
+class CES{}
+class CET{}
+class CEU{}
+class CEV{}
+class CEW{}
+class CEX{}
+class CEY{}
+class CEZ{}
+class CFa{}
+class CFb{}
+class CFc{}
+class CFd{}
+class CFe{}
+class CFf{}
+class CFg{}
+class CFh{}
+class CFi{}
+class CFj{}
+class CFk{}
+class CFl{}
+class CFm{}
+class CFn{}
+class CFo{}
+class CFp{}
+class CFq{}
+class CFr{}
+class CFs{}
+class CFt{}
+class CFu{}
+class CFv{}
+class CFw{}
+class CFx{}
+class CFy{}
+class CFz{}
+class CFA{}
+class CFB{}
+class CFC{}
+class CFD{}
+class CFE{}
+class CFF{}
+class CFG{}
+class CFH{}
+class CFI{}
+class CFJ{}
+class CFK{}
+class CFL{}
+class CFM{}
+class CFN{}
+class CFO{}
+class CFP{}
+class CFQ{}
+class CFR{}
+class CFS{}
+class CFT{}
+class CFU{}
+class CFV{}
+class CFW{}
+class CFX{}
+class CFY{}
+class CFZ{}
+class CGa{}
+class CGb{}
+class CGc{}
+class CGd{}
+class CGe{}
+class CGf{}
+class CGg{}
+class CGh{}
+class CGi{}
+class CGj{}
+class CGk{}
+class CGl{}
+class CGm{}
+class CGn{}
+class CGo{}
+class CGp{}
+class CGq{}
+class CGr{}
+class CGs{}
+class CGt{}
+class CGu{}
+class CGv{}
+class CGw{}
+class CGx{}
+class CGy{}
+class CGz{}
+class CGA{}
+class CGB{}
+class CGC{}
+class CGD{}
+class CGE{}
+class CGF{}
+class CGG{}
+class CGH{}
+class CGI{}
+class CGJ{}
+class CGK{}
+class CGL{}
+class CGM{}
+class CGN{}
+class CGO{}
+class CGP{}
+class CGQ{}
+class CGR{}
+class CGS{}
+class CGT{}
+class CGU{}
+class CGV{}
+class CGW{}
+class CGX{}
+class CGY{}
+class CGZ{}
+class CHa{}
+class CHb{}
+class CHc{}
+class CHd{}
+class CHe{}
+class CHf{}
+class CHg{}
+class CHh{}
+class CHi{}
+class CHj{}
+class CHk{}
+class CHl{}
+class CHm{}
+class CHn{}
+class CHo{}
+class CHp{}
+class CHq{}
+class CHr{}
+class CHs{}
+class CHt{}
+class CHu{}
+class CHv{}
+class CHw{}
+class CHx{}
+class CHy{}
+class CHz{}
+class CHA{}
+class CHB{}
+class CHC{}
+class CHD{}
+class CHE{}
+class CHF{}
+class CHG{}
+class CHH{}
+class CHI{}
+class CHJ{}
+class CHK{}
+class CHL{}
+class CHM{}
+class CHN{}
+class CHO{}
+class CHP{}
+class CHQ{}
+class CHR{}
+class CHS{}
+class CHT{}
+class CHU{}
+class CHV{}
+class CHW{}
+class CHX{}
+class CHY{}
+class CHZ{}
+class CIa{}
+class CIb{}
+class CIc{}
+class CId{}
+class CIe{}
+class CIf{}
+class CIg{}
+class CIh{}
+class CIi{}
+class CIj{}
+class CIk{}
+class CIl{}
+class CIm{}
+class CIn{}
+class CIo{}
+class CIp{}
+class CIq{}
+class CIr{}
+class CIs{}
+class CIt{}
+class CIu{}
+class CIv{}
+class CIw{}
+class CIx{}
+class CIy{}
+class CIz{}
+class CIA{}
+class CIB{}
+class CIC{}
+class CID{}
+class CIE{}
+class CIF{}
+class CIG{}
+class CIH{}
+class CII{}
+class CIJ{}
+class CIK{}
+class CIL{}
+class CIM{}
+class CIN{}
+class CIO{}
+class CIP{}
+class CIQ{}
+class CIR{}
+class CIS{}
+class CIT{}
+class CIU{}
+class CIV{}
+class CIW{}
+class CIX{}
+class CIY{}
+class CIZ{}
+class CJa{}
+class CJb{}
+class CJc{}
+class CJd{}
+class CJe{}
+class CJf{}
+class CJg{}
+class CJh{}
+class CJi{}
+class CJj{}
+class CJk{}
+class CJl{}
+class CJm{}
+class CJn{}
+class CJo{}
+class CJp{}
+class CJq{}
+class CJr{}
+class CJs{}
+class CJt{}
+class CJu{}
+class CJv{}
+class CJw{}
+class CJx{}
+class CJy{}
+class CJz{}
+class CJA{}
+class CJB{}
+class CJC{}
+class CJD{}
+class CJE{}
+class CJF{}
+class CJG{}
+class CJH{}
+class CJI{}
+class CJJ{}
+class CJK{}
+class CJL{}
+class CJM{}
+class CJN{}
+class CJO{}
+class CJP{}
+class CJQ{}
+class CJR{}
+class CJS{}
+class CJT{}
+class CJU{}
+class CJV{}
+class CJW{}
+class CJX{}
+class CJY{}
+class CJZ{}
+class CKa{}
+class CKb{}
+class CKc{}
+class CKd{}
+class CKe{}
+class CKf{}
+class CKg{}
+class CKh{}
+class CKi{}
+class CKj{}
+class CKk{}
+class CKl{}
+class CKm{}
+class CKn{}
+class CKo{}
+class CKp{}
+class CKq{}
+class CKr{}
+class CKs{}
+class CKt{}
+class CKu{}
+class CKv{}
+class CKw{}
+class CKx{}
+class CKy{}
+class CKz{}
+class CKA{}
+class CKB{}
+class CKC{}
+class CKD{}
+class CKE{}
+class CKF{}
+class CKG{}
+class CKH{}
+class CKI{}
+class CKJ{}
+class CKK{}
+class CKL{}
+class CKM{}
+class CKN{}
+class CKO{}
+class CKP{}
+class CKQ{}
+class CKR{}
+class CKS{}
+class CKT{}
+class CKU{}
+class CKV{}
+class CKW{}
+class CKX{}
+class CKY{}
+class CKZ{}
+class CLa{}
+class CLb{}
+class CLc{}
+class CLd{}
+class CLe{}
+class CLf{}
+class CLg{}
+class CLh{}
+class CLi{}
+class CLj{}
+class CLk{}
+class CLl{}
+class CLm{}
+class CLn{}
+class CLo{}
+class CLp{}
+class CLq{}
+class CLr{}
+class CLs{}
+class CLt{}
+class CLu{}
+class CLv{}
+class CLw{}
+class CLx{}
+class CLy{}
+class CLz{}
+class CLA{}
+class CLB{}
+class CLC{}
+class CLD{}
+class CLE{}
+class CLF{}
+class CLG{}
+class CLH{}
+class CLI{}
+class CLJ{}
+class CLK{}
+class CLL{}
+class CLM{}
+class CLN{}
+class CLO{}
+class CLP{}
+class CLQ{}
+class CLR{}
+class CLS{}
+class CLT{}
+class CLU{}
+class CLV{}
+class CLW{}
+class CLX{}
+class CLY{}
+class CLZ{}
+class CMa{}
+class CMb{}
+class CMc{}
+class CMd{}
+class CMe{}
+class CMf{}
+class CMg{}
+class CMh{}
+class CMi{}
+class CMj{}
+class CMk{}
+class CMl{}
+class CMm{}
+class CMn{}
+class CMo{}
+class CMp{}
+class CMq{}
+class CMr{}
+class CMs{}
+class CMt{}
+class CMu{}
+class CMv{}
+class CMw{}
+class CMx{}
+class CMy{}
+class CMz{}
+class CMA{}
+class CMB{}
+class CMC{}
+class CMD{}
+class CME{}
+class CMF{}
+class CMG{}
+class CMH{}
+class CMI{}
+class CMJ{}
+class CMK{}
+class CML{}
+class CMM{}
+class CMN{}
+class CMO{}
+class CMP{}
+class CMQ{}
+class CMR{}
+class CMS{}
+class CMT{}
+class CMU{}
+class CMV{}
+class CMW{}
+class CMX{}
+class CMY{}
+class CMZ{}
+class CNa{}
+class CNb{}
+class CNc{}
+class CNd{}
+class CNe{}
+class CNf{}
+class CNg{}
+class CNh{}
+class CNi{}
+class CNj{}
+class CNk{}
+class CNl{}
+class CNm{}
+class CNn{}
+class CNo{}
+class CNp{}
+class CNq{}
+class CNr{}
+class CNs{}
+class CNt{}
+class CNu{}
+class CNv{}
+class CNw{}
+class CNx{}
+class CNy{}
+class CNz{}
+class CNA{}
+class CNB{}
+class CNC{}
+class CND{}
+class CNE{}
+class CNF{}
+class CNG{}
+class CNH{}
+class CNI{}
+class CNJ{}
+class CNK{}
+class CNL{}
+class CNM{}
+class CNN{}
+class CNO{}
+class CNP{}
+class CNQ{}
+class CNR{}
+class CNS{}
+class CNT{}
+class CNU{}
+class CNV{}
+class CNW{}
+class CNX{}
+class CNY{}
+class CNZ{}
+class COa{}
+class COb{}
+class COc{}
+class COd{}
+class COe{}
+class COf{}
+class COg{}
+class COh{}
+class COi{}
+class COj{}
+class COk{}
+class COl{}
+class COm{}
+class COn{}
+class COo{}
+class COp{}
+class COq{}
+class COr{}
+class COs{}
+class COt{}
+class COu{}
+class COv{}
+class COw{}
+class COx{}
+class COy{}
+class COz{}
+class COA{}
+class COB{}
+class COC{}
+class COD{}
+class COE{}
+class COF{}
+class COG{}
+class COH{}
+class COI{}
+class COJ{}
+class COK{}
+class COL{}
+class COM{}
+class CON{}
+class COO{}
+class COP{}
+class COQ{}
+class COR{}
+class COS{}
+class COT{}
+class COU{}
+class COV{}
+class COW{}
+class COX{}
+class COY{}
+class COZ{}
+class CPa{}
+class CPb{}
+class CPc{}
+class CPd{}
+class CPe{}
+class CPf{}
+class CPg{}
+class CPh{}
+class CPi{}
+class CPj{}
+class CPk{}
+class CPl{}
+class CPm{}
+class CPn{}
+class CPo{}
+class CPp{}
+class CPq{}
+class CPr{}
+class CPs{}
+class CPt{}
+class CPu{}
+class CPv{}
+class CPw{}
+class CPx{}
+class CPy{}
+class CPz{}
+class CPA{}
+class CPB{}
+class CPC{}
+class CPD{}
+class CPE{}
+class CPF{}
+class CPG{}
+class CPH{}
+class CPI{}
+class CPJ{}
+class CPK{}
+class CPL{}
+class CPM{}
+class CPN{}
+class CPO{}
+class CPP{}
+class CPQ{}
+class CPR{}
+class CPS{}
+class CPT{}
+class CPU{}
+class CPV{}
+class CPW{}
+class CPX{}
+class CPY{}
+class CPZ{}
+class CQa{}
+class CQb{}
+class CQc{}
+class CQd{}
+class CQe{}
+class CQf{}
+class CQg{}
+class CQh{}
+class CQi{}
+class CQj{}
+class CQk{}
+class CQl{}
+class CQm{}
+class CQn{}
+class CQo{}
+class CQp{}
+class CQq{}
+class CQr{}
+class CQs{}
+class CQt{}
+class CQu{}
+class CQv{}
+class CQw{}
+class CQx{}
+class CQy{}
+class CQz{}
+class CQA{}
+class CQB{}
+class CQC{}
+class CQD{}
+class CQE{}
+class CQF{}
+class CQG{}
+class CQH{}
+class CQI{}
+class CQJ{}
+class CQK{}
+class CQL{}
+class CQM{}
+class CQN{}
+class CQO{}
+class CQP{}
+class CQQ{}
+class CQR{}
+class CQS{}
+class CQT{}
+class CQU{}
+class CQV{}
+class CQW{}
+class CQX{}
+class CQY{}
+class CQZ{}
+class CRa{}
+class CRb{}
+class CRc{}
+class CRd{}
+class CRe{}
+class CRf{}
+class CRg{}
+class CRh{}
+class CRi{}
+class CRj{}
+class CRk{}
+class CRl{}
+class CRm{}
+class CRn{}
+class CRo{}
+class CRp{}
+class CRq{}
+class CRr{}
+class CRs{}
+class CRt{}
+class CRu{}
+class CRv{}
+class CRw{}
+class CRx{}
+class CRy{}
+class CRz{}
+class CRA{}
+class CRB{}
+class CRC{}
+class CRD{}
+class CRE{}
+class CRF{}
+class CRG{}
+class CRH{}
+class CRI{}
+class CRJ{}
+class CRK{}
+class CRL{}
+class CRM{}
+class CRN{}
+class CRO{}
+class CRP{}
+class CRQ{}
+class CRR{}
+class CRS{}
+class CRT{}
+class CRU{}
+class CRV{}
+class CRW{}
+class CRX{}
+class CRY{}
+class CRZ{}
+class CSa{}
+class CSb{}
+class CSc{}
+class CSd{}
+class CSe{}
+class CSf{}
+class CSg{}
+class CSh{}
+class CSi{}
+class CSj{}
+class CSk{}
+class CSl{}
+class CSm{}
+class CSn{}
+class CSo{}
+class CSp{}
+class CSq{}
+class CSr{}
+class CSs{}
+class CSt{}
+class CSu{}
+class CSv{}
+class CSw{}
+class CSx{}
+class CSy{}
+class CSz{}
+class CSA{}
+class CSB{}
+class CSC{}
+class CSD{}
+class CSE{}
+class CSF{}
+class CSG{}
+class CSH{}
+class CSI{}
+class CSJ{}
+class CSK{}
+class CSL{}
+class CSM{}
+class CSN{}
+class CSO{}
+class CSP{}
+class CSQ{}
+class CSR{}
+class CSS{}
+class CST{}
+class CSU{}
+class CSV{}
+class CSW{}
+class CSX{}
+class CSY{}
+class CSZ{}
+class CTa{}
+class CTb{}
+class CTc{}
+class CTd{}
+class CTe{}
+class CTf{}
+class CTg{}
+class CTh{}
+class CTi{}
+class CTj{}
+class CTk{}
+class CTl{}
+class CTm{}
+class CTn{}
+class CTo{}
+class CTp{}
+class CTq{}
+class CTr{}
+class CTs{}
+class CTt{}
+class CTu{}
+class CTv{}
+class CTw{}
+class CTx{}
+class CTy{}
+class CTz{}
+class CTA{}
+class CTB{}
+class CTC{}
+class CTD{}
+class CTE{}
+class CTF{}
+class CTG{}
+class CTH{}
+class CTI{}
+class CTJ{}
+class CTK{}
+class CTL{}
+class CTM{}
+class CTN{}
+class CTO{}
+class CTP{}
+class CTQ{}
+class CTR{}
+class CTS{}
+class CTT{}
+class CTU{}
+class CTV{}
+class CTW{}
+class CTX{}
+class CTY{}
+class CTZ{}
+class CUa{}
+class CUb{}
+class CUc{}
+class CUd{}
+class CUe{}
+class CUf{}
+class CUg{}
+class CUh{}
+class CUi{}
+class CUj{}
+class CUk{}
+class CUl{}
+class CUm{}
+class CUn{}
+class CUo{}
+class CUp{}
+class CUq{}
+class CUr{}
+class CUs{}
+class CUt{}
+class CUu{}
+class CUv{}
+class CUw{}
+class CUx{}
+class CUy{}
+class CUz{}
+class CUA{}
+class CUB{}
+class CUC{}
+class CUD{}
+class CUE{}
+class CUF{}
+class CUG{}
+class CUH{}
+class CUI{}
+class CUJ{}
+class CUK{}
+class CUL{}
+class CUM{}
+class CUN{}
+class CUO{}
+class CUP{}
+class CUQ{}
+class CUR{}
+class CUS{}
+class CUT{}
+class CUU{}
+class CUV{}
+class CUW{}
+class CUX{}
+class CUY{}
+class CUZ{}
+class CVa{}
+class CVb{}
+class CVc{}
+class CVd{}
+class CVe{}
+class CVf{}
+class CVg{}
+class CVh{}
+class CVi{}
+class CVj{}
+class CVk{}
+class CVl{}
+class CVm{}
+class CVn{}
+class CVo{}
+class CVp{}
+class CVq{}
+class CVr{}
+class CVs{}
+class CVt{}
+class CVu{}
+class CVv{}
+class CVw{}
+class CVx{}
+class CVy{}
+class CVz{}
+class CVA{}
+class CVB{}
+class CVC{}
+class CVD{}
+class CVE{}
+class CVF{}
+class CVG{}
+class CVH{}
+class CVI{}
+class CVJ{}
+class CVK{}
+class CVL{}
+class CVM{}
+class CVN{}
+class CVO{}
+class CVP{}
+class CVQ{}
+class CVR{}
+class CVS{}
+class CVT{}
+class CVU{}
+class CVV{}
+class CVW{}
+class CVX{}
+class CVY{}
+class CVZ{}
+class CWa{}
+class CWb{}
+class CWc{}
+class CWd{}
+class CWe{}
+class CWf{}
+class CWg{}
+class CWh{}
+class CWi{}
+class CWj{}
+class CWk{}
+class CWl{}
+class CWm{}
+class CWn{}
+class CWo{}
+class CWp{}
+class CWq{}
+class CWr{}
+class CWs{}
+class CWt{}
+class CWu{}
+class CWv{}
+class CWw{}
+class CWx{}
+class CWy{}
+class CWz{}
+class CWA{}
+class CWB{}
+class CWC{}
+class CWD{}
+class CWE{}
+class CWF{}
+class CWG{}
+class CWH{}
+class CWI{}
+class CWJ{}
+class CWK{}
+class CWL{}
+class CWM{}
+class CWN{}
+class CWO{}
+class CWP{}
+class CWQ{}
+class CWR{}
+class CWS{}
+class CWT{}
+class CWU{}
+class CWV{}
+class CWW{}
+class CWX{}
+class CWY{}
+class CWZ{}
+class CXa{}
+class CXb{}
+class CXc{}
+class CXd{}
+class CXe{}
+class CXf{}
+class CXg{}
+class CXh{}
+class CXi{}
+class CXj{}
+class CXk{}
+class CXl{}
+class CXm{}
+class CXn{}
+class CXo{}
+class CXp{}
+class CXq{}
+class CXr{}
+class CXs{}
+class CXt{}
+class CXu{}
+class CXv{}
+class CXw{}
+class CXx{}
+class CXy{}
+class CXz{}
+class CXA{}
+class CXB{}
+class CXC{}
+class CXD{}
+class CXE{}
+class CXF{}
+class CXG{}
+class CXH{}
+class CXI{}
+class CXJ{}
+class CXK{}
+class CXL{}
+class CXM{}
+class CXN{}
+class CXO{}
+class CXP{}
+class CXQ{}
+class CXR{}
+class CXS{}
+class CXT{}
+class CXU{}
+class CXV{}
+class CXW{}
+class CXX{}
+class CXY{}
+class CXZ{}
+class CYa{}
+class CYb{}
+class CYc{}
+class CYd{}
+class CYe{}
+class CYf{}
+class CYg{}
+class CYh{}
+class CYi{}
+class CYj{}
+class CYk{}
+class CYl{}
+class CYm{}
+class CYn{}
+class CYo{}
+class CYp{}
+class CYq{}
+class CYr{}
+class CYs{}
+class CYt{}
+class CYu{}
+class CYv{}
+class CYw{}
+class CYx{}
+class CYy{}
+class CYz{}
+class CYA{}
+class CYB{}
+class CYC{}
+class CYD{}
+class CYE{}
+class CYF{}
+class CYG{}
+class CYH{}
+class CYI{}
+class CYJ{}
+class CYK{}
+class CYL{}
+class CYM{}
+class CYN{}
+class CYO{}
+class CYP{}
+class CYQ{}
+class CYR{}
+class CYS{}
+class CYT{}
+class CYU{}
+class CYV{}
+class CYW{}
+class CYX{}
+class CYY{}
+class CYZ{}
+class CZa{}
+class CZb{}
+class CZc{}
+class CZd{}
+class CZe{}
+class CZf{}
+class CZg{}
+class CZh{}
+class CZi{}
+class CZj{}
+class CZk{}
+class CZl{}
+class CZm{}
+class CZn{}
+class CZo{}
+class CZp{}
+class CZq{}
+class CZr{}
+class CZs{}
+class CZt{}
+class CZu{}
+class CZv{}
+class CZw{}
+class CZx{}
+class CZy{}
+class CZz{}
+class CZA{}
+class CZB{}
+class CZC{}
+class CZD{}
+class CZE{}
+class CZF{}
+class CZG{}
+class CZH{}
+class CZI{}
+class CZJ{}
+class CZK{}
+class CZL{}
+class CZM{}
+class CZN{}
+class CZO{}
+class CZP{}
+class CZQ{}
+class CZR{}
+class CZS{}
+class CZT{}
+class CZU{}
+class CZV{}
+class CZW{}
+class CZX{}
+class CZY{}
+class CZZ{}
+
diff --git a/tests/language/conditional_access_helper.dart b/tests/language/conditional_access_helper.dart
index 108857a..c847232 100644
--- a/tests/language/conditional_access_helper.dart
+++ b/tests/language/conditional_access_helper.dart
@@ -14,6 +14,26 @@
 void topLevelFunction() {}
 
 class C {
-  static var staticField;
-  static void staticMethod() {}
+  static int staticInt;
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
 }
+
+C nullC() => null;
+
+class D {
+  static E staticE;
+}
+
+class E {
+  G operator+(int i) => new I();
+  G operator-(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
diff --git a/tests/language/conditional_method_invocation_test.dart b/tests/language/conditional_method_invocation_test.dart
index cfe0545..0dd219d 100644
--- a/tests/language/conditional_method_invocation_test.dart
+++ b/tests/language/conditional_method_invocation_test.dart
@@ -18,7 +18,8 @@
 class C extends B {
   f(callback()) => callback();
   int g(int callback()) => callback();
-  static void staticMethod() {}
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
 }
 
 C nullC() => null;
@@ -32,12 +33,20 @@
   Expect.equals(null, nullC()?.f(bad())); /// 01: ok
   Expect.equals(1, new C()?.f(() => 1)); /// 02: ok
 
+  // C?.m(...) is equivalent to C.m(...).
+  Expect.equals(1, C?.staticF(() => 1)); /// 14: ok
+  Expect.equals(1, h.C?.staticF(() => 1)); /// 15: ok
+
   // The static type of o?.m(...) is the same as the static type of
   // o.m(...).
   { int i = nullC()?.g(bad()); Expect.equals(null, i); } /// 03: ok
   { int i = new C()?.g(() => 1); Expect.equals(1, i); } /// 04: ok
   { String s = nullC()?.g(bad()); Expect.equals(null, s); } /// 05: static type warning
   { String s = new C()?.g(() => null); Expect.equals(null, s); } /// 06: static type warning
+  { int i = C?.staticG(() => 1); Expect.equals(1, i); } /// 16: ok
+  { int i = h.C?.staticG(() => 1); Expect.equals(1, i); } /// 17: ok
+  { String s = C?.staticG(() => null); Expect.equals(null, s); } /// 18: static type warning
+  { String s = h.C?.staticG(() => null); Expect.equals(null, s); } /// 19: static type warning
 
   // Let T be the static type of o and let y be a fresh variable of type T.
   // Exactly the same static warnings that would be caused by y.m(...) are also
@@ -45,15 +54,11 @@
   { B b = new C(); Expect.equals(1, b?.f(() => 1)); } /// 07: static type warning
   { int i = 1; Expect.equals(null, nullC()?.f(i)); } /// 08: static type warning
 
-  // Consequently, '?.' cannot be used to invoke static methods of classes.
-  Expect.throws(() => C?.staticMethod(), noMethod); /// 09: static type warning
-  Expect.throws(() => h.C?.staticMethod(), noMethod); /// 10: static type warning
-
-  // Nor can it be used to access toplevel functions in libraries imported via
+  // '?.' can't be used to access toplevel functions in libraries imported via
   // prefix.
   h?.topLevelFunction(); /// 11: compile-time error
 
-  // However, '?.' can be used to access the toString method on the class Type.
-  Expect.equals(C?.toString(), (C).toString()); /// 12: ok
-  Expect.equals(h.C?.toString(), (h.C).toString()); /// 13: ok
+  // Nor can it be used to access the toString method on the class Type.
+  Expect.throws(() => C?.toString(), noMethod); /// 12: static type warning
+  Expect.throws(() => h.C?.toString(), noMethod); /// 13: static type warning
 }
diff --git a/tests/language/conditional_property_access_test.dart b/tests/language/conditional_property_access_test.dart
index ca44f2d..b5dfa85 100644
--- a/tests/language/conditional_property_access_test.dart
+++ b/tests/language/conditional_property_access_test.dart
@@ -15,7 +15,7 @@
 class C extends B {
   int v;
   C(this.v);
-  static var staticField;
+  static int staticInt;
 }
 
 C nullC() => null;
@@ -29,9 +29,17 @@
   Expect.equals(null, nullC()?.v); /// 01: ok
   Expect.equals(1, new C(1)?.v); /// 02: ok
 
+  // C?.id is equivalent to C.id.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt); } /// 12: ok
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt); } /// 13: ok
+
   // The static type of e1?.d is the static type of e1.id.
   { int i = new C(1)?.v; Expect.equals(1, i); } /// 03: ok
   { String s = new C(null)?.v; Expect.equals(null, s); } /// 04: static type warning
+  { C.staticInt = 1; int i = C?.staticInt; Expect.equals(1, i); } /// 14: ok
+  { h.C.staticInt = 1; int i = h.C?.staticInt; Expect.equals(1, i); } /// 15: ok
+  { C.staticInt = null; String s = C?.staticInt; Expect.equals(null, s); } /// 16: static type warning
+  { h.C.staticInt = null; String s = h.C?.staticInt; Expect.equals(null, s); } /// 17: static type warning
 
   // Let T be the static type of e1 and let y be a fresh variable of type T.
   // Exactly the same static warnings that would be caused by y.id are also
@@ -39,15 +47,11 @@
   Expect.equals(null, nullC()?.bad); /// 05: static type warning
   { B b = new C(1); Expect.equals(1, b?.v); } /// 06: static type warning
 
-  // Consequently, '?.' cannot be used to access static properties of classes.
-  Expect.throws(() => C?.staticField, noMethod); /// 07: static type warning
-  Expect.throws(() => h.C?.staticField, noMethod); /// 08: static type warning
-
-  // Nor can it be used to access toplevel properties in libraries imported via
+  // '?.' cannot be used to access toplevel properties in libraries imported via
   // prefix.
   var x = h?.topLevelVar; /// 09: compile-time error
 
-  // However, '?.' can be used to access the hashCode getter on the class Type.
-  Expect.equals(C?.hashCode, (C).hashCode); /// 10: ok
-  Expect.equals(h.C?.hashCode, (h.C).hashCode); /// 11: ok
+  // Nor can it be used to access the hashCode getter on the class Type.
+  Expect.throws(() => C?.hashCode, noMethod); /// 10: static type warning
+  Expect.throws(() => h.C?.hashCode, noMethod); /// 11: static type warning
 }
diff --git a/tests/language/conditional_property_assignment_test.dart b/tests/language/conditional_property_assignment_test.dart
index 87e2bd0..1207198 100644
--- a/tests/language/conditional_property_assignment_test.dart
+++ b/tests/language/conditional_property_assignment_test.dart
@@ -19,12 +19,13 @@
 class C extends B {
   int v;
   C(this.v);
-  static var staticField;
+  static int staticInt;
 }
 
 class D {
   E v;
   D(this.v);
+  static E staticE;
 }
 
 class E {
@@ -50,9 +51,17 @@
   Expect.equals(null, nullC()?.v = bad()); /// 01: ok
   { C c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c.v); } /// 02: ok
 
+  // C?.v = e2 is equivalent to C.v = e2.
+  { C.staticInt = 1; Expect.equals(2, C?.staticInt = 2); Expect.equals(2, C.staticInt); } /// 23: ok
+  { h.C.staticInt = 1; Expect.equals(2, h.C?.staticInt = 2); Expect.equals(2, h.C.staticInt); } /// 24: ok
+
   // The static type of e1?.v = e2 is the static type of e2.
   { D d = new D(new E()); G g = new G(); F f = (d?.v = g); Expect.identical(f, g); } /// 03: ok
   { D d = new D(new E()); E e = new G(); F f = (d?.v = e); Expect.identical(f, e); } /// 04: static type warning
+  { D.staticE = new E(); G g = new G(); F f = (D?.staticE = g); Expect.identical(f, g); } /// 25: ok
+  { h.D.staticE = new h.E(); h.G g = new h.G(); h.F f = (h.D?.staticE = g); Expect.identical(f, g); } /// 26: ok
+  { D.staticE = new E(); E e = new G(); F f = (D?.staticE = e); Expect.identical(f, e); } /// 27: static type warning
+  { h.D.staticE = new h.E(); h.E e = new h.G(); h.F f = (h.D?.staticE = e); Expect.identical(f, e); } /// 28: static type warning
 
   // Exactly the same static warnings that would be caused by e1.v = e2 are
   // also generated in the case of e1?.v = e2.
@@ -63,8 +72,13 @@
   Expect.equals(null, nullC()?.v += bad()); /// 07: ok
   { C c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c.v); } /// 08: ok
 
+  // C?.v op= e2 is equivalent to C.v op= e2.
+  { C.staticInt = 1; Expect.equals(3, C?.staticInt += 2); Expect.equals(3, C?.staticInt); } /// 29: ok
+
   // The static type of e1?.v op= e2 is the static type of e1.v op e2.
   { D d = new D(new E()); F f = (d?.v += 1); Expect.identical(d.v, f); } /// 09: ok
+  { D.staticE = new E(); F f = (D?.staticE += 1); Expect.identical(D.staticE, f); } /// 30: ok
+  { h.D.staticE = new h.E(); h.F f = (h.D?.staticE += 1); Expect.identical(h.D.staticE, f); } /// 31: ok
 
   // Let T be the static type of e1 and let y be a fresh variable of type T.
   // Exactly the same static warnings that would be caused by y.v op e2 are
@@ -73,17 +87,12 @@
   { B b = new C(1); Expect.equals(3, b?.v += 2); Expect.equals(3, (b as C).v); } /// 11: static type warning
   { D d = new D(new E()); F f = (d?.v += nullC()); Expect.identical(d.v, f); } /// 12: static type warning
   { D d = new D(new E()); H h = (d?.v += 1); Expect.identical(d.v, h); } /// 13: static type warning
+  { D.staticE = new E(); F f = (D?.staticE += nullC()); Expect.identical(D.staticE, f); } /// 32: static type warning
+  { h.D.staticE = new h.E(); h.F f = (h.D?.staticE += h.nullC()); Expect.identical(h.D.staticE, f); } /// 33: static type warning
+  { D.staticE = new E(); H h = (D?.staticE += 1); Expect.identical(D.staticE, h); } /// 34: static type warning
+  { h.D.staticE = new h.E(); h.H hh = (h.D?.staticE += 1); Expect.identical(h.D.staticE, hh); } /// 35: static type warning
 
-  // Consequently, '?.' cannot be used to assign to static properties of
-  // classes.
-  Expect.throws(() => C?.staticField = null, noMethod); /// 14: static type warning
-  Expect.throws(() => C?.staticField += null, noMethod); /// 15: static type warning
-  Expect.throws(() => C?.staticField ??= null, noMethod); /// 16: static type warning
-  Expect.throws(() => h.C?.staticField = null, noMethod); /// 17: static type warning
-  Expect.throws(() => h.C?.staticField += null, noMethod); /// 18: static type warning
-  Expect.throws(() => h.C?.staticField ??= null, noMethod); /// 19: static type warning
-
-  // Nor can it be used to assign to toplevel properties in libraries imported
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
   // via prefix.
   h?.topLevelVar = null; /// 20: compile-time error
   h?.topLevelVar += null; /// 21: compile-time error
diff --git a/tests/language/conditional_property_increment_decrement_test.dart b/tests/language/conditional_property_increment_decrement_test.dart
index 6858a69..81a27c6 100644
--- a/tests/language/conditional_property_increment_decrement_test.dart
+++ b/tests/language/conditional_property_increment_decrement_test.dart
@@ -6,16 +6,18 @@
 // preincrement expression (or a postdecrement or predecrement expression).
 
 import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
 
 class C {
   int v;
   C(this.v);
-  static var staticField;
+  static int staticInt;
 }
 
 class D {
   E v;
   D(this.v);
+  static E staticE;
 }
 
 class E {
@@ -42,31 +44,63 @@
   Expect.equals(null, nullC()?.v++); /// 01: ok
   { C c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c.v); } /// 02: ok
 
+  // C?.v++ is equivalent to C.v++.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt++); Expect.equals(2, C.staticInt); } /// 17: ok
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt++); Expect.equals(2, h.C.staticInt); } /// 18: ok
+
   // The static type of e1?.v++ is the same as the static type of e1.v.
   { E e1 = new E(); D d = new D(e1); E e2 = d?.v++; Expect.identical(e1, e2); } /// 03: ok
   { G g = new G(); D d = new D(g); F f = d?.v++; Expect.identical(f, g); } /// 04: static type warning
+  { E e1 = new E(); D.staticE = e1; E e2 = D?.staticE++; Expect.identical(e1, e2); } /// 19: ok
+  { h.E e1 = new h.E(); h.D.staticE = e1; h.E e2 = h.D?.staticE++; Expect.identical(e1, e2); } /// 20: ok
+  { G g = new G(); D.staticE = g; F f = D?.staticE++; Expect.identical(f, g); } /// 21: static type warning
+  { h.G g = new h.G(); h.D.staticE = g; h.F f = h.D?.staticE++; Expect.identical(f, g); } /// 22: static type warning
 
   // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
   Expect.equals(null, nullC()?.v--); /// 05: ok
   { C c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c.v); } /// 06: ok
 
+  // C?.v-- is equivalent to C.v--.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt--); Expect.equals(0, C.staticInt); } /// 23: ok
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt--); Expect.equals(0, h.C.staticInt); } /// 24: ok
+
   // The static type of e1?.v-- is the same as the static type of e1.v.
   { E e1 = new E(); D d = new D(e1); E e2 = d?.v--; Expect.identical(e1, e2); } /// 07: ok
   { G g = new G(); D d = new D(g); F f = d?.v--; Expect.identical(f, g); } /// 08: static type warning
+  { E e1 = new E(); D.staticE = e1; E e2 = D?.staticE--; Expect.identical(e1, e2); } /// 25: ok
+  { h.E e1 = new h.E(); h.D.staticE = e1; h.E e2 = h.D?.staticE--; Expect.identical(e1, e2); } /// 26: ok
+  { G g = new G(); D.staticE = g; F f = D?.staticE--; Expect.identical(f, g); } /// 27: static type warning
+  { h.G g = new h.G(); h.D.staticE = g; h.F f = h.D?.staticE--; Expect.identical(f, g); } /// 28: static type warning
 
   // ++e1?.v is equivalent to e1?.v += 1.
   Expect.equals(null, ++nullC()?.v); /// 09: ok
   { C c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c.v); } /// 10: ok
 
+  // ++C?.v is equivalent to C?.v += 1.
+  { C.staticInt = 1; Expect.equals(2, ++C?.staticInt); Expect.equals(2, C.staticInt); } /// 29: ok
+  { h.C.staticInt = 1; Expect.equals(2, ++h.C?.staticInt); Expect.equals(2, h.C.staticInt); } /// 30: ok
+
   // The static type of ++e1?.v is the same as the static type of e1.v + 1.
   { D d = new D(new E()); F f = ++d?.v; Expect.identical(d.v, f); } /// 11: ok
   { D d = new D(new E()); H h = ++d?.v; Expect.identical(d.v, h); } /// 12: static type warning
+  { D.staticE = new E(); F f = ++D?.staticE; Expect.identical(D.staticE, f); } /// 31: ok
+  { h.D.staticE = new h.E(); h.F f = ++h.D?.staticE; Expect.identical(h.D.staticE, f); } /// 32: ok
+  { D.staticE = new E(); H h = ++D?.staticE; Expect.identical(D.staticE, h); } /// 33: static type warning
+  { h.D.staticE = new h.E(); h.H hh = ++h.D?.staticE; Expect.identical(h.D.staticE, hh); } /// 34: static type warning
 
-  // --e1?.v is equivalent to e1?.v += 1.
+  // --e1?.v is equivalent to e1?.v -= 1.
   Expect.equals(null, --nullC()?.v); /// 13: ok
   { C c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c.v); } /// 14: ok
 
+  // --C?.v is equivalent to C?.v -= 1.
+  { C.staticInt = 1; Expect.equals(0, --C?.staticInt); Expect.equals(0, C.staticInt); } /// 35: ok
+  { h.C.staticInt = 1; Expect.equals(0, --h.C?.staticInt); Expect.equals(0, h.C.staticInt); } /// 36: ok
+
   // The static type of --e1?.v is the same as the static type of e1.v - 1.
   { D d = new D(new E()); F f = --d?.v; Expect.identical(d.v, f); } /// 15: ok
   { D d = new D(new E()); H h = --d?.v; Expect.identical(d.v, h); } /// 16: static type warning
+  { D.staticE = new E(); F f = --D?.staticE; Expect.identical(D.staticE, f); } /// 37: ok
+  { h.D.staticE = new h.E(); h.F f = --h.D?.staticE; Expect.identical(h.D.staticE, f); } /// 38: ok
+  { D.staticE = new E(); H h = --D?.staticE; Expect.identical(D.staticE, h); } /// 39: static type warning
+  { h.D.staticE = new h.E(); h.H hh = --h.D?.staticE; Expect.identical(h.D.staticE, hh); } /// 40: static type warning
 }
diff --git a/tests/language/const_syntax_test.dart b/tests/language/const_syntax_test.dart
index 668bb9f..59fb362 100644
--- a/tests/language/const_syntax_test.dart
+++ b/tests/language/const_syntax_test.dart
@@ -32,6 +32,13 @@
 
   Expect.equals("Hello 42", B2);
   Expect.equals("42Hello", B3); /// 10: compile-time error
+
+  const cf1 = identical(const Point(1, 2), const Point(1, 2));
+
+  const cf2 = identical(const Point(1, 2), new Point(1, 2));  /// 11: compile-time error
+
+  var f4 = B4;   /// 12: compile-time error
+  var f5 = B5;
 }
 
 const F0 = 42;
@@ -75,3 +82,8 @@
 const B1 = "Hello";
 const B2 = "$B1 $B0";
 const B3 = B0 + B1; /// 10: continued
+
+// Check identical.
+
+const B4 = identical(1, new Point(1,2));  /// 12: compile-time error
+const B5 = identical(1, const Point(1,2));
diff --git a/tests/language/cyclic_default_values_test.dart b/tests/language/cyclic_default_values_test.dart
new file mode 100644
index 0000000..9d7f664
--- /dev/null
+++ b/tests/language/cyclic_default_values_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+bar([x = foo]) => x((_) => "bar");
+foo([y = bar]) => y((_) => "foo");
+
+foo2({f: bar2}) => f(f: ({f}) => "foo2");
+bar2({f: foo2}) => f(f: ({f}) => "bar2");
+
+main() {
+  var f = bar;
+  Expect.equals("bar", Function.apply(f, []));
+  Expect.equals("main", Function.apply(f, [(_) => "main"]));
+
+  f = bar2;
+  Expect.equals("bar2", Function.apply(f, []));
+  Expect.equals("main2", Function.apply(f, [], {#f: ({f}) => "main2"}));
+}
diff --git a/tests/language/deferred_type_dependency_lib1.dart b/tests/language/deferred_type_dependency_lib1.dart
new file mode 100644
index 0000000..b9bac0d
--- /dev/null
+++ b/tests/language/deferred_type_dependency_lib1.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2015, the Dart Team. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+library lib1;
+
+import "deferred_type_dependency_lib3.dart";
+
+bool fooIs(x) {
+  return x is A;
+}
+
+bool fooAs(x) {
+  try {
+    return (x as A).p;
+  } on CastError catch (e) {
+    return false;
+  }
+}
+
+bool fooAnnotation(x) {
+  try {
+    A y = x;
+    return y is! String;
+  } on TypeError catch (e) {
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/tests/language/deferred_type_dependency_lib2.dart b/tests/language/deferred_type_dependency_lib2.dart
new file mode 100644
index 0000000..e6954e5
--- /dev/null
+++ b/tests/language/deferred_type_dependency_lib2.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2015, the Dart Team. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+library lib2;
+
+import "deferred_type_dependency_lib3.dart";
+
+getInstance() {
+  return new A();
+}
\ No newline at end of file
diff --git a/tests/language/deferred_type_dependency_lib3.dart b/tests/language/deferred_type_dependency_lib3.dart
new file mode 100644
index 0000000..9a23fc9
--- /dev/null
+++ b/tests/language/deferred_type_dependency_lib3.dart
@@ -0,0 +1,10 @@
+// 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 lib3;
+
+class A {
+  var p = true;
+}
+
diff --git a/tests/language/deferred_type_dependency_test.dart b/tests/language/deferred_type_dependency_test.dart
new file mode 100644
index 0000000..766834e
--- /dev/null
+++ b/tests/language/deferred_type_dependency_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2015, the Dart Team. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+/// Checks that lib1.fooX's dependencies on [A] via is-checks, as-expressions
+/// and type-annotations(in checked-mode) is correctly tracked.
+
+import "deferred_type_dependency_lib1.dart" deferred as lib1;
+import "deferred_type_dependency_lib2.dart" deferred as lib2;
+import "package:expect/expect.dart";
+
+main() async {
+  await lib1.loadLibrary();
+  // Split the cases into a multi-test to test each feature separately.
+  Expect.isFalse(
+      lib1.fooIs /// is: ok
+      lib1.fooAs /// as: ok
+      lib1.fooAnnotation /// type_annotation: ok
+      ("string")
+      is! String /// none: ok
+  );
+  await lib2.loadLibrary();
+  Expect.isTrue(
+      lib1.fooIs /// is: ok
+      lib1.fooAs /// as: ok
+      lib1.fooAnnotation /// type_annotation: ok
+      (lib2.getInstance())
+      is! String /// none: ok
+  );
+}
\ No newline at end of file
diff --git a/tests/language/if_null_assignment_behavior_test.dart b/tests/language/if_null_assignment_behavior_test.dart
index bf01dbe..765be96 100644
--- a/tests/language/if_null_assignment_behavior_test.dart
+++ b/tests/language/if_null_assignment_behavior_test.dart
@@ -201,4 +201,14 @@
   check(1, () => x?.v ??= bad(), ['x', 'x.v']);     /// 27: continued
   xGetValue = new C('x'); yGetValue = 1;                 /// 28: ok
   check(1, () => x?.v ??= y, ['x', 'x.v', 'y', 'x.v=1']); /// 28: continued
+
+  // C?.v ??= e2 is equivalent to C.v ??= e2.
+  C.xGetValue = 1;                         /// 29: ok
+  check(1, () => C?.x ??= bad(), ['C.x']); /// 29: continued
+  h.C.xgetValue = 1;                           /// 30: ok
+  check(1, () => h.c?.x ??= bad(), ['h.C.x']); /// 30: continued
+  yGetValue = 1;                                     /// 31: ok
+  check(1, () => C?.x ??= y, ['C.x', 'y', 'C.x=1']); /// 31: continued
+  yGetValue = 1;                                           /// 32: ok
+  check(1, () => h.C?.x ??= y, ['h.C.x', 'y', 'h.C.x=1']); /// 32: continued
 }
diff --git a/tests/language/indirect_const_null_test.dart b/tests/language/indirect_const_null_test.dart
new file mode 100644
index 0000000..5161614
--- /dev/null
+++ b/tests/language/indirect_const_null_test.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  const NULL = 1 == 1 ? null : false;
+  Expect.isNull(NULL);
+}
diff --git a/tests/language/issue21079_test.dart b/tests/language/issue21079_test.dart
new file mode 100644
index 0000000..e41c46e
--- /dev/null
+++ b/tests/language/issue21079_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Regression test case for http://dartbug.com/21079
+import 'dart:mirrors';
+import 'dart:isolate';
+import "package:expect/expect.dart";
+
+void main() {
+  Expect.isTrue(reflectClass(MyException).superclass.reflectedType == IsolateSpawnException);
+
+  Expect.isTrue(reflectClass(IsolateSpawnException).reflectedType == IsolateSpawnException);
+}
+
+class MyException extends IsolateSpawnException {
+  MyException() : super("Test") {}
+}
+
+
diff --git a/tests/language/issue23244_test.dart b/tests/language/issue23244_test.dart
new file mode 100644
index 0000000..b155769
--- /dev/null
+++ b/tests/language/issue23244_test.dart
@@ -0,0 +1,64 @@
+// 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.
+
+// Regression test case for http://dartbug.com/23244
+import 'dart:async';
+import 'dart:isolate';
+
+enum Fisk {
+  torsk,
+}
+
+isolate1(SendPort port) {
+  port.send(Fisk.torsk);
+}
+
+isolate2(SendPort port) {
+  port.send([Fisk.torsk]);
+}
+
+isolate3(SendPort port) {
+  var x = new Map<int, Fisk>();
+  x[0] = Fisk.torsk;
+  x[1] = Fisk.torsk;
+  port.send(x);
+}
+
+main() async {
+  var port = new ReceivePort();
+  await Isolate.spawn(isolate1, port.sendPort);
+  Completer completer1 = new Completer();
+  port.listen((message) {
+    print("Received $message");
+    port.close();
+    expectTorsk(message);
+    completer1.complete();
+  });
+  await completer1.future;
+  Completer completer2 = new Completer();
+  port = new ReceivePort();
+  await Isolate.spawn(isolate2, port.sendPort);
+  port.listen((message) {
+    print("Received $message");
+    port.close();
+    expectTorsk(message[0]);
+    completer2.complete();
+  });
+  await completer2.future;
+  port = new ReceivePort();
+  await Isolate.spawn(isolate3, port.sendPort);
+  port.listen((message) {
+    print("Received $message");
+    port.close();
+    expectTorsk(message[0]);
+    expectTorsk(message[1]);
+  });
+}
+
+expectTorsk(Fisk fisk) {
+  if (fisk != Fisk.torsk) {
+    throw "$fisk isn't a ${Fisk.torsk}";
+  }
+}
+
diff --git a/tests/language/issue_23914_test.dart b/tests/language/issue_23914_test.dart
new file mode 100644
index 0000000..072f912
--- /dev/null
+++ b/tests/language/issue_23914_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+main() {
+  var a = new List.unmodifiable(new LinkedList());
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 44d45bf..2f58a23 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -7,6 +7,7 @@
 
 [ $compiler == none ]
 built_in_identifier_prefix_test: Fail # Issue 6970
+tearoff_constructor_basic_test: Skip # Crashes in checked mode -- hausner investigating
 
 # These bugs refer currently ongoing language discussions.
 constructor_initializer_test/none: Fail # Issue 12633
@@ -17,14 +18,9 @@
 # Regular bugs which should be fixed.
 duplicate_export_negative_test: Fail # Issue 6134
 
-[ $compiler == none ]
-
 deferred_redirecting_factory_test: Fail # Issue 23408
 redirecting_constructor_initializer_test: RuntimeError # Issue 23488
 
-[ $compiler == none && $runtime != dartium && $runtime != drt ]
-
-[ $compiler == none ]
 # Non-contractive types are not supported in the vm.
 cyclic_type_test/02: Fail, OK
 cyclic_type_test/04: Fail, OK
@@ -47,6 +43,61 @@
 [ $compiler == none ]
 dynamic_prefix_core_test/01: RuntimeError # Issue 12478
 multiline_strings_test: Fail # Issue 23020
+conditional_method_invocation_test/12: Fail # Issue 23794
+conditional_method_invocation_test/13: Fail # Issue 23794
+conditional_method_invocation_test/14: Fail # Issue 23794
+conditional_method_invocation_test/15: Fail # Issue 23794
+conditional_method_invocation_test/16: Fail # Issue 23794
+conditional_method_invocation_test/17: Fail # Issue 23794
+conditional_method_invocation_test/18: Fail # Issue 23794
+conditional_method_invocation_test/19: Fail # Issue 23794
+conditional_property_access_test/10: Fail # Issue 23794
+conditional_property_access_test/11: Fail # Issue 23794
+conditional_property_access_test/12: Fail # Issue 23794
+conditional_property_access_test/13: Fail # Issue 23794
+conditional_property_access_test/14: Fail # Issue 23794
+conditional_property_access_test/15: Fail # Issue 23794
+conditional_property_access_test/16: Fail # Issue 23794
+conditional_property_access_test/17: Fail # Issue 23794
+conditional_property_assignment_test/23: Fail # Issue 23794
+conditional_property_assignment_test/24: Fail # Issue 23794
+conditional_property_assignment_test/25: Fail # Issue 23794
+conditional_property_assignment_test/26: Fail # Issue 23794
+conditional_property_assignment_test/27: Fail # Issue 23794
+conditional_property_assignment_test/28: Fail # Issue 23794
+conditional_property_assignment_test/29: Fail # Issue 23794
+conditional_property_assignment_test/30: Fail # Issue 23794
+conditional_property_assignment_test/31: Fail # Issue 23794
+conditional_property_assignment_test/32: Fail # Issue 23794
+conditional_property_assignment_test/33: Fail # Issue 23794
+conditional_property_assignment_test/34: Fail # Issue 23794
+conditional_property_assignment_test/35: Fail # Issue 23794
+conditional_property_increment_decrement_test/17: Fail # Issue 23794
+conditional_property_increment_decrement_test/18: Fail # Issue 23794
+conditional_property_increment_decrement_test/19: Fail # Issue 23794
+conditional_property_increment_decrement_test/20: Fail # Issue 23794
+conditional_property_increment_decrement_test/21: Fail # Issue 23794
+conditional_property_increment_decrement_test/22: Fail # Issue 23794
+conditional_property_increment_decrement_test/23: Fail # Issue 23794
+conditional_property_increment_decrement_test/24: Fail # Issue 23794
+conditional_property_increment_decrement_test/25: Fail # Issue 23794
+conditional_property_increment_decrement_test/26: Fail # Issue 23794
+conditional_property_increment_decrement_test/27: Fail # Issue 23794
+conditional_property_increment_decrement_test/28: Fail # Issue 23794
+conditional_property_increment_decrement_test/29: Fail # Issue 23794
+conditional_property_increment_decrement_test/30: Fail # Issue 23794
+conditional_property_increment_decrement_test/31: Fail # Issue 23794
+conditional_property_increment_decrement_test/32: Fail # Issue 23794
+conditional_property_increment_decrement_test/33: Fail # Issue 23794
+conditional_property_increment_decrement_test/34: Fail # Issue 23794
+conditional_property_increment_decrement_test/35: Fail # Issue 23794
+conditional_property_increment_decrement_test/36: Fail # Issue 23794
+conditional_property_increment_decrement_test/37: Fail # Issue 23794
+conditional_property_increment_decrement_test/38: Fail # Issue 23794
+conditional_property_increment_decrement_test/39: Fail # Issue 23794
+conditional_property_increment_decrement_test/40: Fail # Issue 23794
+if_null_assignment_behavior_test/31: Fail # Issue 23794
+if_null_assignment_behavior_test/32: Fail # Issue 23794
 
 [ $compiler == none && ($runtime == vm || $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 dynamic_prefix_core_test/none: Fail # Issue 12478
@@ -97,6 +148,7 @@
 [ $compiler == none && $runtime == vm && ( $arch == simarm || $arch == arm || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
 vm/load_to_load_unaligned_forwarding_vm_test: Pass, Crash # Unaligned offset. Issue 22151
 
-[ $compiler == none && $runtime == dartium ]
+[ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
 mixin_super_test: Fail # Can't pass VMOptions to dartium.
 mixin_super_bound2_test: Fail # Can't pass VMOptions to dartium.
+issue23244_test: Fail # Can't run spawnFunction on dartium.
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index b86fe4b..bb3cf05 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -17,6 +17,8 @@
 getter_setter_in_lib_test: Fail # issue 23286
 
 issue13179_test: CompileTimeError # Issue 13179
+tearoff_basic_test: Skip # Tear-off not supported
+tearoff_constructor_basic_test: Skip # Tear-off not supported
 
 sync_generator2_test/01: MissingCompileTimeError # Issue 22252
 sync_generator2_test/02: MissingCompileTimeError # Issue 22252
@@ -76,6 +78,13 @@
 mixin_super_constructor_positionals_test/01: MissingCompileTimeError # Issue 19576
 reify_typevar_static_test/00: MissingCompileTimeError # Issue 21565
 
+multiline_newline_test/01: CompileTimeError # Issue 23888
+multiline_newline_test/02: CompileTimeError # Issue 23888
+multiline_newline_test/03: CompileTimeError # Issue 23888
+multiline_newline_test/04: MissingCompileTimeError # Issue 23888
+multiline_newline_test/05: MissingCompileTimeError # Issue 23888
+multiline_newline_test/06: MissingCompileTimeError # Issue 23888
+
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
 #
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index b94754d..d6e6134 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -7,14 +7,15 @@
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
 
-symbol_conflict_test: CompileTimeError # 23870
-
 enum_syntax_test/02: Fail # 21649
 enum_syntax_test/03: Fail # 21649
 enum_syntax_test/04: Fail # 21649
 enum_syntax_test/05: Fail # 21649
 enum_syntax_test/06: Fail # 21649
 
+tearoff_basic_test: Skip # Tear-off not supported
+tearoff_constructor_basic_test: Skip # Tear-off not supported
+
 regress_17382_test: Skip # don't care about the static warning.
 regress_23408_test: Skip # don't care about the static warning.
 getter_setter_in_lib_test: Fail # issue 23286
@@ -32,6 +33,13 @@
 constructor_duplicate_final_test/03: Fail
 reify_typevar_static_test/00: MissingCompileTimeError # Issue 21565
 
+multiline_newline_test/01: CompileTimeError # Issue 23888
+multiline_newline_test/02: CompileTimeError # Issue 23888
+multiline_newline_test/03: CompileTimeError # Issue 23888
+multiline_newline_test/04: MissingCompileTimeError # Issue 23888
+multiline_newline_test/05: MissingCompileTimeError # Issue 23888
+multiline_newline_test/06: MissingCompileTimeError # Issue 23888
+
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
 #
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index b6ce534..00d35b0 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -10,10 +10,70 @@
 
 async_star_test/02: RuntimeError # 22853
 async_star_test/05: RuntimeError, Timeout
+tearoff_basic_test: Skip # Tear-off not supported
+tearoff_constructor_basic_test: Skip # Tear-off not supported
 
 try_catch_on_syntax_test/10: Fail # Issue 19823
 try_catch_on_syntax_test/11: Fail # Issue 19823
 
+call_function_apply_test: RuntimeError # Issue 23873
+
+conditional_method_invocation_test/12: Fail # Issue 23795
+conditional_method_invocation_test/13: Fail # Issue 23795
+conditional_method_invocation_test/14: Fail # Issue 23795
+conditional_method_invocation_test/15: Fail # Issue 23795
+conditional_method_invocation_test/16: Fail # Issue 23795
+conditional_method_invocation_test/17: Fail # Issue 23795
+conditional_method_invocation_test/18: Fail # Issue 23795
+conditional_method_invocation_test/19: Fail # Issue 23795
+conditional_property_access_test/10: Fail # Issue 23795
+conditional_property_access_test/11: Fail # Issue 23795
+conditional_property_access_test/12: Fail # Issue 23795
+conditional_property_access_test/13: Fail # Issue 23795
+conditional_property_access_test/14: Fail # Issue 23795
+conditional_property_access_test/15: Fail # Issue 23795
+conditional_property_access_test/16: Fail # Issue 23795
+conditional_property_access_test/17: Fail # Issue 23795
+conditional_property_assignment_test/23: Fail # Issue 23795
+conditional_property_assignment_test/24: Fail # Issue 23795
+conditional_property_assignment_test/25: Fail # Issue 23795
+conditional_property_assignment_test/26: Fail # Issue 23795
+conditional_property_assignment_test/27: Fail # Issue 23795
+conditional_property_assignment_test/28: Fail # Issue 23795
+conditional_property_assignment_test/29: Fail # Issue 23795
+conditional_property_assignment_test/30: Fail # Issue 23795
+conditional_property_assignment_test/31: Fail # Issue 23795
+conditional_property_assignment_test/32: Fail # Issue 23795
+conditional_property_assignment_test/33: Fail # Issue 23795
+conditional_property_assignment_test/34: Fail # Issue 23795
+conditional_property_assignment_test/35: Fail # Issue 23795
+conditional_property_increment_decrement_test/17: Fail # Issue 23795
+conditional_property_increment_decrement_test/18: Fail # Issue 23795
+conditional_property_increment_decrement_test/19: Fail # Issue 23795
+conditional_property_increment_decrement_test/20: Fail # Issue 23795
+conditional_property_increment_decrement_test/21: Fail # Issue 23795
+conditional_property_increment_decrement_test/22: Fail # Issue 23795
+conditional_property_increment_decrement_test/23: Fail # Issue 23795
+conditional_property_increment_decrement_test/24: Fail # Issue 23795
+conditional_property_increment_decrement_test/25: Fail # Issue 23795
+conditional_property_increment_decrement_test/26: Fail # Issue 23795
+conditional_property_increment_decrement_test/27: Fail # Issue 23795
+conditional_property_increment_decrement_test/28: Fail # Issue 23795
+conditional_property_increment_decrement_test/29: Fail # Issue 23795
+conditional_property_increment_decrement_test/30: Fail # Issue 23795
+conditional_property_increment_decrement_test/31: Fail # Issue 23795
+conditional_property_increment_decrement_test/32: Fail # Issue 23795
+conditional_property_increment_decrement_test/33: Fail # Issue 23795
+conditional_property_increment_decrement_test/34: Fail # Issue 23795
+conditional_property_increment_decrement_test/35: Fail # Issue 23795
+conditional_property_increment_decrement_test/36: Fail # Issue 23795
+conditional_property_increment_decrement_test/37: Fail # Issue 23795
+conditional_property_increment_decrement_test/38: Fail # Issue 23795
+conditional_property_increment_decrement_test/39: Fail # Issue 23795
+conditional_property_increment_decrement_test/40: Fail # Issue 23795
+if_null_assignment_behavior_test/31: Fail # Issue 23795
+if_null_assignment_behavior_test/32: Fail # Issue 23795
+
 [ $compiler == dart2js && $runtime == jsshell ]
 await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
 async_star_test: RuntimeError # Jsshell does not provide non-zero timers, Issue 7728
@@ -63,10 +123,8 @@
 nullaware_opt_test: Fail # Fails at e?.f ??= 200;
 
 if_null_assignment_behavior_test/29: Crash # Issue 23611
-if_null_assignment_behavior_test/30: Crash # Issue 23611
 prefix_assignment_test/01: Crash # Issue 23611
 prefix_assignment_test/02: Crash # Issue 23611
-prefix_identifier_reference_test/04: Crash # Issue 23611
 prefix_identifier_reference_test/05: Crash # Issue 23611
 
 const_error_multiply_initialized_test/02: CompileTimeError # Issue 23618
@@ -75,6 +133,14 @@
 # VM specific tests that should not be run by dart2js.
 vm/*: Skip # Issue 12699
 
+multiline_newline_test/01: CompileTimeError # Issue 23888
+multiline_newline_test/02: CompileTimeError # Issue 23888
+multiline_newline_test/03: CompileTimeError # Issue 23888
+multiline_newline_test/04: MissingCompileTimeError # Issue 23888
+multiline_newline_test/05: MissingCompileTimeError # Issue 23888
+multiline_newline_test/06: MissingCompileTimeError # Issue 23888
+multiline_newline_test/none: RuntimeError # Issue 23888
+
 [ $compiler == dart2js && $checked ]
 type_variable_bounds_test/02: Fail # Issue 12702
 type_variable_bounds2_test/01: Fail # Issue 12702
@@ -233,6 +299,7 @@
 [ $compiler == dart2js && $cps_ir == false ]
 generic_field_mixin4_test: Crash # Issue 18651
 generic_field_mixin5_test: Crash # Issue 18651
+many_method_calls_test: Crash # Stack overflow in HGraphVisitor.visitPostDominatorTree.visitBasicBlockAndSuccessors
 
 [ $compiler == dart2js && $cps_ir ]
 async_and_or_test: Crash # (test()async{await test1();await test2();}): cannot handle async/sync*/async* functions
@@ -351,9 +418,10 @@
 cha_deopt3_test: Crash # (d.make_u()): deferred access is not implemented
 closure_in_constructor_test: Crash # Invalid argument(s)
 closure_type_variables_test: Crash # Invalid argument(s)
+closures_initializer_test: RuntimeError # Please triage this failure.
 const_evaluation_test/01: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
 constructor12_test: RuntimeError # Please triage this failure.
-crash_6725_test/01: Crash # The null object does not have a getter '_element'.
+crash_6725_test/01: Crash # unsupported operation on erroneous element
 custom_await_stack_trace_test: Crash # (main()async{try {va...  cannot handle async/sync*/async* functions
 deferred_call_empty_before_load_test: Crash # (lib1.thefun()): deferred access is not implemented
 deferred_closurize_load_library_test: Crash # (lib.trueVar): deferred access is not implemented
@@ -394,8 +462,13 @@
 deferred_shadow_load_library_test: Crash # (lib.trueVar): deferred access is not implemented
 deferred_shared_and_unshared_classes_test: Crash # (lib2.foo()): deferred access is not implemented
 deferred_static_seperate_test: Crash # (lib1.x): deferred access is not implemented
+deferred_type_dependency_test/as: Crash # (main()async{await l...  cannot handle async/sync*/async* functions
+deferred_type_dependency_test/is: Crash # (main()async{await l...  cannot handle async/sync*/async* functions
+deferred_type_dependency_test/none: Crash # (main()async{await l...  cannot handle async/sync*/async* functions
+deferred_type_dependency_test/type_annotation: Crash # (main()async{await l...  cannot handle async/sync*/async* functions
 enum_mirror_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
 final_super_field_set_test/01: RuntimeError # Please triage this failure.
+first_class_types_test: RuntimeError # Please triage this failure.
 flatten_test/01: Crash # (test()async{int x=await new Derived<int>();}): cannot handle async/sync*/async* functions
 flatten_test/02: Crash # (test()async{Future<int> f()async=>new Derived<int>();}): cannot handle async/sync*/async* functions
 flatten_test/03: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
@@ -411,7 +484,10 @@
 flatten_test/none: Crash # (test()async{}): cannot handle async/sync*/async* functions
 for2_test: Crash # The null object does not have a getter 'field'.
 for_variable_capture_test: Crash # (i=0): For-loop variable captured in loop header
+generic2_test: RuntimeError # Please triage this failure.
 generic_field_mixin3_test: RuntimeError # Please triage this failure.
+generic_instanceof_test: RuntimeError # Please triage this failure.
+generic_native_test: RuntimeError # Please triage this failure.
 if_null_assignment_behavior_test/12: RuntimeError # Please triage this failure.
 if_null_assignment_behavior_test/28: RuntimeError # Please triage this failure.
 if_null_assignment_static_test/01: RuntimeError # v0.get$a is not a function
@@ -428,17 +504,15 @@
 if_null_assignment_static_test/40: RuntimeError # v0.get$a is not a function
 infinite_switch_label_test: Crash # (switch (target){l0:...  continue to a labeled switch case
 instance_creation_in_function_annotation_test: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
+instanceof2_test: RuntimeError # Please triage this failure.
 instanceof4_test/01: RuntimeError # Please triage this failure.
 invocation_mirror_invoke_on_test: RuntimeError # Please triage this failure.
 invocation_mirror_test: Crash # (super[37]=42): visitUnresolvedSuperIndexSet
 issue_1751477_test: RuntimeError # O.loadLibrary is not a function
-large_class_declaration_test: Crash # Stack Overflow
+list_is_test: RuntimeError # Please triage this failure.
 list_test: RuntimeError # Please triage this failure.
+many_generic_instanceof_test: RuntimeError # Please triage this failure.
 many_overridden_no_such_method_test: RuntimeError # Please triage this failure.
-mixin_type_parameters_mixin_extends_test: Crash # The null object does not have a getter '_element'.
-mixin_type_parameters_mixin_test: Crash # The null object does not have a getter '_element'.
-mixin_type_parameters_super_extends_test: Crash # The null object does not have a getter '_element'.
-mixin_type_parameters_super_test: Crash # The null object does not have a getter '_element'.
 nested_switch_label_test: Crash # (switch (target){out...  continue to a labeled switch case
 no_such_method_test: RuntimeError # Please triage this failure.
 null_test/none: Crash # (static Iterable<Str...  cannot handle async/sync*/async* functions
@@ -451,8 +525,6 @@
 regress_22579_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 regress_22728_test: Crash # (main()async{bool fa...  cannot handle async/sync*/async* functions
 regress_22777_test: Crash # (test()async{try {te...  cannot handle async/sync*/async* functions
-regress_22936_test/01: Crash # The null object does not have a getter '_element'.
-regress_22936_test/none: Crash # The null object does not have a getter '_element'.
 regress_23408_test: RuntimeError # G.loadLibrary is not a function
 regress_23498_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 regress_23500_test/01: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
@@ -483,7 +555,6 @@
 syncstar_yield_test/copyParameters: Crash # (Iterable<int> foo3(...  cannot handle async/sync*/async* functions
 syncstar_yield_test/none: Crash # (Iterable<int> foo3(...  cannot handle async/sync*/async* functions
 syncstar_yieldstar_test: Crash # (main()async{Expect....  cannot handle async/sync*/async* functions
-try_catch_test/none: Crash # The null object does not have a getter '_element'.
 type_parameter_test/01: Crash # Invalid argument(s)
 type_parameter_test/02: Crash # Invalid argument(s)
 type_parameter_test/03: Crash # Invalid argument(s)
@@ -493,3 +564,9 @@
 type_parameter_test/none: Crash # Invalid argument(s)
 type_variable_closure2_test: RuntimeError # Please triage this failure.
 type_variable_closure_test: Crash # Invalid argument(s)
+type_variable_field_initializer_closure_test: RuntimeError # Please triage this failure.
+type_variable_field_initializer_test: RuntimeError # Please triage this failure.
+type_variable_nested_test: RuntimeError # Please triage this failure.
+
+[ $compiler == dart2js && ($runtime == d8 || $runtime == jsshell) ]
+issue23244_test: RuntimeError # 23244
diff --git a/tests/language/larger_implicit_getter_test.dart b/tests/language/larger_implicit_getter_test.dart
new file mode 100644
index 0000000..31c5969
--- /dev/null
+++ b/tests/language/larger_implicit_getter_test.dart
@@ -0,0 +1,4100 @@
+// 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.
+// Dart test program for testing compilation of large implicit getters.
+
+import 'package:expect/expect.dart';
+
+List<List> panels = [
+  [6853.940039224797,6050.837897021371],
+  [6953.240039224797,6050.837897021371],
+  [7052.5400392247975,5885.237897021371],
+  [7052.5400392247975,5719.637897021372],
+  [7151.840039224798,5885.237897021371],
+  [7052.5400392247975,6050.837897021371],
+  [7052.5400392247975,6216.43789702137],
+  [7052.5400392247975,6382.03789702137],
+  [6953.240039224797,6382.03789702137],
+  [6953.240039224797,6216.43789702137],
+  [6853.940039224797,6216.43789702137],
+  [6853.940039224797,6382.03789702137],
+  [6754.640039224797,6216.43789702137],
+  [6754.640039224797,6382.03789702137],
+  [6754.640039224797,6547.637897021369],
+  [6754.640039224797,6713.237897021369],
+  [6655.340039224797,6713.237897021369],
+  [6754.640039224797,6878.837897021368],
+  [6853.940039224797,6713.237897021369],
+  [6853.940039224797,6878.837897021368],
+  [6953.240039224797,6713.237897021369],
+  [7052.5400392247975,6547.637897021369],
+  [7151.840039224798,6713.237897021369],
+  [7151.840039224798,6547.637897021369],
+  [7151.840039224798,6382.03789702137],
+  [7251.140039224798,6547.637897021369],
+  [7251.140039224798,6713.237897021369],
+  [7350.440039224798,6878.837897021368],
+  [7449.740039224798,6878.837897021368],
+  [7449.740039224798,6713.237897021369],
+  [7549.040039224798,6547.637897021369],
+  [7449.740039224798,6382.03789702137],
+  [7449.740039224798,6216.43789702137],
+  [7549.040039224798,6050.837897021371],
+  [7648.340039224799,6216.43789702137],
+  [7549.040039224798,6382.03789702137],
+  [7648.340039224799,6382.03789702137],
+  [7747.640039224799,6216.43789702137],
+  [7846.940039224799,6382.03789702137],
+  [7946.240039224799,6382.03789702137],
+  [7946.240039224799,6547.637897021369],
+  [7846.940039224799,6713.237897021369],
+  [7946.240039224799,6713.237897021369],
+  [8045.540039224799,6547.637897021369],
+  [8045.540039224799,6713.237897021369],
+  [7946.240039224799,6878.837897021368],
+  [7946.240039224799,7044.4378970213675],
+  [8045.540039224799,7210.037897021367],
+  [8144.8400392247995,7375.637897021366],
+  [8144.8400392247995,7541.237897021366],
+  [8045.540039224799,7375.637897021366],
+  [8144.8400392247995,7210.037897021367],
+  [8045.540039224799,7044.4378970213675],
+  [7946.240039224799,7210.037897021367],
+  [7846.940039224799,7210.037897021367],
+  [7946.240039224799,7375.637897021366],
+  [8045.540039224799,7541.237897021366],
+  [8144.8400392247995,7706.837897021365],
+  [8244.1400392248,7541.237897021366],
+  [8343.4400392248,7541.237897021366],
+  [8343.4400392248,7706.837897021365],
+  [8244.1400392248,7706.837897021365],
+  [4735.523842661975,3503.497768214323],
+  [4636.223842661975,3337.897768214323],
+  [4536.923842661975,3337.897768214323],
+  [4437.623842661975,3172.2977682143232],
+  [4338.323842661975,3172.2977682143232],
+  [4239.023842661974,3172.2977682143232],
+  [4338.323842661975,3006.6977682143233],
+  [4437.623842661975,2841.0977682143234],
+  [4338.323842661975,2675.4977682143235],
+  [4338.323842661975,2509.8977682143236],
+  [4239.023842661974,2675.4977682143235],
+  [4139.723842661974,2509.8977682143236],
+  [4040.4238426619745,2344.2977682143237],
+  [4139.723842661974,2178.697768214324],
+  [4239.023842661974,2178.697768214324],
+  [4139.723842661974,2344.2977682143237],
+  [4040.4238426619745,2178.697768214324],
+  [4139.723842661974,2013.0977682143237],
+  [4139.723842661974,1847.4977682143235],
+  [4239.023842661974,2013.0977682143237],
+  [4239.023842661974,1847.4977682143235],
+  [4338.323842661975,1847.4977682143235],
+  [4437.623842661975,1847.4977682143235],
+  [4536.923842661975,1681.8977682143234],
+  [4437.623842661975,1516.2977682143232],
+  [4536.923842661975,1516.2977682143232],
+  [4536.923842661975,1350.697768214323],
+  [4437.623842661975,1350.697768214323],
+  [4536.923842661975,1185.097768214323],
+  [4636.223842661975,1019.497768214323],
+  [4536.923842661975,853.897768214323],
+  [4636.223842661975,853.897768214323],
+  [4735.523842661975,688.2977682143231],
+  [4636.223842661975,522.6977682143232],
+  [4636.223842661975,357.09776821432325],
+  [4735.523842661975,357.09776821432325],
+  [4735.523842661975,522.6977682143232],
+  [4636.223842661975,688.2977682143231],
+  [4735.523842661975,853.897768214323],
+  [4834.8238426619755,853.897768214323],
+  [4735.523842661975,1019.497768214323],
+  [4735.523842661975,1185.097768214323],
+  [4735.523842661975,1350.697768214323],
+  [4834.8238426619755,1516.2977682143232],
+  [4735.523842661975,1516.2977682143232],
+  [4834.8238426619755,1350.697768214323],
+  [4834.8238426619755,1185.097768214323],
+  [4934.123842661976,1350.697768214323],
+  [5033.423842661976,1185.097768214323],
+  [5033.423842661976,1019.497768214323],
+  [5033.423842661976,853.897768214323],
+  [4934.123842661976,853.897768214323],
+  [4934.123842661976,1019.497768214323],
+  [4834.8238426619755,1019.497768214323],
+  [4934.123842661976,1185.097768214323],
+  [5033.423842661976,1350.697768214323],
+  [5132.723842661976,1350.697768214323],
+  [5132.723842661976,1185.097768214323],
+  [5232.023842661976,1019.497768214323],
+  [5232.023842661976,1185.097768214323],
+  [5331.323842661976,1019.497768214323],
+  [5430.623842661977,1019.497768214323],
+  [5529.923842661977,1185.097768214323],
+  [5430.623842661977,1350.697768214323],
+  [5430.623842661977,1516.2977682143232],
+  [5529.923842661977,1350.697768214323],
+  [5629.223842661977,1350.697768214323],
+  [5728.523842661977,1350.697768214323],
+  [5728.523842661977,1516.2977682143232],
+  [5728.523842661977,1681.8977682143234],
+  [5629.223842661977,1516.2977682143232],
+  [5529.923842661977,1516.2977682143232],
+  [5629.223842661977,1681.8977682143234],
+  [5529.923842661977,1681.8977682143234],
+  [5430.623842661977,1847.4977682143235],
+  [5331.323842661976,1847.4977682143235],
+  [5331.323842661976,2013.0977682143237],
+  [5232.023842661976,2178.697768214324],
+  [5132.723842661976,2013.0977682143237],
+  [5132.723842661976,2178.697768214324],
+  [5232.023842661976,2013.0977682143237],
+  [5232.023842661976,1847.4977682143235],
+  [5232.023842661976,1681.8977682143234],
+  [5331.323842661976,1681.8977682143234],
+  [5331.323842661976,1516.2977682143232],
+  [5331.323842661976,1350.697768214323],
+  [5232.023842661976,1350.697768214323],
+  [5232.023842661976,1516.2977682143232],
+  [5132.723842661976,1516.2977682143232],
+  [5132.723842661976,1681.8977682143234],
+  [5033.423842661976,1847.4977682143235],
+  [5132.723842661976,1847.4977682143235],
+  [5033.423842661976,2013.0977682143237],
+  [4934.123842661976,2178.697768214324],
+  [5033.423842661976,2344.2977682143237],
+  [4934.123842661976,2344.2977682143237],
+  [4834.8238426619755,2178.697768214324],
+  [4834.8238426619755,2344.2977682143237],
+  [4735.523842661975,2344.2977682143237],
+  [4636.223842661975,2344.2977682143237],
+  [4536.923842661975,2178.697768214324],
+  [4437.623842661975,2013.0977682143237],
+  [4338.323842661975,2178.697768214324],
+  [4437.623842661975,2344.2977682143237],
+  [4536.923842661975,2509.8977682143236],
+  [4636.223842661975,2675.4977682143235],
+  [4636.223842661975,2509.8977682143236],
+  [4536.923842661975,2675.4977682143235],
+  [4636.223842661975,2841.0977682143234],
+  [4536.923842661975,2841.0977682143234],
+  [4636.223842661975,3006.6977682143233],
+  [4735.523842661975,3172.2977682143232],
+  [4834.8238426619755,3006.6977682143233],
+  [4735.523842661975,2841.0977682143234],
+  [4735.523842661975,3006.6977682143233],
+  [4636.223842661975,3172.2977682143232],
+  [4735.523842661975,3337.897768214323],
+  [4834.8238426619755,3503.497768214323],
+  [4735.523842661975,3669.097768214323],
+  [4834.8238426619755,3834.697768214323],
+  [4834.8238426619755,3669.097768214323],
+  [4934.123842661976,3503.497768214323],
+  [5033.423842661976,3503.497768214323],
+  [5033.423842661976,3337.897768214323],
+  [4934.123842661976,3337.897768214323],
+  [4834.8238426619755,3172.2977682143232],
+  [4834.8238426619755,3337.897768214323],
+  [4934.123842661976,3172.2977682143232],
+  [5033.423842661976,3006.6977682143233],
+  [5132.723842661976,2841.0977682143234],
+  [5132.723842661976,3006.6977682143233],
+  [5232.023842661976,3172.2977682143232],
+  [5232.023842661976,3337.897768214323],
+  [5132.723842661976,3337.897768214323],
+  [5232.023842661976,3503.497768214323],
+  [5331.323842661976,3337.897768214323],
+  [5331.323842661976,3503.497768214323],
+  [5430.623842661977,3669.097768214323],
+  [5331.323842661976,3669.097768214323],
+  [5430.623842661977,3503.497768214323],
+  [5430.623842661977,3337.897768214323],
+  [5529.923842661977,3172.2977682143232],
+  [5529.923842661977,3337.897768214323],
+  [5629.223842661977,3337.897768214323],
+  [5728.523842661977,3337.897768214323],
+  [5728.523842661977,3503.497768214323],
+  [5827.823842661977,3503.497768214323],
+  [5927.1238426619775,3669.097768214323],
+  [6026.423842661978,3669.097768214323],
+  [6125.723842661978,3503.497768214323],
+  [6125.723842661978,3669.097768214323],
+  [6225.023842661978,3503.497768214323],
+  [6225.023842661978,3337.897768214323],
+  [6324.323842661978,3337.897768214323],
+  [6423.623842661978,3503.497768214323],
+  [6324.323842661978,3669.097768214323],
+  [6225.023842661978,3669.097768214323],
+  [6324.323842661978,3834.697768214323],
+  [6423.623842661978,3834.697768214323],
+  [6324.323842661978,4000.297768214323],
+  [6225.023842661978,3834.697768214323],
+  [6125.723842661978,3834.697768214323],
+  [6125.723842661978,4000.297768214323],
+  [6225.023842661978,4000.297768214323],
+  [6225.023842661978,4165.897768214322],
+  [6225.023842661978,4331.497768214322],
+  [6125.723842661978,4165.897768214322],
+  [6026.423842661978,4000.2977682143223],
+  [5927.1238426619775,4165.897768214322],
+  [6026.423842661978,4331.497768214322],
+  [6026.423842661978,4497.097768214321],
+  [5927.1238426619775,4497.097768214321],
+  [5827.823842661977,4662.697768214321],
+  [5728.523842661977,4828.29776821432],
+  [5827.823842661977,4828.29776821432],
+  [5927.1238426619775,4828.29776821432],
+  [5927.1238426619775,4662.697768214321],
+  [5827.823842661977,4497.097768214321],
+  [5927.1238426619775,4331.497768214322],
+  [5827.823842661977,4165.897768214322],
+  [5728.523842661977,4331.497768214322],
+  [5728.523842661977,4165.897768214322],
+  [5629.223842661977,4000.2977682143223],
+  [5629.223842661977,3834.6977682143224],
+  [5529.923842661977,3669.0977682143225],
+  [5629.223842661977,3503.4977682143226],
+  [5728.523842661977,3669.0977682143225],
+  [5827.823842661977,3669.0977682143225],
+  [5927.1238426619775,3834.6977682143224],
+  [5927.1238426619775,4000.2977682143223],
+  [6026.423842661978,4165.897768214322],
+  [6125.723842661978,4331.497768214322],
+  [6225.023842661978,4497.097768214321],
+  [6225.023842661978,4662.697768214321],
+  [6324.323842661978,4662.697768214321],
+  [6225.023842661978,4828.29776821432],
+  [6324.323842661978,4828.29776821432],
+  [6423.623842661978,4828.29776821432],
+  [6324.323842661978,4993.8977682143195],
+  [6225.023842661978,5159.497768214319],
+  [6125.723842661978,5159.497768214319],
+  [6026.423842661978,5325.097768214318],
+  [5927.1238426619775,5490.697768214318],
+  [6026.423842661978,5656.297768214317],
+  [5927.1238426619775,5821.897768214317],
+  [5927.1238426619775,5987.497768214316],
+  [6026.423842661978,5987.497768214316],
+  [6026.423842661978,5821.897768214317],
+  [5927.1238426619775,5656.297768214317],
+  [5827.823842661977,5656.297768214317],
+  [5827.823842661977,5490.697768214318],
+  [5728.523842661977,5490.697768214318],
+  [5629.223842661977,5325.097768214318],
+  [5629.223842661977,5159.497768214319],
+  [5529.923842661977,4993.8977682143195],
+  [5529.923842661977,5159.497768214319],
+  [5629.223842661977,4993.8977682143195],
+  [5629.223842661977,4828.29776821432],
+  [5529.923842661977,4662.697768214321],
+  [5430.623842661977,4828.29776821432],
+  [5529.923842661977,4828.29776821432],
+  [5629.223842661977,4662.697768214321],
+  [5728.523842661977,4662.697768214321],
+  [5629.223842661977,4497.097768214321],
+  [5728.523842661977,4497.097768214321],
+  [5827.823842661977,4331.497768214322],
+  [10216.161365168813,2951.605409896135],
+  [10116.861365168812,2951.605409896135],
+  [10017.56136516881,3117.205409896135],
+  [9918.26136516881,3117.205409896135],
+  [9818.961365168809,3117.205409896135],
+  [9719.661365168808,3282.8054098961347],
+  [9620.361365168807,3282.8054098961347],
+  [9620.361365168807,3117.205409896135],
+  [9521.061365168805,2951.605409896135],
+  [9521.061365168805,2786.005409896135],
+  [9620.361365168807,2786.005409896135],
+  [9719.661365168808,2786.005409896135],
+  [9818.961365168809,2620.405409896135],
+  [9918.26136516881,2786.005409896135],
+  [9818.961365168809,2951.605409896135],
+  [9818.961365168809,2786.005409896135],
+  [9719.661365168808,2620.405409896135],
+  [9719.661365168808,2454.805409896135],
+  [9620.361365168807,2289.2054098961353],
+  [9521.061365168805,2123.6054098961354],
+  [9620.361365168807,1958.0054098961352],
+  [9719.661365168808,2123.6054098961354],
+  [9818.961365168809,2289.2054098961353],
+  [9818.961365168809,2123.6054098961354],
+  [9818.961365168809,1958.0054098961352],
+  [9719.661365168808,1958.0054098961352],
+  [9620.361365168807,1792.405409896135],
+  [9620.361365168807,1626.805409896135],
+  [9521.061365168805,1461.2054098961348],
+  [9421.761365168804,1295.6054098961347],
+  [9521.061365168805,1130.0054098961346],
+  [9521.061365168805,964.4054098961345],
+  [9421.761365168804,964.4054098961345],
+  [9521.061365168805,798.8054098961346],
+  [9620.361365168807,798.8054098961346],
+  [9620.361365168807,964.4054098961345],
+  [9620.361365168807,1130.0054098961346],
+  [9620.361365168807,1295.6054098961347],
+  [9620.361365168807,1461.2054098961348],
+  [9719.661365168808,1295.6054098961347],
+  [9818.961365168809,1130.0054098961346],
+  [9918.26136516881,964.4054098961345],
+  [9818.961365168809,964.4054098961345],
+  [9918.26136516881,798.8054098961346],
+  [10017.56136516881,633.2054098961347],
+  [9918.26136516881,467.60540989613474],
+  [9918.26136516881,302.0054098961348],
+  [10017.56136516881,302.0054098961348],
+  [10116.861365168812,136.40540989613478],
+  [10116.861365168812,302.0054098961348],
+  [10116.861365168812,467.60540989613474],
+  [10116.861365168812,633.2054098961347],
+  [10216.161365168813,633.2054098961347],
+  [10216.161365168813,798.8054098961346],
+  [10315.461365168814,633.2054098961347],
+  [10315.461365168814,798.8054098961346],
+  [10414.761365168815,798.8054098961346],
+  [10514.061365168816,633.2054098961347],
+  [10514.061365168816,798.8054098961346],
+  [10414.761365168815,964.4054098961345],
+  [10315.461365168814,964.4054098961345],
+  [10216.161365168813,964.4054098961345],
+  [10116.861365168812,798.8054098961346],
+  [10017.56136516881,798.8054098961346],
+  [10116.861365168812,964.4054098961345],
+  [10216.161365168813,1130.0054098961346],
+  [10116.861365168812,1130.0054098961346],
+  [10216.161365168813,1295.6054098961347],
+  [10216.161365168813,1461.2054098961348],
+  [10315.461365168814,1626.805409896135],
+  [10315.461365168814,1792.405409896135],
+  [10216.161365168813,1958.0054098961352],
+  [10216.161365168813,1792.405409896135],
+  [10116.861365168812,1792.405409896135],
+  [10017.56136516881,1958.0054098961352],
+  [9918.26136516881,2123.6054098961354],
+  [9918.26136516881,1958.0054098961352],
+  [10017.56136516881,2123.6054098961354],
+  [10116.861365168812,2123.6054098961354],
+  [10017.56136516881,2289.2054098961353],
+  [10017.56136516881,2454.805409896135],
+  [10116.861365168812,2289.2054098961353],
+  [10216.161365168813,2454.805409896135],
+  [10315.461365168814,2620.405409896135],
+  [10315.461365168814,2454.805409896135],
+  [10315.461365168814,2289.2054098961353],
+  [10414.761365168815,2454.805409896135],
+  [10514.061365168816,2620.405409896135],
+  [10613.361365168817,2786.005409896135],
+  [10514.061365168816,2786.005409896135],
+  [10613.361365168817,2620.405409896135],
+  [10514.061365168816,2454.805409896135],
+  [10514.061365168816,2289.2054098961353],
+  [10613.361365168817,2289.2054098961353],
+  [10712.661365168819,2289.2054098961353],
+  [10811.96136516882,2454.805409896135],
+  [10911.26136516882,2289.2054098961353],
+  [10811.96136516882,2289.2054098961353],
+  [10712.661365168819,2454.805409896135],
+  [10712.661365168819,2620.405409896135],
+  [10811.96136516882,2786.005409896135],
+  [10911.26136516882,2620.405409896135],
+  [10911.26136516882,2786.005409896135],
+  [11010.561365168822,2620.405409896135],
+  [10911.26136516882,2454.805409896135],
+  [10811.96136516882,2620.405409896135],
+  [10712.661365168819,2786.005409896135],
+  [10811.96136516882,2951.605409896135],
+  [10911.26136516882,2951.605409896135],
+  [10811.96136516882,3117.205409896135],
+  [10712.661365168819,2951.605409896135],
+  [10613.361365168817,2951.605409896135],
+  [10514.061365168816,2951.605409896135],
+  [10414.761365168815,3117.205409896135],
+  [10414.761365168815,2951.605409896135],
+  [10315.461365168814,2786.005409896135],
+  [10216.161365168813,2620.405409896135],
+  [10216.161365168813,2786.005409896135],
+  [10315.461365168814,2951.605409896135],
+  [10315.461365168814,3117.205409896135],
+  [10216.161365168813,3117.205409896135],
+  [10116.861365168812,3117.205409896135],
+  [10017.56136516881,3282.8054098961347],
+  [9918.26136516881,3448.4054098961346],
+  [9818.961365168809,3448.4054098961346],
+  [9818.961365168809,3614.0054098961346],
+  [9719.661365168808,3448.4054098961346],
+  [9818.961365168809,3282.8054098961347],
+  [9719.661365168808,3117.205409896135],
+  [9620.361365168807,2951.605409896135],
+  [9521.061365168805,3117.205409896135],
+  [9521.061365168805,3282.8054098961347],
+  [9421.761365168804,3117.205409896135],
+  [9421.761365168804,3282.8054098961347],
+  [9322.461365168803,3117.205409896135],
+  [9421.761365168804,2951.605409896135],
+  [9322.461365168803,2951.605409896135],
+  [9223.161365168802,2786.005409896135],
+  [9322.461365168803,2620.405409896135],
+  [9421.761365168804,2454.805409896135],
+  [9521.061365168805,2289.2054098961353],
+  [9421.761365168804,2123.6054098961354],
+  [9421.761365168804,1958.0054098961352],
+  [9421.761365168804,1792.405409896135],
+  [9521.061365168805,1626.805409896135],
+  [9421.761365168804,1626.805409896135],
+  [9322.461365168803,1792.405409896135],
+  [9322.461365168803,1626.805409896135],
+  [9322.461365168803,1461.2054098961348],
+  [9421.761365168804,1461.2054098961348],
+  [9521.061365168805,1295.6054098961347],
+  [9421.761365168804,1130.0054098961346],
+  [9322.461365168803,964.4054098961345],
+  [9223.161365168802,964.4054098961345],
+  [9223.161365168802,798.8054098961346],
+  [9322.461365168803,633.2054098961347],
+  [9421.761365168804,798.8054098961346],
+  [9421.761365168804,633.2054098961347],
+  [9521.061365168805,633.2054098961347],
+  [9421.761365168804,467.60540989613474],
+  [9421.761365168804,302.0054098961348],
+  [9322.461365168803,136.40540989613478],
+  [9223.161365168802,302.0054098961348],
+  [9123.861365168801,302.0054098961348],
+  [9024.5613651688,136.40540989613478],
+  [9123.861365168801,136.40540989613478],
+  [9223.161365168802,136.40540989613478],
+  [9322.461365168803,302.0054098961348],
+  [9421.761365168804,136.40540989613478],
+  [9521.061365168805,136.40540989613478],
+  [9620.361365168807,136.40540989613478],
+  [9620.361365168807,302.0054098961348],
+  [9521.061365168805,302.0054098961348],
+  [9521.061365168805,467.60540989613474],
+  [9620.361365168807,467.60540989613474],
+  [9719.661365168808,302.0054098961348],
+  [9719.661365168808,136.40540989613478],
+  [9818.961365168809,136.40540989613478],
+  [9918.26136516881,136.40540989613478],
+  [10017.56136516881,136.40540989613478],
+  [366.07287160549004,5394.185440937868],
+  [465.37287160549005,5394.185440937868],
+  [465.37287160549005,5559.785440937868],
+  [366.0728716054901,5559.785440937868],
+  [366.0728716054901,5725.385440937867],
+  [266.77287160549014,5725.385440937867],
+  [167.47287160549016,5559.785440937868],
+  [266.77287160549014,5559.785440937868],
+  [266.77287160549014,5394.185440937868],
+  [266.77287160549014,5228.585440937869],
+  [167.47287160549016,5394.185440937868],
+  [68.17287160549016,5228.585440937869],
+  [167.47287160549013,5062.9854409378695],
+  [68.17287160549013,4897.38544093787],
+  [167.47287160549013,4731.785440937871],
+  [266.77287160549014,4731.785440937871],
+  [167.47287160549016,4566.185440937871],
+  [68.17287160549016,4566.185440937871],
+  [68.17287160549016,4731.785440937871],
+  [167.47287160549013,4897.38544093787],
+  [68.17287160549013,5062.9854409378695],
+  [167.47287160549013,5228.585440937869],
+  [266.77287160549014,5062.9854409378695],
+  [366.0728716054901,4897.38544093787],
+  [266.77287160549014,4897.38544093787],
+  [366.0728716054901,4731.785440937871],
+  [465.37287160549005,4897.38544093787],
+  [366.0728716054901,5062.9854409378695],
+  [465.37287160549005,5062.9854409378695],
+  [366.0728716054901,5228.585440937869],
+  [465.37287160549005,5228.585440937869],
+  [564.6728716054901,5394.185440937868],
+  [663.9728716054901,5228.585440937869],
+  [564.6728716054901,5062.9854409378695],
+  [663.9728716054901,4897.38544093787],
+  [763.2728716054902,4731.785440937871],
+  [862.5728716054903,4566.185440937871],
+  [961.8728716054903,4731.785440937871],
+  [862.5728716054903,4731.785440937871],
+  [961.8728716054903,4566.185440937871],
+  [862.5728716054903,4400.585440937872],
+  [961.8728716054903,4234.985440937872],
+  [1061.1728716054904,4400.585440937872],
+  [1160.4728716054904,4234.985440937872],
+  [1160.4728716054904,4400.585440937872],
+  [1259.7728716054903,4234.985440937872],
+  [1359.0728716054903,4069.3854409378723],
+  [1458.3728716054902,4069.3854409378723],
+  [1557.6728716054902,4234.985440937872],
+  [1656.9728716054901,4400.585440937872],
+  [1557.6728716054902,4400.585440937872],
+  [1458.3728716054902,4400.585440937872],
+  [1359.0728716054903,4566.185440937871],
+  [1359.0728716054903,4731.785440937871],
+  [1259.7728716054903,4731.785440937871],
+  [1359.0728716054903,4897.38544093787],
+  [1458.3728716054902,4731.785440937871],
+  [1458.3728716054902,4897.38544093787],
+  [1359.0728716054903,5062.9854409378695],
+  [1259.7728716054903,5228.585440937869],
+  [1259.7728716054903,5062.9854409378695],
+  [1259.7728716054903,4897.38544093787],
+  [1160.4728716054904,5062.9854409378695],
+  [1160.4728716054904,5228.585440937869],
+  [1061.1728716054904,5228.585440937869],
+  [1061.1728716054904,5062.9854409378695],
+  [961.8728716054903,5228.585440937869],
+  [862.5728716054903,5062.9854409378695],
+  [961.8728716054903,5062.9854409378695],
+  [961.8728716054903,4897.38544093787],
+  [1061.1728716054904,4897.38544093787],
+  [1160.4728716054904,4731.785440937871],
+  [1259.7728716054903,4566.185440937871],
+  [1359.0728716054903,4400.585440937872],
+  [1458.3728716054902,4566.185440937871],
+  [1557.6728716054902,4566.185440937871],
+  [1656.9728716054901,4731.785440937871],
+  [1557.6728716054902,4897.38544093787],
+  [1458.3728716054902,5062.9854409378695],
+  [1557.6728716054902,5228.585440937869],
+  [1656.9728716054901,5062.9854409378695],
+  [1756.27287160549,5062.9854409378695],
+  [1756.27287160549,4897.38544093787],
+  [1855.57287160549,5062.9854409378695],
+  [1954.87287160549,4897.38544093787],
+  [2054.17287160549,5062.9854409378695],
+  [1954.87287160549,5062.9854409378695],
+  [2054.17287160549,5228.585440937869],
+  [2153.4728716054897,5228.585440937869],
+  [2252.7728716054894,5062.9854409378695],
+  [2352.072871605489,5228.585440937869],
+  [2451.372871605489,5394.185440937868],
+  [2352.072871605489,5394.185440937868],
+  [2252.7728716054894,5228.585440937869],
+  [2153.4728716054897,5062.9854409378695],
+  [2153.4728716054897,4897.38544093787],
+  [2252.7728716054894,4897.38544093787],
+  [2352.072871605489,4731.785440937871],
+  [2252.7728716054894,4731.785440937871],
+  [2153.4728716054897,4731.785440937871],
+  [2054.17287160549,4566.185440937871],
+  [1954.87287160549,4731.785440937871],
+  [1855.57287160549,4897.38544093787],
+  [1756.27287160549,4731.785440937871],
+  [1855.57287160549,4731.785440937871],
+  [1855.57287160549,4566.185440937871],
+  [1756.27287160549,4566.185440937871],
+  [1656.9728716054901,4566.185440937871],
+  [1557.6728716054902,4731.785440937871],
+  [1656.9728716054901,4897.38544093787],
+  [1557.6728716054902,5062.9854409378695],
+  [1458.3728716054902,5228.585440937869],
+  [1359.0728716054903,5228.585440937869],
+  [1259.7728716054903,5394.185440937868],
+  [1259.7728716054903,5559.785440937868],
+  [1160.4728716054904,5559.785440937868],
+  [1061.1728716054904,5559.785440937868],
+  [1160.4728716054904,5725.385440937867],
+  [1259.7728716054903,5725.385440937867],
+  [1359.0728716054903,5559.785440937868],
+  [1458.3728716054902,5725.385440937867],
+  [1458.3728716054902,5559.785440937868],
+  [1359.0728716054903,5725.385440937867],
+  [1259.7728716054903,5890.985440937867],
+  [1359.0728716054903,5890.985440937867],
+  [1259.7728716054903,6056.585440937866],
+  [1359.0728716054903,6222.185440937866],
+  [1458.3728716054902,6222.185440937866],
+  [1458.3728716054902,6387.785440937865],
+  [1557.6728716054902,6222.185440937866],
+  [1557.6728716054902,6387.785440937865],
+  [1656.9728716054901,6222.185440937866],
+  [1756.27287160549,6056.585440937866],
+  [1855.57287160549,5890.985440937867],
+  [1756.27287160549,5890.985440937867],
+  [1656.9728716054901,6056.585440937866],
+  [1557.6728716054902,5890.985440937867],
+  [1458.3728716054902,5890.985440937867],
+  [1359.0728716054903,6056.585440937866],
+  [1259.7728716054903,6222.185440937866],
+  [1160.4728716054904,6056.585440937866],
+  [1061.1728716054904,5890.985440937867],
+  [1061.1728716054904,6056.585440937866],
+  [1160.4728716054904,6222.185440937866],
+  [1061.1728716054904,6222.185440937866],
+  [961.8728716054903,6222.185440937866],
+  [961.8728716054903,6056.585440937866],
+  [961.8728716054903,5890.985440937867],
+  [961.8728716054903,5725.385440937867],
+  [862.5728716054903,5559.785440937868],
+  [763.2728716054902,5725.385440937867],
+  [862.5728716054903,5725.385440937867],
+  [763.2728716054902,5890.985440937867],
+  [663.9728716054901,5725.385440937867],
+  [763.2728716054902,5559.785440937868],
+  [763.2728716054902,5394.185440937868],
+  [862.5728716054903,5228.585440937869],
+  [961.8728716054903,5394.185440937868],
+  [1061.1728716054904,5394.185440937868],
+  [961.8728716054903,5559.785440937868],
+  [862.5728716054903,5394.185440937868],
+  [763.2728716054902,5228.585440937869],
+  [663.9728716054901,5062.9854409378695],
+  [763.2728716054902,5062.9854409378695],
+  [763.2728716054902,4897.38544093787],
+  [663.9728716054901,4731.785440937871],
+  [564.6728716054901,4731.785440937871],
+  [465.37287160549005,4566.185440937871],
+  [366.0728716054901,4566.185440937871],
+  [465.37287160549005,4731.785440937871],
+  [564.6728716054901,4566.185440937871],
+  [465.37287160549005,4400.585440937872],
+  [366.0728716054901,4400.585440937872],
+  [266.77287160549014,4234.985440937872],
+  [167.47287160549016,4234.985440937872],
+  [266.77287160549014,4400.585440937872],
+  [266.77287160549014,4566.185440937871],
+  [167.47287160549016,4400.585440937872],
+  [68.17287160549016,4234.985440937872],
+  [167.47287160549013,4069.3854409378723],
+  [68.17287160549013,3903.7854409378724],
+  [68.17287160549013,4069.3854409378723],
+  [167.47287160549013,3903.7854409378724],
+  [266.77287160549014,3903.7854409378724],
+  [366.0728716054901,3738.1854409378725],
+  [266.77287160549014,3738.1854409378725],
+  [266.77287160549014,3572.5854409378726],
+  [167.47287160549016,3406.9854409378727],
+  [167.47287160549016,3241.3854409378728],
+  [266.77287160549014,3241.3854409378728],
+  [266.77287160549014,3406.9854409378727],
+  [366.0728716054901,3572.5854409378726],
+  [465.37287160549005,3738.1854409378725],
+  [465.37287160549005,3903.7854409378724],
+  [366.0728716054901,4069.3854409378723],
+  [366.0728716054901,4234.985440937872],
+  [465.37287160549005,4234.985440937872],
+  [564.6728716054901,4069.3854409378723],
+  [465.37287160549005,4069.3854409378723],
+  [564.6728716054901,4234.985440937872],
+  [663.9728716054901,4069.3854409378723],
+  [663.9728716054901,4234.985440937872],
+  [663.9728716054901,4400.585440937872],
+  [763.2728716054902,4566.185440937871],
+  [763.2728716054902,4400.585440937872],
+  [663.9728716054901,4566.185440937871],
+  [564.6728716054901,4400.585440937872],
+  [19431.915041401327,3495.506142643713],
+  [19332.61504140133,3661.1061426437127],
+  [19431.915041401327,3661.1061426437127],
+  [19531.215041401327,3661.1061426437127],
+  [19630.515041401326,3495.506142643713],
+  [19630.515041401326,3661.1061426437127],
+  [19729.815041401325,3826.7061426437126],
+  [19630.515041401326,3826.7061426437126],
+  [19729.815041401325,3992.3061426437125],
+  [19630.515041401326,3992.3061426437125],
+  [19630.515041401326,4157.906142643712],
+  [19630.515041401326,4323.506142643711],
+  [19531.215041401327,4157.906142643712],
+  [19431.915041401327,4323.506142643711],
+  [19531.215041401327,4489.106142643711],
+  [19431.915041401327,4654.70614264371],
+  [19332.61504140133,4654.70614264371],
+  [19332.61504140133,4820.30614264371],
+  [19332.61504140133,4985.906142643709],
+  [19233.31504140133,4985.906142643709],
+  [19134.01504140133,5151.506142643709],
+  [19034.71504140133,5151.506142643709],
+  [19134.01504140133,5317.106142643708],
+  [19034.71504140133,5317.106142643708],
+  [19034.71504140133,5482.706142643708],
+  [18935.41504140133,5648.306142643707],
+  [18836.115041401332,5813.9061426437065],
+  [18836.115041401332,5979.506142643706],
+  [18935.41504140133,5979.506142643706],
+  [19034.71504140133,6145.106142643705],
+  [19034.71504140133,5979.506142643706],
+  [19034.71504140133,5813.9061426437065],
+  [19134.01504140133,5648.306142643707],
+  [19233.31504140133,5648.306142643707],
+  [19134.01504140133,5813.9061426437065],
+  [19134.01504140133,5979.506142643706],
+  [19233.31504140133,5813.9061426437065],
+  [19233.31504140133,5979.506142643706],
+  [19332.61504140133,6145.106142643705],
+  [19332.61504140133,6310.706142643705],
+  [19233.31504140133,6310.706142643705],
+  [19233.31504140133,6476.306142643704],
+  [19332.61504140133,6476.306142643704],
+  [19431.915041401327,6641.906142643704],
+  [19332.61504140133,6807.506142643703],
+  [19332.61504140133,6641.906142643704],
+  [19431.915041401327,6476.306142643704],
+  [19431.915041401327,6310.706142643705],
+  [19531.215041401327,6145.106142643705],
+  [19431.915041401327,5979.506142643706],
+  [19431.915041401327,6145.106142643705],
+  [19531.215041401327,5979.506142643706],
+  [19630.515041401326,5813.9061426437065],
+  [19630.515041401326,5979.506142643706],
+  [19729.815041401325,5813.9061426437065],
+  [19829.115041401325,5979.506142643706],
+  [19729.815041401325,5979.506142643706],
+  [19729.815041401325,6145.106142643705],
+  [19729.815041401325,6310.706142643705],
+  [19630.515041401326,6476.306142643704],
+  [19729.815041401325,6476.306142643704],
+  [19630.515041401326,6310.706142643705],
+  [19531.215041401327,6310.706142643705],
+  [19531.215041401327,6476.306142643704],
+  [19630.515041401326,6641.906142643704],
+  [19729.815041401325,6807.506142643703],
+  [19829.115041401325,6973.106142643703],
+  [19928.415041401324,6973.106142643703],
+  [19928.415041401324,7138.706142643702],
+  [20027.715041401323,7138.706142643702],
+  [20027.715041401323,7304.306142643702],
+  [19928.415041401324,7304.306142643702],
+  [19829.115041401325,7304.306142643702],
+  [19829.115041401325,7469.906142643701],
+  [19928.415041401324,7469.906142643701],
+  [19928.415041401324,7635.5061426437005],
+  [19928.415041401324,7801.1061426437],
+  [20027.715041401323,7635.5061426437005],
+  [20027.715041401323,7801.1061426437],
+  [20127.015041401322,7801.1061426437],
+  [20226.31504140132,7801.1061426437],
+  [20325.61504140132,7801.1061426437],
+  [20226.31504140132,7635.5061426437005],
+  [20226.31504140132,7469.906142643701],
+  [20226.31504140132,7304.306142643702],
+  [20127.015041401322,7304.306142643702],
+  [20027.715041401323,7469.906142643701],
+  [20127.015041401322,7469.906142643701],
+  [20127.015041401322,7635.5061426437005],
+  [2748.790306732237,2362.9553147492866],
+  [2848.0903067322365,2528.5553147492865],
+  [2748.790306732237,2694.1553147492864],
+  [2649.490306732237,2859.7553147492863],
+  [2748.790306732237,3025.355314749286],
+  [2848.0903067322365,2859.7553147492863],
+  [2848.0903067322365,2694.1553147492864],
+  [2947.3903067322362,2694.1553147492864],
+  [3046.690306732236,2859.7553147492863],
+  [3145.9903067322357,2694.1553147492864],
+  [3145.9903067322357,2528.5553147492865],
+  [3046.690306732236,2694.1553147492864],
+  [3145.9903067322357,2859.7553147492863],
+  [3046.690306732236,3025.355314749286],
+  [3145.9903067322357,3025.355314749286],
+  [3245.2903067322354,3190.955314749286],
+  [3245.2903067322354,3356.555314749286],
+  [3344.590306732235,3522.155314749286],
+  [3443.890306732235,3356.555314749286],
+  [3543.1903067322346,3356.555314749286],
+  [3642.4903067322343,3190.955314749286],
+  [3741.790306732234,3025.355314749286],
+  [3741.790306732234,2859.7553147492863],
+  [3841.090306732234,3025.355314749286],
+  [3841.090306732234,3190.955314749286],
+  [3741.790306732234,3190.955314749286],
+  [3642.4903067322343,3025.355314749286],
+  [3543.1903067322346,3025.355314749286],
+  [3543.1903067322346,2859.7553147492863],
+  [3443.890306732235,3025.355314749286],
+  [3443.890306732235,3190.955314749286],
+  [3543.1903067322346,3190.955314749286],
+  [3642.4903067322343,3356.555314749286],
+  [3543.1903067322346,3522.155314749286],
+  [3443.890306732235,3687.755314749286],
+  [3443.890306732235,3853.3553147492858],
+  [3344.590306732235,3687.755314749286],
+  [3245.2903067322354,3853.3553147492858],
+  [3245.2903067322354,3687.755314749286],
+  [3145.9903067322357,3687.755314749286],
+  [3046.690306732236,3853.3553147492858],
+  [3145.9903067322357,4018.9553147492857],
+  [3145.9903067322357,3853.3553147492858],
+  [3046.690306732236,3687.755314749286],
+  [3145.9903067322357,3522.155314749286],
+  [3145.9903067322357,3356.555314749286],
+  [3145.9903067322357,3190.955314749286],
+  [3046.690306732236,3190.955314749286],
+  [3046.690306732236,3356.555314749286],
+  [2947.3903067322362,3356.555314749286],
+  [2848.0903067322365,3190.955314749286],
+  [2947.3903067322362,3025.355314749286],
+  [2848.0903067322365,3025.355314749286],
+  [2748.790306732237,2859.7553147492863],
+  [2649.490306732237,2694.1553147492864],
+  [2748.790306732237,2528.5553147492865],
+  [2848.0903067322365,2362.9553147492866],
+  [2748.790306732237,2197.3553147492867],
+  [2649.490306732237,2362.9553147492866],
+  [2649.490306732237,2197.3553147492867],
+  [2550.1903067322373,2362.9553147492866],
+  [2450.8903067322376,2362.9553147492866],
+  [2351.590306732238,2528.5553147492865],
+  [2252.290306732238,2528.5553147492865],
+  [2351.590306732238,2362.9553147492866],
+  [2252.290306732238,2197.3553147492867],
+  [2351.590306732238,2197.3553147492867],
+  [2351.590306732238,2031.7553147492865],
+  [2351.590306732238,1866.1553147492864],
+  [2252.290306732238,1866.1553147492864],
+  [2351.590306732238,1700.5553147492863],
+  [2450.8903067322376,1534.9553147492861],
+  [2351.590306732238,1369.355314749286],
+  [2252.290306732238,1203.7553147492858],
+  [2252.290306732238,1369.355314749286],
+  [2252.290306732238,1534.9553147492861],
+  [2152.9903067322384,1369.355314749286],
+  [2053.6903067322387,1369.355314749286],
+  [1954.3903067322387,1203.7553147492858],
+  [1855.0903067322388,1203.7553147492858],
+  [1755.7903067322388,1038.1553147492857],
+  [1656.4903067322389,1038.1553147492857],
+  [1557.190306732239,872.5553147492857],
+  [1457.890306732239,1038.1553147492857],
+  [1457.890306732239,872.5553147492857],
+  [1457.890306732239,706.9553147492858],
+  [1557.190306732239,706.9553147492858],
+  [1656.4903067322389,872.5553147492857],
+  [1656.4903067322389,706.9553147492858],
+  [1755.7903067322388,706.9553147492858],
+  [1656.4903067322389,541.3553147492859],
+  [1557.190306732239,375.7553147492859],
+  [1656.4903067322389,210.1553147492859],
+  [1755.7903067322388,44.55531474928592],
+  [1656.4903067322389,44.55531474928592],
+  [1557.190306732239,210.1553147492859],
+  [1457.890306732239,210.1553147492859],
+  [1457.890306732239,44.55531474928592],
+  [1358.590306732239,210.1553147492859],
+  [1358.590306732239,375.75531474928584],
+  [1259.290306732239,210.15531474928585],
+  [1259.290306732239,375.75531474928584],
+  [1259.290306732239,541.3553147492859],
+  [1358.590306732239,706.9553147492858],
+  [1358.590306732239,872.5553147492857],
+  [1259.290306732239,706.9553147492858],
+  [1259.290306732239,872.5553147492857],
+  [1259.290306732239,1038.1553147492857],
+  [1358.590306732239,1203.7553147492858],
+  [1358.590306732239,1038.1553147492857],
+  [1457.890306732239,1203.7553147492858],
+  [1557.190306732239,1369.355314749286],
+  [1656.4903067322389,1203.7553147492858],
+  [1557.190306732239,1203.7553147492858],
+  [1557.190306732239,1038.1553147492857],
+  [17254.572515546668,1460.5807801244923],
+  [17353.872515546667,1626.1807801244925],
+  [17453.172515546667,1791.7807801244926],
+  [17552.472515546666,1791.7807801244926],
+  [17453.172515546667,1626.1807801244925],
+  [17353.872515546667,1791.7807801244926],
+  [17453.172515546667,1957.3807801244927],
+  [17353.872515546667,2122.980780124493],
+  [17453.172515546667,2288.580780124493],
+  [17353.872515546667,2454.1807801244927],
+  [17453.172515546667,2619.7807801244926],
+  [17552.472515546666,2619.7807801244926],
+  [17453.172515546667,2785.3807801244925],
+  [17353.872515546667,2619.7807801244926],
+  [17254.572515546668,2454.1807801244927],
+  [17254.572515546668,2288.580780124493],
+  [17353.872515546667,2288.580780124493],
+  [17453.172515546667,2122.980780124493],
+  [17552.472515546666,2288.580780124493],
+  [17552.472515546666,2454.1807801244927],
+  [17453.172515546667,2454.1807801244927],
+  [4447.67624466283,4761.1416826913],
+  [4546.97624466283,4595.541682691301],
+  [4546.97624466283,4429.941682691301],
+  [4447.67624466283,4429.941682691301],
+  [4447.67624466283,4595.541682691301],
+  [4348.37624466283,4595.541682691301],
+  [4249.07624466283,4595.541682691301],
+  [4348.37624466283,4761.1416826913],
+  [4249.07624466283,4761.1416826913],
+  [4348.37624466283,4926.7416826912995],
+  [4348.37624466283,5092.341682691299],
+  [4447.67624466283,5257.941682691298],
+  [4546.97624466283,5257.941682691298],
+  [4646.27624466283,5092.341682691299],
+  [4546.97624466283,5092.341682691299],
+  [4646.27624466283,4926.7416826912995],
+  [4646.27624466283,4761.1416826913],
+  [4546.97624466283,4761.1416826913],
+  [4646.27624466283,4595.541682691301],
+  [4745.5762446628305,4595.541682691301],
+  [4646.27624466283,4429.941682691301],
+  [4745.5762446628305,4429.941682691301],
+  [4844.876244662831,4595.541682691301],
+  [4745.5762446628305,4761.1416826913],
+  [4745.5762446628305,4926.7416826912995],
+  [4844.876244662831,4761.1416826913],
+  [4944.176244662831,4761.1416826913],
+  [5043.476244662831,4926.7416826912995],
+  [5043.476244662831,4761.1416826913],
+  [5142.776244662831,4926.7416826912995],
+  [5142.776244662831,4761.1416826913],
+  [5242.076244662831,4595.541682691301],
+  [5142.776244662831,4595.541682691301],
+  [5242.076244662831,4429.941682691301],
+  [5242.076244662831,4264.341682691302],
+  [5142.776244662831,4429.941682691301],
+  [5043.476244662831,4595.541682691301],
+  [5043.476244662831,4429.941682691301],
+  [5043.476244662831,4264.341682691302],
+  [5142.776244662831,4098.741682691302],
+  [5043.476244662831,4098.741682691302],
+  [4944.176244662831,3933.1416826913023],
+  [4944.176244662831,4098.741682691302],
+  [4944.176244662831,4264.341682691302],
+  [4844.876244662831,4098.741682691302],
+  [4745.5762446628305,4264.341682691302],
+  [4646.27624466283,4098.741682691302],
+  [4546.97624466283,3933.1416826913023],
+  [4447.67624466283,4098.741682691302],
+  [4546.97624466283,4264.341682691302],
+  [4447.67624466283,4264.341682691302],
+  [4546.97624466283,4098.741682691302],
+  [4646.27624466283,3933.1416826913023],
+  [4546.97624466283,3767.5416826913024],
+  [4447.67624466283,3601.9416826913025],
+  [4447.67624466283,3767.5416826913024],
+  [4348.37624466283,3767.5416826913024],
+  [4348.37624466283,3933.1416826913023],
+  [4249.07624466283,3767.5416826913024],
+  [4249.07624466283,3933.1416826913023],
+  [4149.776244662829,3933.1416826913023],
+  [4050.4762446628297,4098.741682691302],
+  [4050.4762446628297,3933.1416826913023],
+  [3951.17624466283,3933.1416826913023],
+  [3951.17624466283,4098.741682691302],
+  [3851.8762446628302,4264.341682691302],
+  [3851.8762446628302,4098.741682691302],
+  [3752.5762446628305,4098.741682691302],
+  [3653.276244662831,4264.341682691302],
+  [3553.976244662831,4429.941682691301],
+  [3553.976244662831,4595.541682691301],
+  [3454.6762446628313,4429.941682691301],
+  [3553.976244662831,4264.341682691302],
+  [3653.276244662831,4429.941682691301],
+  [3752.5762446628305,4264.341682691302],
+  [3752.5762446628305,4429.941682691301],
+  [3851.8762446628302,4595.541682691301],
+  [3851.8762446628302,4429.941682691301],
+  [3951.17624466283,4429.941682691301],
+  [4050.4762446628297,4264.341682691302],
+  [4149.776244662829,4098.741682691302],
+  [4249.07624466283,4264.341682691302],
+  [4348.37624466283,4098.741682691302],
+  [4447.67624466283,3933.1416826913023],
+  [9574.088902135607,7352.26293905581],
+  [9474.788902135606,7352.26293905581],
+  [9375.488902135605,7186.662939055811],
+  [9474.788902135606,7021.0629390558115],
+  [9574.088902135607,7021.0629390558115],
+  [9474.788902135606,7186.662939055811],
+  [9574.088902135607,7186.662939055811],
+  [9673.388902135608,7021.0629390558115],
+  [9673.388902135608,6855.462939055812],
+  [9772.68890213561,6689.862939055813],
+  [9673.388902135608,6689.862939055813],
+  [9772.68890213561,6524.262939055813],
+  [9871.98890213561,6358.662939055814],
+  [9971.288902135611,6524.262939055813],
+  [10070.588902135612,6358.662939055814],
+  [10070.588902135612,6193.062939055814],
+  [9971.288902135611,6027.462939055815],
+  [9971.288902135611,5861.862939055815],
+  [9871.98890213561,5861.862939055815],
+  [9871.98890213561,5696.262939055816],
+  [9971.288902135611,5530.662939055816],
+  [10070.588902135612,5530.662939055816],
+  [10070.588902135612,5696.262939055816],
+  [10169.888902135614,5861.862939055815],
+  [10169.888902135614,5696.262939055816],
+  [10070.588902135612,5861.862939055815],
+  [10169.888902135614,6027.462939055815],
+  [10169.888902135614,6193.062939055814],
+  [10269.188902135615,6027.462939055815],
+  [10269.188902135615,5861.862939055815],
+  [10368.488902135616,6027.462939055815],
+  [10269.188902135615,6193.062939055814],
+  [10269.188902135615,6358.662939055814],
+  [10169.888902135614,6358.662939055814],
+  [10070.588902135612,6524.262939055813],
+  [10070.588902135612,6689.862939055813],
+  [9971.288902135611,6855.462939055812],
+  [9971.288902135611,7021.0629390558115],
+  [10070.588902135612,7186.662939055811],
+  [10169.888902135614,7186.662939055811],
+  [10269.188902135615,7186.662939055811],
+  [10169.888902135614,7352.26293905581],
+  [10070.588902135612,7352.26293905581],
+  [10169.888902135614,7517.86293905581],
+  [10169.888902135614,7683.462939055809],
+  [10269.188902135615,7517.86293905581],
+  [10368.488902135616,7683.462939055809],
+  [10467.788902135617,7683.462939055809],
+  [10368.488902135616,7517.86293905581],
+  [10269.188902135615,7352.26293905581],
+  [10368.488902135616,7352.26293905581],
+  [10368.488902135616,7186.662939055811],
+  [10368.488902135616,7021.0629390558115],
+  [10368.488902135616,6855.462939055812],
+  [10269.188902135615,6855.462939055812],
+  [10169.888902135614,6855.462939055812],
+  [10169.888902135614,7021.0629390558115],
+  [10070.588902135612,7021.0629390558115],
+  [10070.588902135612,6855.462939055812],
+  [10169.888902135614,6689.862939055813],
+  [10269.188902135615,6689.862939055813],
+  [10169.888902135614,6524.262939055813],
+  [10269.188902135615,6524.262939055813],
+  [10368.488902135616,6524.262939055813],
+  [10368.488902135616,6358.662939055814],
+  [10467.788902135617,6358.662939055814],
+  [10467.788902135617,6193.062939055814],
+  [10567.088902135618,6358.662939055814],
+  [10567.088902135618,6193.062939055814],
+  [10666.388902135619,6193.062939055814],
+  [10666.388902135619,6358.662939055814],
+  [10567.088902135618,6524.262939055813],
+  [10467.788902135617,6524.262939055813],
+  [10567.088902135618,6689.862939055813],
+  [10467.788902135617,6855.462939055812],
+  [10567.088902135618,7021.0629390558115],
+  [10467.788902135617,7021.0629390558115],
+  [10567.088902135618,6855.462939055812],
+  [10467.788902135617,6689.862939055813],
+  [10368.488902135616,6689.862939055813],
+  [1073.6944354374714,1154.3681204032646],
+  [974.3944354374713,1319.9681204032647],
+  [875.0944354374712,1319.9681204032647],
+  [775.7944354374712,1154.3681204032646],
+  [775.7944354374712,988.7681204032646],
+  [875.0944354374712,823.1681204032647],
+  [875.0944354374712,657.5681204032647],
+  [775.7944354374712,823.1681204032647],
+  [676.4944354374711,657.5681204032647],
+  [676.4944354374711,491.9681204032648],
+  [775.7944354374712,657.5681204032647],
+  [676.4944354374711,823.1681204032647],
+  [676.4944354374711,988.7681204032646],
+  [577.194435437471,823.1681204032647],
+  [577.194435437471,988.7681204032646],
+  [577.194435437471,1154.3681204032646],
+  [676.4944354374711,1319.9681204032647],
+  [577.194435437471,1319.9681204032647],
+  [477.89443543747103,1319.9681204032647],
+  [577.194435437471,1485.5681204032649],
+  [477.89443543747103,1651.168120403265],
+  [577.194435437471,1816.7681204032651],
+  [477.89443543747103,1816.7681204032651],
+  [378.5944354374711,1982.3681204032653],
+  [378.5944354374711,2147.9681204032654],
+  [279.2944354374711,2313.5681204032653],
+  [179.99443543747114,2147.9681204032654],
+  [80.69443543747114,2313.5681204032653],
+  [80.69443543747114,2479.168120403265],
+  [179.9944354374711,2644.768120403265],
+  [179.9944354374711,2479.168120403265],
+  [179.9944354374711,2313.5681204032653],
+  [80.69443543747111,2147.9681204032654],
+  [80.69443543747111,1982.3681204032653],
+  [179.9944354374711,1982.3681204032653],
+  [179.9944354374711,1816.7681204032651],
+  [80.69443543747111,1816.7681204032651],
+  [179.9944354374711,1651.168120403265],
+  [80.69443543747111,1485.5681204032649],
+  [80.69443543747111,1319.9681204032647],
+  [179.9944354374711,1154.3681204032646],
+  [80.69443543747111,1154.3681204032646],
+  [179.9944354374711,988.7681204032646],
+  [279.2944354374711,823.1681204032647],
+  [378.5944354374711,657.5681204032647],
+  [378.5944354374711,823.1681204032647],
+  [477.89443543747103,823.1681204032647],
+  [477.89443543747103,657.5681204032647],
+  [378.5944354374711,491.9681204032648],
+  [477.89443543747103,326.3681204032648],
+  [477.89443543747103,160.76812040326482],
+  [378.5944354374711,160.76812040326482],
+  [279.2944354374711,326.3681204032648],
+  [179.99443543747114,491.9681204032648],
+  [179.99443543747114,326.3681204032648],
+  [279.2944354374711,491.9681204032648],
+  [279.2944354374711,657.5681204032647],
+  [179.99443543747114,823.1681204032647],
+  [279.2944354374711,988.7681204032646],
+  [279.2944354374711,1154.3681204032646],
+  [378.5944354374711,1319.9681204032647],
+  [477.89443543747103,1485.5681204032649],
+  [577.194435437471,1651.168120403265],
+  [676.4944354374711,1651.168120403265],
+  [775.7944354374712,1816.7681204032651],
+  [676.4944354374711,1816.7681204032651],
+  [775.7944354374712,1651.168120403265],
+  [875.0944354374712,1651.168120403265],
+  [974.3944354374713,1651.168120403265],
+  [875.0944354374712,1485.5681204032649],
+  [775.7944354374712,1485.5681204032649],
+  [676.4944354374711,1485.5681204032649],
+  [775.7944354374712,1319.9681204032647],
+  [676.4944354374711,1154.3681204032646],
+  [3138.413562431697,2355.845602060523],
+  [3039.113562431697,2521.445602060523],
+  [3039.113562431697,2355.845602060523],
+  [3039.113562431697,2190.245602060523],
+  [3138.413562431697,2024.645602060523],
+  [3237.7135624316966,1859.045602060523],
+  [3237.7135624316966,2024.645602060523],
+  [3337.0135624316963,1859.045602060523],
+  [3337.0135624316963,1693.4456020605228],
+  [3436.313562431696,1527.8456020605227],
+  [3535.6135624316958,1693.4456020605228],
+  [3535.6135624316958,1859.045602060523],
+  [3634.9135624316955,2024.645602060523],
+  [3734.213562431695,2190.245602060523],
+  [3634.9135624316955,2190.245602060523],
+  [3535.6135624316958,2190.245602060523],
+  [3535.6135624316958,2355.845602060523],
+  [3535.6135624316958,2521.445602060523],
+  [3436.313562431696,2687.045602060523],
+  [3436.313562431696,2852.645602060523],
+  [3535.6135624316958,2687.045602060523],
+  [3634.9135624316955,2521.445602060523],
+  [3634.9135624316955,2355.845602060523],
+  [3734.213562431695,2355.845602060523],
+  [3833.513562431695,2190.245602060523],
+  [3932.8135624316947,2024.645602060523],
+  [3833.513562431695,1859.045602060523],
+  [3833.513562431695,1693.4456020605228],
+  [3734.213562431695,1859.045602060523],
+  [3734.213562431695,1693.4456020605228],
+  [3734.213562431695,1527.8456020605227],
+  [3634.9135624316955,1527.8456020605227],
+  [3634.9135624316955,1693.4456020605228],
+  [3535.6135624316958,1527.8456020605227],
+  [3634.9135624316955,1362.2456020605225],
+  [3535.6135624316958,1362.2456020605225],
+  [3436.313562431696,1196.6456020605224],
+  [3535.6135624316958,1196.6456020605224],
+  [3535.6135624316958,1031.0456020605222],
+  [3436.313562431696,1031.0456020605222],
+  [3535.6135624316958,865.4456020605222],
+  [3436.313562431696,865.4456020605222],
+  [3535.6135624316958,699.8456020605223],
+  [3634.9135624316955,699.8456020605223],
+  [3535.6135624316958,534.2456020605224],
+  [3436.313562431696,368.64560206052244],
+  [3436.313562431696,203.04560206052244],
+  [3337.0135624316963,37.445602060522454],
+  [3436.313562431696,37.445602060522454],
+  [3337.0135624316963,203.04560206052244],
+  [3237.7135624316966,37.445602060522454],
+  [3138.413562431697,37.445602060522454],
+  [3237.7135624316966,203.04560206052244],
+  [3337.0135624316963,368.6456020605224],
+  [3436.313562431696,534.2456020605224],
+  [3337.0135624316963,699.8456020605223],
+  [3237.7135624316966,534.2456020605224],
+  [3337.0135624316963,534.2456020605224],
+  [3436.313562431696,699.8456020605223],
+  [3337.0135624316963,865.4456020605222],
+  [3237.7135624316966,865.4456020605222],
+  [3337.0135624316963,1031.0456020605222],
+  [3237.7135624316966,1196.6456020605224],
+  [3138.413562431697,1362.2456020605225],
+  [3039.113562431697,1527.8456020605227],
+  [3138.413562431697,1527.8456020605227],
+  [3039.113562431697,1693.4456020605228],
+  [2939.8135624316974,1527.8456020605227],
+  [2840.5135624316977,1362.2456020605225],
+  [2840.5135624316977,1527.8456020605227],
+  [2840.5135624316977,1693.4456020605228],
+  [2939.8135624316974,1859.045602060523],
+  [2840.5135624316977,2024.645602060523],
+  [2840.5135624316977,1859.045602060523],
+  [2939.8135624316974,1693.4456020605228],
+  [3039.113562431697,1859.045602060523],
+  [3039.113562431697,2024.645602060523],
+  [2939.8135624316974,2190.245602060523],
+  [2939.8135624316974,2024.645602060523],
+  [16388.412117675925,1839.818884803299],
+  [16289.112117675924,1839.818884803299],
+  [16388.412117675925,1674.2188848032988],
+  [16487.712117675925,1508.6188848032987],
+  [16487.712117675925,1674.2188848032988],
+  [16388.412117675925,1508.6188848032987],
+  [16289.112117675924,1343.0188848032985],
+  [16289.112117675924,1508.6188848032987],
+  [16189.812117675923,1674.2188848032988],
+  [16090.512117675922,1839.818884803299],
+  [16090.512117675922,2005.418884803299],
+  [15991.212117675921,2171.018884803299],
+  [16090.512117675922,2336.618884803299],
+  [16090.512117675922,2502.218884803299],
+  [16090.512117675922,2667.8188848032987],
+  [15991.212117675921,2833.4188848032986],
+  [15991.212117675921,2999.0188848032985],
+  [15891.91211767592,3164.6188848032984],
+  [15891.91211767592,3330.2188848032984],
+  [15991.212117675921,3330.2188848032984],
+  [16090.512117675922,3330.2188848032984],
+  [16189.812117675923,3495.8188848032983],
+  [16289.112117675924,3495.8188848032983],
+  [16189.812117675923,3330.2188848032984],
+  [16189.812117675923,3164.6188848032984],
+  [16289.112117675924,3164.6188848032984],
+  [16388.412117675925,3164.6188848032984],
+  [16388.412117675925,3330.2188848032984],
+  [16487.712117675925,3330.2188848032984],
+  [16587.012117675924,3495.8188848032983],
+  [16587.012117675924,3661.418884803298],
+  [16686.312117675923,3661.418884803298],
+  [16785.612117675922,3661.418884803298],
+  [16884.91211767592,3661.418884803298],
+  [16984.21211767592,3661.418884803298],
+  [16884.91211767592,3827.018884803298],
+  [16884.91211767592,3992.618884803298],
+  [16984.21211767592,3827.018884803298],
+  [17083.51211767592,3661.418884803298],
+  [17182.81211767592,3495.8188848032983],
+  [17182.81211767592,3330.2188848032984],
+  [17282.11211767592,3164.6188848032984],
+  [17282.11211767592,3330.2188848032984],
+  [17182.81211767592,3164.6188848032984],
+  [17083.51211767592,3164.6188848032984],
+  [16984.21211767592,3330.2188848032984],
+  [16984.21211767592,3495.8188848032983],
+  [17083.51211767592,3330.2188848032984],
+  [16984.21211767592,3164.6188848032984],
+  [16984.21211767592,2999.0188848032985],
+  [17083.51211767592,2833.4188848032986],
+  [17083.51211767592,2667.8188848032987],
+  [17182.81211767592,2667.8188848032987],
+  [17182.81211767592,2833.4188848032986],
+  [17083.51211767592,2999.0188848032985],
+  [16984.21211767592,2833.4188848032986],
+  [16884.91211767592,2833.4188848032986],
+  [16884.91211767592,2999.0188848032985],
+  [16785.612117675922,2999.0188848032985],
+  [16884.91211767592,3164.6188848032984],
+  [16785.612117675922,3164.6188848032984],
+  [16686.312117675923,3164.6188848032984],
+  [16587.012117675924,3164.6188848032984],
+  [16587.012117675924,2999.0188848032985],
+  [16487.712117675925,3164.6188848032984],
+  [16587.012117675924,3330.2188848032984],
+  [16686.312117675923,3495.8188848032983],
+  [16686.312117675923,3330.2188848032984],
+  [16785.612117675922,3330.2188848032984],
+  [16884.91211767592,3495.8188848032983],
+  [16785.612117675922,3495.8188848032983],
+  [16884.91211767592,3330.2188848032984],
+  [1272.175991128079,3842.7700224365044],
+  [1371.475991128079,3842.7700224365044],
+  [1272.175991128079,3677.1700224365045],
+  [1172.875991128079,3511.5700224365046],
+  [1272.175991128079,3511.5700224365046],
+  [1172.875991128079,3345.9700224365047],
+  [1073.575991128079,3180.3700224365048],
+  [1073.575991128079,3014.770022436505],
+  [974.275991128079,3014.770022436505],
+  [874.9759911280789,3014.770022436505],
+  [775.6759911280789,2849.170022436505],
+  [775.6759911280789,3014.770022436505],
+  [775.6759911280789,3180.3700224365048],
+  [676.3759911280788,3345.9700224365047],
+  [676.3759911280788,3511.5700224365046],
+  [775.6759911280789,3677.1700224365045],
+  [676.3759911280788,3842.7700224365044],
+  [577.0759911280787,3842.7700224365044],
+  [577.0759911280787,3677.1700224365045],
+  [676.3759911280788,3677.1700224365045],
+  [775.6759911280789,3511.5700224365046],
+  [775.6759911280789,3345.9700224365047],
+  [874.9759911280789,3345.9700224365047],
+  [874.9759911280789,3180.3700224365048],
+  [974.275991128079,3180.3700224365048],
+  [974.275991128079,3345.9700224365047],
+  [1073.575991128079,3511.5700224365046],
+  [1073.575991128079,3677.1700224365045],
+  [1172.875991128079,3677.1700224365045],
+  [1172.875991128079,3842.7700224365044],
+  [1073.575991128079,3842.7700224365044],
+  [1172.875991128079,4008.3700224365043],
+  [1073.575991128079,4008.3700224365043],
+  [974.275991128079,3842.7700224365044],
+  [974.275991128079,4008.3700224365043],
+  [874.9759911280789,4008.3700224365043],
+  [775.6759911280789,4008.3700224365043],
+  [874.9759911280789,3842.7700224365044],
+  [974.275991128079,3677.1700224365045],
+  [974.275991128079,3511.5700224365046],
+  [1073.575991128079,3345.9700224365047],
+  [1172.875991128079,3180.3700224365048],
+  [1272.175991128079,3180.3700224365048],
+  [1272.175991128079,3345.9700224365047],
+  [1371.475991128079,3180.3700224365048],
+  [1470.7759911280789,3345.9700224365047],
+  [1371.475991128079,3345.9700224365047],
+  [1371.475991128079,3511.5700224365046],
+  [1470.7759911280789,3511.5700224365046],
+  [1570.0759911280788,3677.1700224365045],
+  [1470.7759911280789,3677.1700224365045],
+  [1570.0759911280788,3511.5700224365046],
+  [1669.3759911280788,3511.5700224365046],
+  [1669.3759911280788,3677.1700224365045],
+  [1768.6759911280787,3842.7700224365044],
+  [1669.3759911280788,3842.7700224365044],
+  [1768.6759911280787,4008.3700224365043],
+  [1867.9759911280787,3842.7700224365044],
+  [1967.2759911280787,3677.1700224365045],
+  [2066.5759911280784,3842.7700224365044],
+  [2165.875991128078,3677.1700224365045],
+  [2066.5759911280784,3511.5700224365046],
+  [2165.875991128078,3511.5700224365046],
+  [2066.5759911280784,3677.1700224365045],
+  [2165.875991128078,3842.7700224365044],
+  [2265.175991128078,4008.3700224365043],
+  [2364.4759911280776,4008.3700224365043],
+  [2265.175991128078,3842.7700224365044],
+  [2364.4759911280776,3677.1700224365045],
+  [2463.7759911280773,3842.7700224365044],
+  [2463.7759911280773,4008.3700224365043],
+  [2364.4759911280776,3842.7700224365044],
+  [6853.940039224797,6050.837897021371],
+  [6953.240039224797,6050.837897021371],
+  [7052.5400392247975,5885.237897021371],
+  [7052.5400392247975,5719.637897021372],
+  [7151.840039224798,5885.237897021371],
+  [7052.5400392247975,6050.837897021371],
+  [7052.5400392247975,6216.43789702137],
+  [7052.5400392247975,6382.03789702137],
+  [6953.240039224797,6382.03789702137],
+  [6953.240039224797,6216.43789702137],
+  [6853.940039224797,6216.43789702137],
+  [6853.940039224797,6382.03789702137],
+  [6754.640039224797,6216.43789702137],
+  [6754.640039224797,6382.03789702137],
+  [6754.640039224797,6547.637897021369],
+  [6754.640039224797,6713.237897021369],
+  [6655.340039224797,6713.237897021369],
+  [6754.640039224797,6878.837897021368],
+  [6853.940039224797,6713.237897021369],
+  [6853.940039224797,6878.837897021368],
+  [6953.240039224797,6713.237897021369],
+  [7052.5400392247975,6547.637897021369],
+  [7151.840039224798,6713.237897021369],
+  [7151.840039224798,6547.637897021369],
+  [7151.840039224798,6382.03789702137],
+  [7251.140039224798,6547.637897021369],
+  [7251.140039224798,6713.237897021369],
+  [7350.440039224798,6878.837897021368],
+  [7449.740039224798,6878.837897021368],
+  [7449.740039224798,6713.237897021369],
+  [7549.040039224798,6547.637897021369],
+  [7449.740039224798,6382.03789702137],
+  [7449.740039224798,6216.43789702137],
+  [7549.040039224798,6050.837897021371],
+  [7648.340039224799,6216.43789702137],
+  [7549.040039224798,6382.03789702137],
+  [7648.340039224799,6382.03789702137],
+  [7747.640039224799,6216.43789702137],
+  [7846.940039224799,6382.03789702137],
+  [7946.240039224799,6382.03789702137],
+  [7946.240039224799,6547.637897021369],
+  [7846.940039224799,6713.237897021369],
+  [7946.240039224799,6713.237897021369],
+  [8045.540039224799,6547.637897021369],
+  [8045.540039224799,6713.237897021369],
+  [7946.240039224799,6878.837897021368],
+  [7946.240039224799,7044.4378970213675],
+  [8045.540039224799,7210.037897021367],
+  [8144.8400392247995,7375.637897021366],
+  [8144.8400392247995,7541.237897021366],
+  [8045.540039224799,7375.637897021366],
+  [8144.8400392247995,7210.037897021367],
+  [8045.540039224799,7044.4378970213675],
+  [7946.240039224799,7210.037897021367],
+  [7846.940039224799,7210.037897021367],
+  [7946.240039224799,7375.637897021366],
+  [8045.540039224799,7541.237897021366],
+  [8144.8400392247995,7706.837897021365],
+  [8244.1400392248,7541.237897021366],
+  [8343.4400392248,7541.237897021366],
+  [8343.4400392248,7706.837897021365],
+  [8244.1400392248,7706.837897021365],
+  [4735.523842661975,3503.497768214323],
+  [4636.223842661975,3337.897768214323],
+  [4536.923842661975,3337.897768214323],
+  [4437.623842661975,3172.2977682143232],
+  [4338.323842661975,3172.2977682143232],
+  [4239.023842661974,3172.2977682143232],
+  [4338.323842661975,3006.6977682143233],
+  [4437.623842661975,2841.0977682143234],
+  [4338.323842661975,2675.4977682143235],
+  [4338.323842661975,2509.8977682143236],
+  [4239.023842661974,2675.4977682143235],
+  [4139.723842661974,2509.8977682143236],
+  [4040.4238426619745,2344.2977682143237],
+  [4139.723842661974,2178.697768214324],
+  [4239.023842661974,2178.697768214324],
+  [4139.723842661974,2344.2977682143237],
+  [4040.4238426619745,2178.697768214324],
+  [4139.723842661974,2013.0977682143237],
+  [4139.723842661974,1847.4977682143235],
+  [4239.023842661974,2013.0977682143237],
+  [4239.023842661974,1847.4977682143235],
+  [4338.323842661975,1847.4977682143235],
+  [4437.623842661975,1847.4977682143235],
+  [4536.923842661975,1681.8977682143234],
+  [4437.623842661975,1516.2977682143232],
+  [4536.923842661975,1516.2977682143232],
+  [4536.923842661975,1350.697768214323],
+  [4437.623842661975,1350.697768214323],
+  [4536.923842661975,1185.097768214323],
+  [4636.223842661975,1019.497768214323],
+  [4536.923842661975,853.897768214323],
+  [4636.223842661975,853.897768214323],
+  [4735.523842661975,688.2977682143231],
+  [4636.223842661975,522.6977682143232],
+  [4636.223842661975,357.09776821432325],
+  [4735.523842661975,357.09776821432325],
+  [4735.523842661975,522.6977682143232],
+  [4636.223842661975,688.2977682143231],
+  [4735.523842661975,853.897768214323],
+  [4834.8238426619755,853.897768214323],
+  [4735.523842661975,1019.497768214323],
+  [4735.523842661975,1185.097768214323],
+  [4735.523842661975,1350.697768214323],
+  [4834.8238426619755,1516.2977682143232],
+  [4735.523842661975,1516.2977682143232],
+  [4834.8238426619755,1350.697768214323],
+  [4834.8238426619755,1185.097768214323],
+  [4934.123842661976,1350.697768214323],
+  [5033.423842661976,1185.097768214323],
+  [5033.423842661976,1019.497768214323],
+  [5033.423842661976,853.897768214323],
+  [4934.123842661976,853.897768214323],
+  [4934.123842661976,1019.497768214323],
+  [4834.8238426619755,1019.497768214323],
+  [4934.123842661976,1185.097768214323],
+  [5033.423842661976,1350.697768214323],
+  [5132.723842661976,1350.697768214323],
+  [5132.723842661976,1185.097768214323],
+  [5232.023842661976,1019.497768214323],
+  [5232.023842661976,1185.097768214323],
+  [5331.323842661976,1019.497768214323],
+  [5430.623842661977,1019.497768214323],
+  [5529.923842661977,1185.097768214323],
+  [5430.623842661977,1350.697768214323],
+  [5430.623842661977,1516.2977682143232],
+  [5529.923842661977,1350.697768214323],
+  [5629.223842661977,1350.697768214323],
+  [5728.523842661977,1350.697768214323],
+  [5728.523842661977,1516.2977682143232],
+  [5728.523842661977,1681.8977682143234],
+  [5629.223842661977,1516.2977682143232],
+  [5529.923842661977,1516.2977682143232],
+  [5629.223842661977,1681.8977682143234],
+  [5529.923842661977,1681.8977682143234],
+  [5430.623842661977,1847.4977682143235],
+  [5331.323842661976,1847.4977682143235],
+  [5331.323842661976,2013.0977682143237],
+  [5232.023842661976,2178.697768214324],
+  [5132.723842661976,2013.0977682143237],
+  [5132.723842661976,2178.697768214324],
+  [5232.023842661976,2013.0977682143237],
+  [5232.023842661976,1847.4977682143235],
+  [5232.023842661976,1681.8977682143234],
+  [5331.323842661976,1681.8977682143234],
+  [5331.323842661976,1516.2977682143232],
+  [5331.323842661976,1350.697768214323],
+  [5232.023842661976,1350.697768214323],
+  [5232.023842661976,1516.2977682143232],
+  [5132.723842661976,1516.2977682143232],
+  [5132.723842661976,1681.8977682143234],
+  [5033.423842661976,1847.4977682143235],
+  [5132.723842661976,1847.4977682143235],
+  [5033.423842661976,2013.0977682143237],
+  [4934.123842661976,2178.697768214324],
+  [5033.423842661976,2344.2977682143237],
+  [4934.123842661976,2344.2977682143237],
+  [4834.8238426619755,2178.697768214324],
+  [4834.8238426619755,2344.2977682143237],
+  [4735.523842661975,2344.2977682143237],
+  [4636.223842661975,2344.2977682143237],
+  [4536.923842661975,2178.697768214324],
+  [4437.623842661975,2013.0977682143237],
+  [4338.323842661975,2178.697768214324],
+  [4437.623842661975,2344.2977682143237],
+  [4536.923842661975,2509.8977682143236],
+  [4636.223842661975,2675.4977682143235],
+  [4636.223842661975,2509.8977682143236],
+  [4536.923842661975,2675.4977682143235],
+  [4636.223842661975,2841.0977682143234],
+  [4536.923842661975,2841.0977682143234],
+  [4636.223842661975,3006.6977682143233],
+  [4735.523842661975,3172.2977682143232],
+  [4834.8238426619755,3006.6977682143233],
+  [4735.523842661975,2841.0977682143234],
+  [4735.523842661975,3006.6977682143233],
+  [4636.223842661975,3172.2977682143232],
+  [4735.523842661975,3337.897768214323],
+  [4834.8238426619755,3503.497768214323],
+  [4735.523842661975,3669.097768214323],
+  [4834.8238426619755,3834.697768214323],
+  [4834.8238426619755,3669.097768214323],
+  [4934.123842661976,3503.497768214323],
+  [5033.423842661976,3503.497768214323],
+  [5033.423842661976,3337.897768214323],
+  [4934.123842661976,3337.897768214323],
+  [4834.8238426619755,3172.2977682143232],
+  [4834.8238426619755,3337.897768214323],
+  [4934.123842661976,3172.2977682143232],
+  [5033.423842661976,3006.6977682143233],
+  [5132.723842661976,2841.0977682143234],
+  [5132.723842661976,3006.6977682143233],
+  [5232.023842661976,3172.2977682143232],
+  [5232.023842661976,3337.897768214323],
+  [5132.723842661976,3337.897768214323],
+  [5232.023842661976,3503.497768214323],
+  [5331.323842661976,3337.897768214323],
+  [5331.323842661976,3503.497768214323],
+  [5430.623842661977,3669.097768214323],
+  [5331.323842661976,3669.097768214323],
+  [5430.623842661977,3503.497768214323],
+  [5430.623842661977,3337.897768214323],
+  [5529.923842661977,3172.2977682143232],
+  [5529.923842661977,3337.897768214323],
+  [5629.223842661977,3337.897768214323],
+  [5728.523842661977,3337.897768214323],
+  [5728.523842661977,3503.497768214323],
+  [5827.823842661977,3503.497768214323],
+  [5927.1238426619775,3669.097768214323],
+  [6026.423842661978,3669.097768214323],
+  [6125.723842661978,3503.497768214323],
+  [6125.723842661978,3669.097768214323],
+  [6225.023842661978,3503.497768214323],
+  [6225.023842661978,3337.897768214323],
+  [6324.323842661978,3337.897768214323],
+  [6423.623842661978,3503.497768214323],
+  [6324.323842661978,3669.097768214323],
+  [6225.023842661978,3669.097768214323],
+  [6324.323842661978,3834.697768214323],
+  [6423.623842661978,3834.697768214323],
+  [6324.323842661978,4000.297768214323],
+  [6225.023842661978,3834.697768214323],
+  [6125.723842661978,3834.697768214323],
+  [6125.723842661978,4000.297768214323],
+  [6225.023842661978,4000.297768214323],
+  [6225.023842661978,4165.897768214322],
+  [6225.023842661978,4331.497768214322],
+  [6125.723842661978,4165.897768214322],
+  [6026.423842661978,4000.2977682143223],
+  [5927.1238426619775,4165.897768214322],
+  [6026.423842661978,4331.497768214322],
+  [6026.423842661978,4497.097768214321],
+  [5927.1238426619775,4497.097768214321],
+  [5827.823842661977,4662.697768214321],
+  [5728.523842661977,4828.29776821432],
+  [5827.823842661977,4828.29776821432],
+  [5927.1238426619775,4828.29776821432],
+  [5927.1238426619775,4662.697768214321],
+  [5827.823842661977,4497.097768214321],
+  [5927.1238426619775,4331.497768214322],
+  [5827.823842661977,4165.897768214322],
+  [5728.523842661977,4331.497768214322],
+  [5728.523842661977,4165.897768214322],
+  [5629.223842661977,4000.2977682143223],
+  [5629.223842661977,3834.6977682143224],
+  [5529.923842661977,3669.0977682143225],
+  [5629.223842661977,3503.4977682143226],
+  [5728.523842661977,3669.0977682143225],
+  [5827.823842661977,3669.0977682143225],
+  [5927.1238426619775,3834.6977682143224],
+  [5927.1238426619775,4000.2977682143223],
+  [6026.423842661978,4165.897768214322],
+  [6125.723842661978,4331.497768214322],
+  [6225.023842661978,4497.097768214321],
+  [6225.023842661978,4662.697768214321],
+  [6324.323842661978,4662.697768214321],
+  [6225.023842661978,4828.29776821432],
+  [6324.323842661978,4828.29776821432],
+  [6423.623842661978,4828.29776821432],
+  [6324.323842661978,4993.8977682143195],
+  [6225.023842661978,5159.497768214319],
+  [6125.723842661978,5159.497768214319],
+  [6026.423842661978,5325.097768214318],
+  [5927.1238426619775,5490.697768214318],
+  [6026.423842661978,5656.297768214317],
+  [5927.1238426619775,5821.897768214317],
+  [5927.1238426619775,5987.497768214316],
+  [6026.423842661978,5987.497768214316],
+  [6026.423842661978,5821.897768214317],
+  [5927.1238426619775,5656.297768214317],
+  [5827.823842661977,5656.297768214317],
+  [5827.823842661977,5490.697768214318],
+  [5728.523842661977,5490.697768214318],
+  [5629.223842661977,5325.097768214318],
+  [5629.223842661977,5159.497768214319],
+  [5529.923842661977,4993.8977682143195],
+  [5529.923842661977,5159.497768214319],
+  [5629.223842661977,4993.8977682143195],
+  [5629.223842661977,4828.29776821432],
+  [5529.923842661977,4662.697768214321],
+  [5430.623842661977,4828.29776821432],
+  [5529.923842661977,4828.29776821432],
+  [5629.223842661977,4662.697768214321],
+  [5728.523842661977,4662.697768214321],
+  [5629.223842661977,4497.097768214321],
+  [5728.523842661977,4497.097768214321],
+  [5827.823842661977,4331.497768214322],
+  [10216.161365168813,2951.605409896135],
+  [10116.861365168812,2951.605409896135],
+  [10017.56136516881,3117.205409896135],
+  [9918.26136516881,3117.205409896135],
+  [9818.961365168809,3117.205409896135],
+  [9719.661365168808,3282.8054098961347],
+  [9620.361365168807,3282.8054098961347],
+  [9620.361365168807,3117.205409896135],
+  [9521.061365168805,2951.605409896135],
+  [9521.061365168805,2786.005409896135],
+  [9620.361365168807,2786.005409896135],
+  [9719.661365168808,2786.005409896135],
+  [9818.961365168809,2620.405409896135],
+  [9918.26136516881,2786.005409896135],
+  [9818.961365168809,2951.605409896135],
+  [9818.961365168809,2786.005409896135],
+  [9719.661365168808,2620.405409896135],
+  [9719.661365168808,2454.805409896135],
+  [9620.361365168807,2289.2054098961353],
+  [9521.061365168805,2123.6054098961354],
+  [9620.361365168807,1958.0054098961352],
+  [9719.661365168808,2123.6054098961354],
+  [9818.961365168809,2289.2054098961353],
+  [9818.961365168809,2123.6054098961354],
+  [9818.961365168809,1958.0054098961352],
+  [9719.661365168808,1958.0054098961352],
+  [9620.361365168807,1792.405409896135],
+  [9620.361365168807,1626.805409896135],
+  [9521.061365168805,1461.2054098961348],
+  [9421.761365168804,1295.6054098961347],
+  [9521.061365168805,1130.0054098961346],
+  [9521.061365168805,964.4054098961345],
+  [9421.761365168804,964.4054098961345],
+  [9521.061365168805,798.8054098961346],
+  [9620.361365168807,798.8054098961346],
+  [9620.361365168807,964.4054098961345],
+  [9620.361365168807,1130.0054098961346],
+  [9620.361365168807,1295.6054098961347],
+  [9620.361365168807,1461.2054098961348],
+  [9719.661365168808,1295.6054098961347],
+  [9818.961365168809,1130.0054098961346],
+  [9918.26136516881,964.4054098961345],
+  [9818.961365168809,964.4054098961345],
+  [9918.26136516881,798.8054098961346],
+  [10017.56136516881,633.2054098961347],
+  [9918.26136516881,467.60540989613474],
+  [9918.26136516881,302.0054098961348],
+  [10017.56136516881,302.0054098961348],
+  [10116.861365168812,136.40540989613478],
+  [10116.861365168812,302.0054098961348],
+  [10116.861365168812,467.60540989613474],
+  [10116.861365168812,633.2054098961347],
+  [10216.161365168813,633.2054098961347],
+  [10216.161365168813,798.8054098961346],
+  [10315.461365168814,633.2054098961347],
+  [10315.461365168814,798.8054098961346],
+  [10414.761365168815,798.8054098961346],
+  [10514.061365168816,633.2054098961347],
+  [10514.061365168816,798.8054098961346],
+  [10414.761365168815,964.4054098961345],
+  [10315.461365168814,964.4054098961345],
+  [10216.161365168813,964.4054098961345],
+  [10116.861365168812,798.8054098961346],
+  [10017.56136516881,798.8054098961346],
+  [10116.861365168812,964.4054098961345],
+  [10216.161365168813,1130.0054098961346],
+  [10116.861365168812,1130.0054098961346],
+  [10216.161365168813,1295.6054098961347],
+  [10216.161365168813,1461.2054098961348],
+  [10315.461365168814,1626.805409896135],
+  [10315.461365168814,1792.405409896135],
+  [10216.161365168813,1958.0054098961352],
+  [10216.161365168813,1792.405409896135],
+  [10116.861365168812,1792.405409896135],
+  [10017.56136516881,1958.0054098961352],
+  [9918.26136516881,2123.6054098961354],
+  [9918.26136516881,1958.0054098961352],
+  [10017.56136516881,2123.6054098961354],
+  [10116.861365168812,2123.6054098961354],
+  [10017.56136516881,2289.2054098961353],
+  [10017.56136516881,2454.805409896135],
+  [10116.861365168812,2289.2054098961353],
+  [10216.161365168813,2454.805409896135],
+  [10315.461365168814,2620.405409896135],
+  [10315.461365168814,2454.805409896135],
+  [10315.461365168814,2289.2054098961353],
+  [10414.761365168815,2454.805409896135],
+  [10514.061365168816,2620.405409896135],
+  [10613.361365168817,2786.005409896135],
+  [10514.061365168816,2786.005409896135],
+  [10613.361365168817,2620.405409896135],
+  [10514.061365168816,2454.805409896135],
+  [10514.061365168816,2289.2054098961353],
+  [10613.361365168817,2289.2054098961353],
+  [10712.661365168819,2289.2054098961353],
+  [10811.96136516882,2454.805409896135],
+  [10911.26136516882,2289.2054098961353],
+  [10811.96136516882,2289.2054098961353],
+  [10712.661365168819,2454.805409896135],
+  [10712.661365168819,2620.405409896135],
+  [10811.96136516882,2786.005409896135],
+  [10911.26136516882,2620.405409896135],
+  [10911.26136516882,2786.005409896135],
+  [11010.561365168822,2620.405409896135],
+  [10911.26136516882,2454.805409896135],
+  [10811.96136516882,2620.405409896135],
+  [10712.661365168819,2786.005409896135],
+  [10811.96136516882,2951.605409896135],
+  [10911.26136516882,2951.605409896135],
+  [10811.96136516882,3117.205409896135],
+  [10712.661365168819,2951.605409896135],
+  [10613.361365168817,2951.605409896135],
+  [10514.061365168816,2951.605409896135],
+  [10414.761365168815,3117.205409896135],
+  [10414.761365168815,2951.605409896135],
+  [10315.461365168814,2786.005409896135],
+  [10216.161365168813,2620.405409896135],
+  [10216.161365168813,2786.005409896135],
+  [10315.461365168814,2951.605409896135],
+  [10315.461365168814,3117.205409896135],
+  [10216.161365168813,3117.205409896135],
+  [10116.861365168812,3117.205409896135],
+  [10017.56136516881,3282.8054098961347],
+  [9918.26136516881,3448.4054098961346],
+  [9818.961365168809,3448.4054098961346],
+  [9818.961365168809,3614.0054098961346],
+  [9719.661365168808,3448.4054098961346],
+  [9818.961365168809,3282.8054098961347],
+  [9719.661365168808,3117.205409896135],
+  [9620.361365168807,2951.605409896135],
+  [9521.061365168805,3117.205409896135],
+  [9521.061365168805,3282.8054098961347],
+  [9421.761365168804,3117.205409896135],
+  [9421.761365168804,3282.8054098961347],
+  [9322.461365168803,3117.205409896135],
+  [9421.761365168804,2951.605409896135],
+  [9322.461365168803,2951.605409896135],
+  [9223.161365168802,2786.005409896135],
+  [9322.461365168803,2620.405409896135],
+  [9421.761365168804,2454.805409896135],
+  [9521.061365168805,2289.2054098961353],
+  [9421.761365168804,2123.6054098961354],
+  [9421.761365168804,1958.0054098961352],
+  [9421.761365168804,1792.405409896135],
+  [9521.061365168805,1626.805409896135],
+  [9421.761365168804,1626.805409896135],
+  [9322.461365168803,1792.405409896135],
+  [9322.461365168803,1626.805409896135],
+  [9322.461365168803,1461.2054098961348],
+  [9421.761365168804,1461.2054098961348],
+  [9521.061365168805,1295.6054098961347],
+  [9421.761365168804,1130.0054098961346],
+  [9322.461365168803,964.4054098961345],
+  [9223.161365168802,964.4054098961345],
+  [9223.161365168802,798.8054098961346],
+  [9322.461365168803,633.2054098961347],
+  [9421.761365168804,798.8054098961346],
+  [9421.761365168804,633.2054098961347],
+  [9521.061365168805,633.2054098961347],
+  [9421.761365168804,467.60540989613474],
+  [9421.761365168804,302.0054098961348],
+  [9322.461365168803,136.40540989613478],
+  [9223.161365168802,302.0054098961348],
+  [9123.861365168801,302.0054098961348],
+  [9024.5613651688,136.40540989613478],
+  [9123.861365168801,136.40540989613478],
+  [9223.161365168802,136.40540989613478],
+  [9322.461365168803,302.0054098961348],
+  [9421.761365168804,136.40540989613478],
+  [9521.061365168805,136.40540989613478],
+  [9620.361365168807,136.40540989613478],
+  [9620.361365168807,302.0054098961348],
+  [9521.061365168805,302.0054098961348],
+  [9521.061365168805,467.60540989613474],
+  [9620.361365168807,467.60540989613474],
+  [9719.661365168808,302.0054098961348],
+  [9719.661365168808,136.40540989613478],
+  [9818.961365168809,136.40540989613478],
+  [9918.26136516881,136.40540989613478],
+  [10017.56136516881,136.40540989613478],
+  [366.07287160549004,5394.185440937868],
+  [465.37287160549005,5394.185440937868],
+  [465.37287160549005,5559.785440937868],
+  [366.0728716054901,5559.785440937868],
+  [366.0728716054901,5725.385440937867],
+  [266.77287160549014,5725.385440937867],
+  [167.47287160549016,5559.785440937868],
+  [266.77287160549014,5559.785440937868],
+  [266.77287160549014,5394.185440937868],
+  [266.77287160549014,5228.585440937869],
+  [167.47287160549016,5394.185440937868],
+  [68.17287160549016,5228.585440937869],
+  [167.47287160549013,5062.9854409378695],
+  [68.17287160549013,4897.38544093787],
+  [167.47287160549013,4731.785440937871],
+  [266.77287160549014,4731.785440937871],
+  [167.47287160549016,4566.185440937871],
+  [68.17287160549016,4566.185440937871],
+  [68.17287160549016,4731.785440937871],
+  [167.47287160549013,4897.38544093787],
+  [68.17287160549013,5062.9854409378695],
+  [167.47287160549013,5228.585440937869],
+  [266.77287160549014,5062.9854409378695],
+  [366.0728716054901,4897.38544093787],
+  [266.77287160549014,4897.38544093787],
+  [366.0728716054901,4731.785440937871],
+  [465.37287160549005,4897.38544093787],
+  [366.0728716054901,5062.9854409378695],
+  [465.37287160549005,5062.9854409378695],
+  [366.0728716054901,5228.585440937869],
+  [465.37287160549005,5228.585440937869],
+  [564.6728716054901,5394.185440937868],
+  [663.9728716054901,5228.585440937869],
+  [564.6728716054901,5062.9854409378695],
+  [663.9728716054901,4897.38544093787],
+  [763.2728716054902,4731.785440937871],
+  [862.5728716054903,4566.185440937871],
+  [961.8728716054903,4731.785440937871],
+  [862.5728716054903,4731.785440937871],
+  [961.8728716054903,4566.185440937871],
+  [862.5728716054903,4400.585440937872],
+  [961.8728716054903,4234.985440937872],
+  [1061.1728716054904,4400.585440937872],
+  [1160.4728716054904,4234.985440937872],
+  [1160.4728716054904,4400.585440937872],
+  [1259.7728716054903,4234.985440937872],
+  [1359.0728716054903,4069.3854409378723],
+  [1458.3728716054902,4069.3854409378723],
+  [1557.6728716054902,4234.985440937872],
+  [1656.9728716054901,4400.585440937872],
+  [1557.6728716054902,4400.585440937872],
+  [1458.3728716054902,4400.585440937872],
+  [1359.0728716054903,4566.185440937871],
+  [1359.0728716054903,4731.785440937871],
+  [1259.7728716054903,4731.785440937871],
+  [1359.0728716054903,4897.38544093787],
+  [1458.3728716054902,4731.785440937871],
+  [1458.3728716054902,4897.38544093787],
+  [1359.0728716054903,5062.9854409378695],
+  [1259.7728716054903,5228.585440937869],
+  [1259.7728716054903,5062.9854409378695],
+  [1259.7728716054903,4897.38544093787],
+  [1160.4728716054904,5062.9854409378695],
+  [1160.4728716054904,5228.585440937869],
+  [1061.1728716054904,5228.585440937869],
+  [1061.1728716054904,5062.9854409378695],
+  [961.8728716054903,5228.585440937869],
+  [862.5728716054903,5062.9854409378695],
+  [961.8728716054903,5062.9854409378695],
+  [961.8728716054903,4897.38544093787],
+  [1061.1728716054904,4897.38544093787],
+  [1160.4728716054904,4731.785440937871],
+  [1259.7728716054903,4566.185440937871],
+  [1359.0728716054903,4400.585440937872],
+  [1458.3728716054902,4566.185440937871],
+  [1557.6728716054902,4566.185440937871],
+  [1656.9728716054901,4731.785440937871],
+  [1557.6728716054902,4897.38544093787],
+  [1458.3728716054902,5062.9854409378695],
+  [1557.6728716054902,5228.585440937869],
+  [1656.9728716054901,5062.9854409378695],
+  [1756.27287160549,5062.9854409378695],
+  [1756.27287160549,4897.38544093787],
+  [1855.57287160549,5062.9854409378695],
+  [1954.87287160549,4897.38544093787],
+  [2054.17287160549,5062.9854409378695],
+  [1954.87287160549,5062.9854409378695],
+  [2054.17287160549,5228.585440937869],
+  [2153.4728716054897,5228.585440937869],
+  [2252.7728716054894,5062.9854409378695],
+  [2352.072871605489,5228.585440937869],
+  [2451.372871605489,5394.185440937868],
+  [2352.072871605489,5394.185440937868],
+  [2252.7728716054894,5228.585440937869],
+  [2153.4728716054897,5062.9854409378695],
+  [2153.4728716054897,4897.38544093787],
+  [2252.7728716054894,4897.38544093787],
+  [2352.072871605489,4731.785440937871],
+  [2252.7728716054894,4731.785440937871],
+  [2153.4728716054897,4731.785440937871],
+  [2054.17287160549,4566.185440937871],
+  [1954.87287160549,4731.785440937871],
+  [1855.57287160549,4897.38544093787],
+  [1756.27287160549,4731.785440937871],
+  [1855.57287160549,4731.785440937871],
+  [1855.57287160549,4566.185440937871],
+  [1756.27287160549,4566.185440937871],
+  [1656.9728716054901,4566.185440937871],
+  [1557.6728716054902,4731.785440937871],
+  [1656.9728716054901,4897.38544093787],
+  [1557.6728716054902,5062.9854409378695],
+  [1458.3728716054902,5228.585440937869],
+  [1359.0728716054903,5228.585440937869],
+  [1259.7728716054903,5394.185440937868],
+  [1259.7728716054903,5559.785440937868],
+  [1160.4728716054904,5559.785440937868],
+  [1061.1728716054904,5559.785440937868],
+  [1160.4728716054904,5725.385440937867],
+  [1259.7728716054903,5725.385440937867],
+  [1359.0728716054903,5559.785440937868],
+  [1458.3728716054902,5725.385440937867],
+  [1458.3728716054902,5559.785440937868],
+  [1359.0728716054903,5725.385440937867],
+  [1259.7728716054903,5890.985440937867],
+  [1359.0728716054903,5890.985440937867],
+  [1259.7728716054903,6056.585440937866],
+  [1359.0728716054903,6222.185440937866],
+  [1458.3728716054902,6222.185440937866],
+  [1458.3728716054902,6387.785440937865],
+  [1557.6728716054902,6222.185440937866],
+  [1557.6728716054902,6387.785440937865],
+  [1656.9728716054901,6222.185440937866],
+  [1756.27287160549,6056.585440937866],
+  [1855.57287160549,5890.985440937867],
+  [1756.27287160549,5890.985440937867],
+  [1656.9728716054901,6056.585440937866],
+  [1557.6728716054902,5890.985440937867],
+  [1458.3728716054902,5890.985440937867],
+  [1359.0728716054903,6056.585440937866],
+  [1259.7728716054903,6222.185440937866],
+  [1160.4728716054904,6056.585440937866],
+  [1061.1728716054904,5890.985440937867],
+  [1061.1728716054904,6056.585440937866],
+  [1160.4728716054904,6222.185440937866],
+  [1061.1728716054904,6222.185440937866],
+  [961.8728716054903,6222.185440937866],
+  [961.8728716054903,6056.585440937866],
+  [961.8728716054903,5890.985440937867],
+  [961.8728716054903,5725.385440937867],
+  [862.5728716054903,5559.785440937868],
+  [763.2728716054902,5725.385440937867],
+  [862.5728716054903,5725.385440937867],
+  [763.2728716054902,5890.985440937867],
+  [663.9728716054901,5725.385440937867],
+  [763.2728716054902,5559.785440937868],
+  [763.2728716054902,5394.185440937868],
+  [862.5728716054903,5228.585440937869],
+  [961.8728716054903,5394.185440937868],
+  [1061.1728716054904,5394.185440937868],
+  [961.8728716054903,5559.785440937868],
+  [862.5728716054903,5394.185440937868],
+  [763.2728716054902,5228.585440937869],
+  [663.9728716054901,5062.9854409378695],
+  [763.2728716054902,5062.9854409378695],
+  [763.2728716054902,4897.38544093787],
+  [663.9728716054901,4731.785440937871],
+  [564.6728716054901,4731.785440937871],
+  [465.37287160549005,4566.185440937871],
+  [366.0728716054901,4566.185440937871],
+  [465.37287160549005,4731.785440937871],
+  [564.6728716054901,4566.185440937871],
+  [465.37287160549005,4400.585440937872],
+  [366.0728716054901,4400.585440937872],
+  [266.77287160549014,4234.985440937872],
+  [167.47287160549016,4234.985440937872],
+  [266.77287160549014,4400.585440937872],
+  [266.77287160549014,4566.185440937871],
+  [167.47287160549016,4400.585440937872],
+  [68.17287160549016,4234.985440937872],
+  [167.47287160549013,4069.3854409378723],
+  [68.17287160549013,3903.7854409378724],
+  [68.17287160549013,4069.3854409378723],
+  [167.47287160549013,3903.7854409378724],
+  [266.77287160549014,3903.7854409378724],
+  [366.0728716054901,3738.1854409378725],
+  [266.77287160549014,3738.1854409378725],
+  [266.77287160549014,3572.5854409378726],
+  [167.47287160549016,3406.9854409378727],
+  [167.47287160549016,3241.3854409378728],
+  [266.77287160549014,3241.3854409378728],
+  [266.77287160549014,3406.9854409378727],
+  [366.0728716054901,3572.5854409378726],
+  [465.37287160549005,3738.1854409378725],
+  [465.37287160549005,3903.7854409378724],
+  [366.0728716054901,4069.3854409378723],
+  [366.0728716054901,4234.985440937872],
+  [465.37287160549005,4234.985440937872],
+  [564.6728716054901,4069.3854409378723],
+  [465.37287160549005,4069.3854409378723],
+  [564.6728716054901,4234.985440937872],
+  [663.9728716054901,4069.3854409378723],
+  [663.9728716054901,4234.985440937872],
+  [663.9728716054901,4400.585440937872],
+  [763.2728716054902,4566.185440937871],
+  [763.2728716054902,4400.585440937872],
+  [663.9728716054901,4566.185440937871],
+  [564.6728716054901,4400.585440937872],
+  [19431.915041401327,3495.506142643713],
+  [19332.61504140133,3661.1061426437127],
+  [19431.915041401327,3661.1061426437127],
+  [19531.215041401327,3661.1061426437127],
+  [19630.515041401326,3495.506142643713],
+  [19630.515041401326,3661.1061426437127],
+  [19729.815041401325,3826.7061426437126],
+  [19630.515041401326,3826.7061426437126],
+  [19729.815041401325,3992.3061426437125],
+  [19630.515041401326,3992.3061426437125],
+  [19630.515041401326,4157.906142643712],
+  [19630.515041401326,4323.506142643711],
+  [19531.215041401327,4157.906142643712],
+  [19431.915041401327,4323.506142643711],
+  [19531.215041401327,4489.106142643711],
+  [19431.915041401327,4654.70614264371],
+  [19332.61504140133,4654.70614264371],
+  [19332.61504140133,4820.30614264371],
+  [19332.61504140133,4985.906142643709],
+  [19233.31504140133,4985.906142643709],
+  [19134.01504140133,5151.506142643709],
+  [19034.71504140133,5151.506142643709],
+  [19134.01504140133,5317.106142643708],
+  [19034.71504140133,5317.106142643708],
+  [19034.71504140133,5482.706142643708],
+  [18935.41504140133,5648.306142643707],
+  [18836.115041401332,5813.9061426437065],
+  [18836.115041401332,5979.506142643706],
+  [18935.41504140133,5979.506142643706],
+  [19034.71504140133,6145.106142643705],
+  [19034.71504140133,5979.506142643706],
+  [19034.71504140133,5813.9061426437065],
+  [19134.01504140133,5648.306142643707],
+  [19233.31504140133,5648.306142643707],
+  [19134.01504140133,5813.9061426437065],
+  [19134.01504140133,5979.506142643706],
+  [19233.31504140133,5813.9061426437065],
+  [19233.31504140133,5979.506142643706],
+  [19332.61504140133,6145.106142643705],
+  [19332.61504140133,6310.706142643705],
+  [19233.31504140133,6310.706142643705],
+  [19233.31504140133,6476.306142643704],
+  [19332.61504140133,6476.306142643704],
+  [19431.915041401327,6641.906142643704],
+  [19332.61504140133,6807.506142643703],
+  [19332.61504140133,6641.906142643704],
+  [19431.915041401327,6476.306142643704],
+  [19431.915041401327,6310.706142643705],
+  [19531.215041401327,6145.106142643705],
+  [19431.915041401327,5979.506142643706],
+  [19431.915041401327,6145.106142643705],
+  [19531.215041401327,5979.506142643706],
+  [19630.515041401326,5813.9061426437065],
+  [19630.515041401326,5979.506142643706],
+  [19729.815041401325,5813.9061426437065],
+  [19829.115041401325,5979.506142643706],
+  [19729.815041401325,5979.506142643706],
+  [19729.815041401325,6145.106142643705],
+  [19729.815041401325,6310.706142643705],
+  [19630.515041401326,6476.306142643704],
+  [19729.815041401325,6476.306142643704],
+  [19630.515041401326,6310.706142643705],
+  [19531.215041401327,6310.706142643705],
+  [19531.215041401327,6476.306142643704],
+  [19630.515041401326,6641.906142643704],
+  [19729.815041401325,6807.506142643703],
+  [19829.115041401325,6973.106142643703],
+  [19928.415041401324,6973.106142643703],
+  [19928.415041401324,7138.706142643702],
+  [20027.715041401323,7138.706142643702],
+  [20027.715041401323,7304.306142643702],
+  [19928.415041401324,7304.306142643702],
+  [19829.115041401325,7304.306142643702],
+  [19829.115041401325,7469.906142643701],
+  [19928.415041401324,7469.906142643701],
+  [19928.415041401324,7635.5061426437005],
+  [19928.415041401324,7801.1061426437],
+  [20027.715041401323,7635.5061426437005],
+  [20027.715041401323,7801.1061426437],
+  [20127.015041401322,7801.1061426437],
+  [20226.31504140132,7801.1061426437],
+  [20325.61504140132,7801.1061426437],
+  [20226.31504140132,7635.5061426437005],
+  [20226.31504140132,7469.906142643701],
+  [20226.31504140132,7304.306142643702],
+  [20127.015041401322,7304.306142643702],
+  [20027.715041401323,7469.906142643701],
+  [20127.015041401322,7469.906142643701],
+  [20127.015041401322,7635.5061426437005],
+  [2748.790306732237,2362.9553147492866],
+  [2848.0903067322365,2528.5553147492865],
+  [2748.790306732237,2694.1553147492864],
+  [2649.490306732237,2859.7553147492863],
+  [2748.790306732237,3025.355314749286],
+  [2848.0903067322365,2859.7553147492863],
+  [2848.0903067322365,2694.1553147492864],
+  [2947.3903067322362,2694.1553147492864],
+  [3046.690306732236,2859.7553147492863],
+  [3145.9903067322357,2694.1553147492864],
+  [3145.9903067322357,2528.5553147492865],
+  [3046.690306732236,2694.1553147492864],
+  [3145.9903067322357,2859.7553147492863],
+  [3046.690306732236,3025.355314749286],
+  [3145.9903067322357,3025.355314749286],
+  [3245.2903067322354,3190.955314749286],
+  [3245.2903067322354,3356.555314749286],
+  [3344.590306732235,3522.155314749286],
+  [3443.890306732235,3356.555314749286],
+  [3543.1903067322346,3356.555314749286],
+  [3642.4903067322343,3190.955314749286],
+  [3741.790306732234,3025.355314749286],
+  [3741.790306732234,2859.7553147492863],
+  [3841.090306732234,3025.355314749286],
+  [3841.090306732234,3190.955314749286],
+  [3741.790306732234,3190.955314749286],
+  [3642.4903067322343,3025.355314749286],
+  [3543.1903067322346,3025.355314749286],
+  [3543.1903067322346,2859.7553147492863],
+  [3443.890306732235,3025.355314749286],
+  [3443.890306732235,3190.955314749286],
+  [3543.1903067322346,3190.955314749286],
+  [3642.4903067322343,3356.555314749286],
+  [3543.1903067322346,3522.155314749286],
+  [3443.890306732235,3687.755314749286],
+  [3443.890306732235,3853.3553147492858],
+  [3344.590306732235,3687.755314749286],
+  [3245.2903067322354,3853.3553147492858],
+  [3245.2903067322354,3687.755314749286],
+  [3145.9903067322357,3687.755314749286],
+  [3046.690306732236,3853.3553147492858],
+  [3145.9903067322357,4018.9553147492857],
+  [3145.9903067322357,3853.3553147492858],
+  [3046.690306732236,3687.755314749286],
+  [3145.9903067322357,3522.155314749286],
+  [3145.9903067322357,3356.555314749286],
+  [3145.9903067322357,3190.955314749286],
+  [3046.690306732236,3190.955314749286],
+  [3046.690306732236,3356.555314749286],
+  [2947.3903067322362,3356.555314749286],
+  [2848.0903067322365,3190.955314749286],
+  [2947.3903067322362,3025.355314749286],
+  [2848.0903067322365,3025.355314749286],
+  [2748.790306732237,2859.7553147492863],
+  [2649.490306732237,2694.1553147492864],
+  [2748.790306732237,2528.5553147492865],
+  [2848.0903067322365,2362.9553147492866],
+  [2748.790306732237,2197.3553147492867],
+  [2649.490306732237,2362.9553147492866],
+  [2649.490306732237,2197.3553147492867],
+  [2550.1903067322373,2362.9553147492866],
+  [2450.8903067322376,2362.9553147492866],
+  [2351.590306732238,2528.5553147492865],
+  [2252.290306732238,2528.5553147492865],
+  [2351.590306732238,2362.9553147492866],
+  [2252.290306732238,2197.3553147492867],
+  [2351.590306732238,2197.3553147492867],
+  [2351.590306732238,2031.7553147492865],
+  [2351.590306732238,1866.1553147492864],
+  [2252.290306732238,1866.1553147492864],
+  [2351.590306732238,1700.5553147492863],
+  [2450.8903067322376,1534.9553147492861],
+  [2351.590306732238,1369.355314749286],
+  [2252.290306732238,1203.7553147492858],
+  [2252.290306732238,1369.355314749286],
+  [2252.290306732238,1534.9553147492861],
+  [2152.9903067322384,1369.355314749286],
+  [2053.6903067322387,1369.355314749286],
+  [1954.3903067322387,1203.7553147492858],
+  [1855.0903067322388,1203.7553147492858],
+  [1755.7903067322388,1038.1553147492857],
+  [1656.4903067322389,1038.1553147492857],
+  [1557.190306732239,872.5553147492857],
+  [1457.890306732239,1038.1553147492857],
+  [1457.890306732239,872.5553147492857],
+  [1457.890306732239,706.9553147492858],
+  [1557.190306732239,706.9553147492858],
+  [1656.4903067322389,872.5553147492857],
+  [1656.4903067322389,706.9553147492858],
+  [1755.7903067322388,706.9553147492858],
+  [1656.4903067322389,541.3553147492859],
+  [1557.190306732239,375.7553147492859],
+  [1656.4903067322389,210.1553147492859],
+  [1755.7903067322388,44.55531474928592],
+  [1656.4903067322389,44.55531474928592],
+  [1557.190306732239,210.1553147492859],
+  [1457.890306732239,210.1553147492859],
+  [1457.890306732239,44.55531474928592],
+  [1358.590306732239,210.1553147492859],
+  [1358.590306732239,375.75531474928584],
+  [1259.290306732239,210.15531474928585],
+  [1259.290306732239,375.75531474928584],
+  [1259.290306732239,541.3553147492859],
+  [1358.590306732239,706.9553147492858],
+  [1358.590306732239,872.5553147492857],
+  [1259.290306732239,706.9553147492858],
+  [1259.290306732239,872.5553147492857],
+  [1259.290306732239,1038.1553147492857],
+  [1358.590306732239,1203.7553147492858],
+  [1358.590306732239,1038.1553147492857],
+  [1457.890306732239,1203.7553147492858],
+  [1557.190306732239,1369.355314749286],
+  [1656.4903067322389,1203.7553147492858],
+  [1557.190306732239,1203.7553147492858],
+  [1557.190306732239,1038.1553147492857],
+  [17254.572515546668,1460.5807801244923],
+  [17353.872515546667,1626.1807801244925],
+  [17453.172515546667,1791.7807801244926],
+  [17552.472515546666,1791.7807801244926],
+  [17453.172515546667,1626.1807801244925],
+  [17353.872515546667,1791.7807801244926],
+  [17453.172515546667,1957.3807801244927],
+  [17353.872515546667,2122.980780124493],
+  [17453.172515546667,2288.580780124493],
+  [17353.872515546667,2454.1807801244927],
+  [17453.172515546667,2619.7807801244926],
+  [17552.472515546666,2619.7807801244926],
+  [17453.172515546667,2785.3807801244925],
+  [17353.872515546667,2619.7807801244926],
+  [17254.572515546668,2454.1807801244927],
+  [17254.572515546668,2288.580780124493],
+  [17353.872515546667,2288.580780124493],
+  [17453.172515546667,2122.980780124493],
+  [17552.472515546666,2288.580780124493],
+  [17552.472515546666,2454.1807801244927],
+  [17453.172515546667,2454.1807801244927],
+  [4447.67624466283,4761.1416826913],
+  [4546.97624466283,4595.541682691301],
+  [4546.97624466283,4429.941682691301],
+  [4447.67624466283,4429.941682691301],
+  [4447.67624466283,4595.541682691301],
+  [4348.37624466283,4595.541682691301],
+  [4249.07624466283,4595.541682691301],
+  [4348.37624466283,4761.1416826913],
+  [4249.07624466283,4761.1416826913],
+  [4348.37624466283,4926.7416826912995],
+  [4348.37624466283,5092.341682691299],
+  [4447.67624466283,5257.941682691298],
+  [4546.97624466283,5257.941682691298],
+  [4646.27624466283,5092.341682691299],
+  [4546.97624466283,5092.341682691299],
+  [4646.27624466283,4926.7416826912995],
+  [4646.27624466283,4761.1416826913],
+  [4546.97624466283,4761.1416826913],
+  [4646.27624466283,4595.541682691301],
+  [4745.5762446628305,4595.541682691301],
+  [4646.27624466283,4429.941682691301],
+  [4745.5762446628305,4429.941682691301],
+  [4844.876244662831,4595.541682691301],
+  [4745.5762446628305,4761.1416826913],
+  [4745.5762446628305,4926.7416826912995],
+  [4844.876244662831,4761.1416826913],
+  [4944.176244662831,4761.1416826913],
+  [5043.476244662831,4926.7416826912995],
+  [5043.476244662831,4761.1416826913],
+  [5142.776244662831,4926.7416826912995],
+  [5142.776244662831,4761.1416826913],
+  [5242.076244662831,4595.541682691301],
+  [5142.776244662831,4595.541682691301],
+  [5242.076244662831,4429.941682691301],
+  [5242.076244662831,4264.341682691302],
+  [5142.776244662831,4429.941682691301],
+  [5043.476244662831,4595.541682691301],
+  [5043.476244662831,4429.941682691301],
+  [5043.476244662831,4264.341682691302],
+  [5142.776244662831,4098.741682691302],
+  [5043.476244662831,4098.741682691302],
+  [4944.176244662831,3933.1416826913023],
+  [4944.176244662831,4098.741682691302],
+  [4944.176244662831,4264.341682691302],
+  [4844.876244662831,4098.741682691302],
+  [4745.5762446628305,4264.341682691302],
+  [4646.27624466283,4098.741682691302],
+  [4546.97624466283,3933.1416826913023],
+  [4447.67624466283,4098.741682691302],
+  [4546.97624466283,4264.341682691302],
+  [4447.67624466283,4264.341682691302],
+  [4546.97624466283,4098.741682691302],
+  [4646.27624466283,3933.1416826913023],
+  [4546.97624466283,3767.5416826913024],
+  [4447.67624466283,3601.9416826913025],
+  [4447.67624466283,3767.5416826913024],
+  [4348.37624466283,3767.5416826913024],
+  [4348.37624466283,3933.1416826913023],
+  [4249.07624466283,3767.5416826913024],
+  [4249.07624466283,3933.1416826913023],
+  [4149.776244662829,3933.1416826913023],
+  [4050.4762446628297,4098.741682691302],
+  [4050.4762446628297,3933.1416826913023],
+  [3951.17624466283,3933.1416826913023],
+  [3951.17624466283,4098.741682691302],
+  [3851.8762446628302,4264.341682691302],
+  [3851.8762446628302,4098.741682691302],
+  [3752.5762446628305,4098.741682691302],
+  [3653.276244662831,4264.341682691302],
+  [3553.976244662831,4429.941682691301],
+  [3553.976244662831,4595.541682691301],
+  [3454.6762446628313,4429.941682691301],
+  [3553.976244662831,4264.341682691302],
+  [3653.276244662831,4429.941682691301],
+  [3752.5762446628305,4264.341682691302],
+  [3752.5762446628305,4429.941682691301],
+  [3851.8762446628302,4595.541682691301],
+  [3851.8762446628302,4429.941682691301],
+  [3951.17624466283,4429.941682691301],
+  [4050.4762446628297,4264.341682691302],
+  [4149.776244662829,4098.741682691302],
+  [4249.07624466283,4264.341682691302],
+  [4348.37624466283,4098.741682691302],
+  [4447.67624466283,3933.1416826913023],
+  [9574.088902135607,7352.26293905581],
+  [9474.788902135606,7352.26293905581],
+  [9375.488902135605,7186.662939055811],
+  [9474.788902135606,7021.0629390558115],
+  [9574.088902135607,7021.0629390558115],
+  [9474.788902135606,7186.662939055811],
+  [9574.088902135607,7186.662939055811],
+  [9673.388902135608,7021.0629390558115],
+  [9673.388902135608,6855.462939055812],
+  [9772.68890213561,6689.862939055813],
+  [9673.388902135608,6689.862939055813],
+  [9772.68890213561,6524.262939055813],
+  [9871.98890213561,6358.662939055814],
+  [9971.288902135611,6524.262939055813],
+  [10070.588902135612,6358.662939055814],
+  [10070.588902135612,6193.062939055814],
+  [9971.288902135611,6027.462939055815],
+  [9971.288902135611,5861.862939055815],
+  [9871.98890213561,5861.862939055815],
+  [9871.98890213561,5696.262939055816],
+  [9971.288902135611,5530.662939055816],
+  [10070.588902135612,5530.662939055816],
+  [10070.588902135612,5696.262939055816],
+  [10169.888902135614,5861.862939055815],
+  [10169.888902135614,5696.262939055816],
+  [10070.588902135612,5861.862939055815],
+  [10169.888902135614,6027.462939055815],
+  [10169.888902135614,6193.062939055814],
+  [10269.188902135615,6027.462939055815],
+  [10269.188902135615,5861.862939055815],
+  [10368.488902135616,6027.462939055815],
+  [10269.188902135615,6193.062939055814],
+  [10269.188902135615,6358.662939055814],
+  [10169.888902135614,6358.662939055814],
+  [10070.588902135612,6524.262939055813],
+  [10070.588902135612,6689.862939055813],
+  [9971.288902135611,6855.462939055812],
+  [9971.288902135611,7021.0629390558115],
+  [10070.588902135612,7186.662939055811],
+  [10169.888902135614,7186.662939055811],
+  [10269.188902135615,7186.662939055811],
+  [10169.888902135614,7352.26293905581],
+  [10070.588902135612,7352.26293905581],
+  [10169.888902135614,7517.86293905581],
+  [10169.888902135614,7683.462939055809],
+  [10269.188902135615,7517.86293905581],
+  [10368.488902135616,7683.462939055809],
+  [10467.788902135617,7683.462939055809],
+  [10368.488902135616,7517.86293905581],
+  [10269.188902135615,7352.26293905581],
+  [10368.488902135616,7352.26293905581],
+  [10368.488902135616,7186.662939055811],
+  [10368.488902135616,7021.0629390558115],
+  [10368.488902135616,6855.462939055812],
+  [10269.188902135615,6855.462939055812],
+  [10169.888902135614,6855.462939055812],
+  [10169.888902135614,7021.0629390558115],
+  [10070.588902135612,7021.0629390558115],
+  [10070.588902135612,6855.462939055812],
+  [10169.888902135614,6689.862939055813],
+  [10269.188902135615,6689.862939055813],
+  [10169.888902135614,6524.262939055813],
+  [10269.188902135615,6524.262939055813],
+  [10368.488902135616,6524.262939055813],
+  [10368.488902135616,6358.662939055814],
+  [10467.788902135617,6358.662939055814],
+  [10467.788902135617,6193.062939055814],
+  [10567.088902135618,6358.662939055814],
+  [10567.088902135618,6193.062939055814],
+  [10666.388902135619,6193.062939055814],
+  [10666.388902135619,6358.662939055814],
+  [10567.088902135618,6524.262939055813],
+  [10467.788902135617,6524.262939055813],
+  [10567.088902135618,6689.862939055813],
+  [10467.788902135617,6855.462939055812],
+  [10567.088902135618,7021.0629390558115],
+  [10467.788902135617,7021.0629390558115],
+  [10567.088902135618,6855.462939055812],
+  [10467.788902135617,6689.862939055813],
+  [10368.488902135616,6689.862939055813],
+  [1073.6944354374714,1154.3681204032646],
+  [974.3944354374713,1319.9681204032647],
+  [875.0944354374712,1319.9681204032647],
+  [775.7944354374712,1154.3681204032646],
+  [775.7944354374712,988.7681204032646],
+  [875.0944354374712,823.1681204032647],
+  [875.0944354374712,657.5681204032647],
+  [775.7944354374712,823.1681204032647],
+  [676.4944354374711,657.5681204032647],
+  [676.4944354374711,491.9681204032648],
+  [775.7944354374712,657.5681204032647],
+  [676.4944354374711,823.1681204032647],
+  [676.4944354374711,988.7681204032646],
+  [577.194435437471,823.1681204032647],
+  [577.194435437471,988.7681204032646],
+  [577.194435437471,1154.3681204032646],
+  [676.4944354374711,1319.9681204032647],
+  [577.194435437471,1319.9681204032647],
+  [477.89443543747103,1319.9681204032647],
+  [577.194435437471,1485.5681204032649],
+  [477.89443543747103,1651.168120403265],
+  [577.194435437471,1816.7681204032651],
+  [477.89443543747103,1816.7681204032651],
+  [378.5944354374711,1982.3681204032653],
+  [378.5944354374711,2147.9681204032654],
+  [279.2944354374711,2313.5681204032653],
+  [179.99443543747114,2147.9681204032654],
+  [80.69443543747114,2313.5681204032653],
+  [80.69443543747114,2479.168120403265],
+  [179.9944354374711,2644.768120403265],
+  [179.9944354374711,2479.168120403265],
+  [179.9944354374711,2313.5681204032653],
+  [80.69443543747111,2147.9681204032654],
+  [80.69443543747111,1982.3681204032653],
+  [179.9944354374711,1982.3681204032653],
+  [179.9944354374711,1816.7681204032651],
+  [80.69443543747111,1816.7681204032651],
+  [179.9944354374711,1651.168120403265],
+  [80.69443543747111,1485.5681204032649],
+  [80.69443543747111,1319.9681204032647],
+  [179.9944354374711,1154.3681204032646],
+  [80.69443543747111,1154.3681204032646],
+  [179.9944354374711,988.7681204032646],
+  [279.2944354374711,823.1681204032647],
+  [378.5944354374711,657.5681204032647],
+  [378.5944354374711,823.1681204032647],
+  [477.89443543747103,823.1681204032647],
+  [477.89443543747103,657.5681204032647],
+  [378.5944354374711,491.9681204032648],
+  [477.89443543747103,326.3681204032648],
+  [477.89443543747103,160.76812040326482],
+  [378.5944354374711,160.76812040326482],
+  [279.2944354374711,326.3681204032648],
+  [179.99443543747114,491.9681204032648],
+  [179.99443543747114,326.3681204032648],
+  [279.2944354374711,491.9681204032648],
+  [279.2944354374711,657.5681204032647],
+  [179.99443543747114,823.1681204032647],
+  [279.2944354374711,988.7681204032646],
+  [279.2944354374711,1154.3681204032646],
+  [378.5944354374711,1319.9681204032647],
+  [477.89443543747103,1485.5681204032649],
+  [577.194435437471,1651.168120403265],
+  [676.4944354374711,1651.168120403265],
+  [775.7944354374712,1816.7681204032651],
+  [676.4944354374711,1816.7681204032651],
+  [775.7944354374712,1651.168120403265],
+  [875.0944354374712,1651.168120403265],
+  [974.3944354374713,1651.168120403265],
+  [875.0944354374712,1485.5681204032649],
+  [775.7944354374712,1485.5681204032649],
+  [676.4944354374711,1485.5681204032649],
+  [775.7944354374712,1319.9681204032647],
+  [676.4944354374711,1154.3681204032646],
+  [3138.413562431697,2355.845602060523],
+  [3039.113562431697,2521.445602060523],
+  [3039.113562431697,2355.845602060523],
+  [3039.113562431697,2190.245602060523],
+  [3138.413562431697,2024.645602060523],
+  [3237.7135624316966,1859.045602060523],
+  [3237.7135624316966,2024.645602060523],
+  [3337.0135624316963,1859.045602060523],
+  [3337.0135624316963,1693.4456020605228],
+  [3436.313562431696,1527.8456020605227],
+  [3535.6135624316958,1693.4456020605228],
+  [3535.6135624316958,1859.045602060523],
+  [3634.9135624316955,2024.645602060523],
+  [3734.213562431695,2190.245602060523],
+  [3634.9135624316955,2190.245602060523],
+  [3535.6135624316958,2190.245602060523],
+  [3535.6135624316958,2355.845602060523],
+  [3535.6135624316958,2521.445602060523],
+  [3436.313562431696,2687.045602060523],
+  [3436.313562431696,2852.645602060523],
+  [3535.6135624316958,2687.045602060523],
+  [3634.9135624316955,2521.445602060523],
+  [3634.9135624316955,2355.845602060523],
+  [3734.213562431695,2355.845602060523],
+  [3833.513562431695,2190.245602060523],
+  [3932.8135624316947,2024.645602060523],
+  [3833.513562431695,1859.045602060523],
+  [3833.513562431695,1693.4456020605228],
+  [3734.213562431695,1859.045602060523],
+  [3734.213562431695,1693.4456020605228],
+  [3734.213562431695,1527.8456020605227],
+  [3634.9135624316955,1527.8456020605227],
+  [3634.9135624316955,1693.4456020605228],
+  [3535.6135624316958,1527.8456020605227],
+  [3634.9135624316955,1362.2456020605225],
+  [3535.6135624316958,1362.2456020605225],
+  [3436.313562431696,1196.6456020605224],
+  [3535.6135624316958,1196.6456020605224],
+  [3535.6135624316958,1031.0456020605222],
+  [3436.313562431696,1031.0456020605222],
+  [3535.6135624316958,865.4456020605222],
+  [3436.313562431696,865.4456020605222],
+  [3535.6135624316958,699.8456020605223],
+  [3634.9135624316955,699.8456020605223],
+  [3535.6135624316958,534.2456020605224],
+  [3436.313562431696,368.64560206052244],
+  [3436.313562431696,203.04560206052244],
+  [3337.0135624316963,37.445602060522454],
+  [3436.313562431696,37.445602060522454],
+  [3337.0135624316963,203.04560206052244],
+  [3237.7135624316966,37.445602060522454],
+  [3138.413562431697,37.445602060522454],
+  [3237.7135624316966,203.04560206052244],
+  [3337.0135624316963,368.6456020605224],
+  [3436.313562431696,534.2456020605224],
+  [3337.0135624316963,699.8456020605223],
+  [3237.7135624316966,534.2456020605224],
+  [3337.0135624316963,534.2456020605224],
+  [3436.313562431696,699.8456020605223],
+  [3337.0135624316963,865.4456020605222],
+  [3237.7135624316966,865.4456020605222],
+  [3337.0135624316963,1031.0456020605222],
+  [3237.7135624316966,1196.6456020605224],
+  [3138.413562431697,1362.2456020605225],
+  [3039.113562431697,1527.8456020605227],
+  [3138.413562431697,1527.8456020605227],
+  [3039.113562431697,1693.4456020605228],
+  [2939.8135624316974,1527.8456020605227],
+  [2840.5135624316977,1362.2456020605225],
+  [2840.5135624316977,1527.8456020605227],
+  [2840.5135624316977,1693.4456020605228],
+  [2939.8135624316974,1859.045602060523],
+  [2840.5135624316977,2024.645602060523],
+  [2840.5135624316977,1859.045602060523],
+  [2939.8135624316974,1693.4456020605228],
+  [3039.113562431697,1859.045602060523],
+  [3039.113562431697,2024.645602060523],
+  [2939.8135624316974,2190.245602060523],
+  [2939.8135624316974,2024.645602060523],
+  [16388.412117675925,1839.818884803299],
+  [16289.112117675924,1839.818884803299],
+  [16388.412117675925,1674.2188848032988],
+  [16487.712117675925,1508.6188848032987],
+  [16487.712117675925,1674.2188848032988],
+  [16388.412117675925,1508.6188848032987],
+  [16289.112117675924,1343.0188848032985],
+  [16289.112117675924,1508.6188848032987],
+  [16189.812117675923,1674.2188848032988],
+  [16090.512117675922,1839.818884803299],
+  [16090.512117675922,2005.418884803299],
+  [15991.212117675921,2171.018884803299],
+  [16090.512117675922,2336.618884803299],
+  [16090.512117675922,2502.218884803299],
+  [16090.512117675922,2667.8188848032987],
+  [15991.212117675921,2833.4188848032986],
+  [15991.212117675921,2999.0188848032985],
+  [15891.91211767592,3164.6188848032984],
+  [15891.91211767592,3330.2188848032984],
+  [15991.212117675921,3330.2188848032984],
+  [16090.512117675922,3330.2188848032984],
+  [16189.812117675923,3495.8188848032983],
+  [16289.112117675924,3495.8188848032983],
+  [16189.812117675923,3330.2188848032984],
+  [16189.812117675923,3164.6188848032984],
+  [16289.112117675924,3164.6188848032984],
+  [16388.412117675925,3164.6188848032984],
+  [16388.412117675925,3330.2188848032984],
+  [16487.712117675925,3330.2188848032984],
+  [16587.012117675924,3495.8188848032983],
+  [16587.012117675924,3661.418884803298],
+  [16686.312117675923,3661.418884803298],
+  [16785.612117675922,3661.418884803298],
+  [16884.91211767592,3661.418884803298],
+  [16984.21211767592,3661.418884803298],
+  [16884.91211767592,3827.018884803298],
+  [16884.91211767592,3992.618884803298],
+  [16984.21211767592,3827.018884803298],
+  [17083.51211767592,3661.418884803298],
+  [17182.81211767592,3495.8188848032983],
+  [17182.81211767592,3330.2188848032984],
+  [17282.11211767592,3164.6188848032984],
+  [17282.11211767592,3330.2188848032984],
+  [17182.81211767592,3164.6188848032984],
+  [17083.51211767592,3164.6188848032984],
+  [16984.21211767592,3330.2188848032984],
+  [16984.21211767592,3495.8188848032983],
+  [17083.51211767592,3330.2188848032984],
+  [16984.21211767592,3164.6188848032984],
+  [16984.21211767592,2999.0188848032985],
+  [17083.51211767592,2833.4188848032986],
+  [17083.51211767592,2667.8188848032987],
+  [17182.81211767592,2667.8188848032987],
+  [17182.81211767592,2833.4188848032986],
+  [17083.51211767592,2999.0188848032985],
+  [16984.21211767592,2833.4188848032986],
+  [16884.91211767592,2833.4188848032986],
+  [16884.91211767592,2999.0188848032985],
+  [16785.612117675922,2999.0188848032985],
+  [16884.91211767592,3164.6188848032984],
+  [16785.612117675922,3164.6188848032984],
+  [16686.312117675923,3164.6188848032984],
+  [16587.012117675924,3164.6188848032984],
+  [16587.012117675924,2999.0188848032985],
+  [16487.712117675925,3164.6188848032984],
+  [16587.012117675924,3330.2188848032984],
+  [16686.312117675923,3495.8188848032983],
+  [16686.312117675923,3330.2188848032984],
+  [16785.612117675922,3330.2188848032984],
+  [16884.91211767592,3495.8188848032983],
+  [16785.612117675922,3495.8188848032983],
+  [16884.91211767592,3330.2188848032984],
+  [1272.175991128079,3842.7700224365044],
+  [1371.475991128079,3842.7700224365044],
+  [1272.175991128079,3677.1700224365045],
+  [1172.875991128079,3511.5700224365046],
+  [1272.175991128079,3511.5700224365046],
+  [1172.875991128079,3345.9700224365047],
+  [1073.575991128079,3180.3700224365048],
+  [1073.575991128079,3014.770022436505],
+  [974.275991128079,3014.770022436505],
+  [874.9759911280789,3014.770022436505],
+  [775.6759911280789,2849.170022436505],
+  [775.6759911280789,3014.770022436505],
+  [775.6759911280789,3180.3700224365048],
+  [676.3759911280788,3345.9700224365047],
+  [676.3759911280788,3511.5700224365046],
+  [775.6759911280789,3677.1700224365045],
+  [676.3759911280788,3842.7700224365044],
+  [577.0759911280787,3842.7700224365044],
+  [577.0759911280787,3677.1700224365045],
+  [676.3759911280788,3677.1700224365045],
+  [775.6759911280789,3511.5700224365046],
+  [775.6759911280789,3345.9700224365047],
+  [874.9759911280789,3345.9700224365047],
+  [874.9759911280789,3180.3700224365048],
+  [974.275991128079,3180.3700224365048],
+  [974.275991128079,3345.9700224365047],
+  [1073.575991128079,3511.5700224365046],
+  [1073.575991128079,3677.1700224365045],
+  [1172.875991128079,3677.1700224365045],
+  [1172.875991128079,3842.7700224365044],
+  [1073.575991128079,3842.7700224365044],
+  [1172.875991128079,4008.3700224365043],
+  [1073.575991128079,4008.3700224365043],
+  [974.275991128079,3842.7700224365044],
+  [974.275991128079,4008.3700224365043],
+  [874.9759911280789,4008.3700224365043],
+  [775.6759911280789,4008.3700224365043],
+  [874.9759911280789,3842.7700224365044],
+  [974.275991128079,3677.1700224365045],
+  [974.275991128079,3511.5700224365046],
+  [1073.575991128079,3345.9700224365047],
+  [1172.875991128079,3180.3700224365048],
+  [1272.175991128079,3180.3700224365048],
+  [1272.175991128079,3345.9700224365047],
+  [1371.475991128079,3180.3700224365048],
+  [1470.7759911280789,3345.9700224365047],
+  [1371.475991128079,3345.9700224365047],
+  [1371.475991128079,3511.5700224365046],
+  [1470.7759911280789,3511.5700224365046],
+  [1570.0759911280788,3677.1700224365045],
+  [1470.7759911280789,3677.1700224365045],
+  [1570.0759911280788,3511.5700224365046],
+  [1669.3759911280788,3511.5700224365046],
+  [1669.3759911280788,3677.1700224365045],
+  [1768.6759911280787,3842.7700224365044],
+  [1669.3759911280788,3842.7700224365044],
+  [1768.6759911280787,4008.3700224365043],
+  [1867.9759911280787,3842.7700224365044],
+  [1967.2759911280787,3677.1700224365045],
+  [2066.5759911280784,3842.7700224365044],
+  [2165.875991128078,3677.1700224365045],
+  [2066.5759911280784,3511.5700224365046],
+  [2165.875991128078,3511.5700224365046],
+  [2066.5759911280784,3677.1700224365045],
+  [2165.875991128078,3842.7700224365044],
+  [2265.175991128078,4008.3700224365043],
+  [2364.4759911280776,4008.3700224365043],
+  [2265.175991128078,3842.7700224365044],
+  [2364.4759911280776,3677.1700224365045],
+  [2463.7759911280773,3842.7700224365044],
+  [2463.7759911280773,4008.3700224365043],
+  [2364.4759911280776,3842.7700224365044],
+  [6853.940039224797,6050.837897021371],
+  [6953.240039224797,6050.837897021371],
+  [7052.5400392247975,5885.237897021371],
+  [7052.5400392247975,5719.637897021372],
+  [7151.840039224798,5885.237897021371],
+  [7052.5400392247975,6050.837897021371],
+  [7052.5400392247975,6216.43789702137],
+  [7052.5400392247975,6382.03789702137],
+  [6953.240039224797,6382.03789702137],
+  [6953.240039224797,6216.43789702137],
+  [6853.940039224797,6216.43789702137],
+  [6853.940039224797,6382.03789702137],
+  [6754.640039224797,6216.43789702137],
+  [6754.640039224797,6382.03789702137],
+  [6754.640039224797,6547.637897021369],
+  [6754.640039224797,6713.237897021369],
+  [6655.340039224797,6713.237897021369],
+  [6754.640039224797,6878.837897021368],
+  [6853.940039224797,6713.237897021369],
+  [6853.940039224797,6878.837897021368],
+  [6953.240039224797,6713.237897021369],
+  [7052.5400392247975,6547.637897021369],
+  [7151.840039224798,6713.237897021369],
+  [7151.840039224798,6547.637897021369],
+  [7151.840039224798,6382.03789702137],
+  [7251.140039224798,6547.637897021369],
+  [7251.140039224798,6713.237897021369],
+  [7350.440039224798,6878.837897021368],
+  [7449.740039224798,6878.837897021368],
+  [7449.740039224798,6713.237897021369],
+  [7549.040039224798,6547.637897021369],
+  [7449.740039224798,6382.03789702137],
+  [7449.740039224798,6216.43789702137],
+  [7549.040039224798,6050.837897021371],
+  [7648.340039224799,6216.43789702137],
+  [7549.040039224798,6382.03789702137],
+  [7648.340039224799,6382.03789702137],
+  [7747.640039224799,6216.43789702137],
+  [7846.940039224799,6382.03789702137],
+  [7946.240039224799,6382.03789702137],
+  [7946.240039224799,6547.637897021369],
+  [7846.940039224799,6713.237897021369],
+  [7946.240039224799,6713.237897021369],
+  [8045.540039224799,6547.637897021369],
+  [8045.540039224799,6713.237897021369],
+  [7946.240039224799,6878.837897021368],
+  [7946.240039224799,7044.4378970213675],
+  [8045.540039224799,7210.037897021367],
+  [8144.8400392247995,7375.637897021366],
+  [8144.8400392247995,7541.237897021366],
+  [8045.540039224799,7375.637897021366],
+  [8144.8400392247995,7210.037897021367],
+  [8045.540039224799,7044.4378970213675],
+  [7946.240039224799,7210.037897021367],
+  [7846.940039224799,7210.037897021367],
+  [7946.240039224799,7375.637897021366],
+  [8045.540039224799,7541.237897021366],
+  [8144.8400392247995,7706.837897021365],
+  [8244.1400392248,7541.237897021366],
+  [8343.4400392248,7541.237897021366],
+  [8343.4400392248,7706.837897021365],
+  [8244.1400392248,7706.837897021365],
+  [4735.523842661975,3503.497768214323],
+  [4636.223842661975,3337.897768214323],
+  [4536.923842661975,3337.897768214323],
+  [4437.623842661975,3172.2977682143232],
+  [4338.323842661975,3172.2977682143232],
+  [4239.023842661974,3172.2977682143232],
+  [4338.323842661975,3006.6977682143233],
+  [4437.623842661975,2841.0977682143234],
+  [4338.323842661975,2675.4977682143235],
+  [4338.323842661975,2509.8977682143236],
+  [4239.023842661974,2675.4977682143235],
+  [4139.723842661974,2509.8977682143236],
+  [4040.4238426619745,2344.2977682143237],
+  [4139.723842661974,2178.697768214324],
+  [4239.023842661974,2178.697768214324],
+  [4139.723842661974,2344.2977682143237],
+  [4040.4238426619745,2178.697768214324],
+  [4139.723842661974,2013.0977682143237],
+  [4139.723842661974,1847.4977682143235],
+  [4239.023842661974,2013.0977682143237],
+  [4239.023842661974,1847.4977682143235],
+  [4338.323842661975,1847.4977682143235],
+  [4437.623842661975,1847.4977682143235],
+  [4536.923842661975,1681.8977682143234],
+  [4437.623842661975,1516.2977682143232],
+  [4536.923842661975,1516.2977682143232],
+  [4536.923842661975,1350.697768214323],
+  [4437.623842661975,1350.697768214323],
+  [4536.923842661975,1185.097768214323],
+  [4636.223842661975,1019.497768214323],
+  [4536.923842661975,853.897768214323],
+  [4636.223842661975,853.897768214323],
+  [4735.523842661975,688.2977682143231],
+  [4636.223842661975,522.6977682143232],
+  [4636.223842661975,357.09776821432325],
+  [4735.523842661975,357.09776821432325],
+  [4735.523842661975,522.6977682143232],
+  [4636.223842661975,688.2977682143231],
+  [4735.523842661975,853.897768214323],
+  [4834.8238426619755,853.897768214323],
+  [4735.523842661975,1019.497768214323],
+  [4735.523842661975,1185.097768214323],
+  [4735.523842661975,1350.697768214323],
+  [4834.8238426619755,1516.2977682143232],
+  [4735.523842661975,1516.2977682143232],
+  [4834.8238426619755,1350.697768214323],
+  [4834.8238426619755,1185.097768214323],
+  [4934.123842661976,1350.697768214323],
+  [5033.423842661976,1185.097768214323],
+  [5033.423842661976,1019.497768214323],
+  [5033.423842661976,853.897768214323],
+  [4934.123842661976,853.897768214323],
+  [4934.123842661976,1019.497768214323],
+  [4834.8238426619755,1019.497768214323],
+  [4934.123842661976,1185.097768214323],
+  [5033.423842661976,1350.697768214323],
+  [5132.723842661976,1350.697768214323],
+  [5132.723842661976,1185.097768214323],
+  [5232.023842661976,1019.497768214323],
+  [5232.023842661976,1185.097768214323],
+  [5331.323842661976,1019.497768214323],
+  [5430.623842661977,1019.497768214323],
+  [5529.923842661977,1185.097768214323],
+  [5430.623842661977,1350.697768214323],
+  [5430.623842661977,1516.2977682143232],
+  [5529.923842661977,1350.697768214323],
+  [5629.223842661977,1350.697768214323],
+  [5728.523842661977,1350.697768214323],
+  [5728.523842661977,1516.2977682143232],
+  [5728.523842661977,1681.8977682143234],
+  [5629.223842661977,1516.2977682143232],
+  [5529.923842661977,1516.2977682143232],
+  [5629.223842661977,1681.8977682143234],
+  [5529.923842661977,1681.8977682143234],
+  [5430.623842661977,1847.4977682143235],
+  [5331.323842661976,1847.4977682143235],
+  [5331.323842661976,2013.0977682143237],
+  [5232.023842661976,2178.697768214324],
+  [5132.723842661976,2013.0977682143237],
+  [5132.723842661976,2178.697768214324],
+  [5232.023842661976,2013.0977682143237],
+  [5232.023842661976,1847.4977682143235],
+  [5232.023842661976,1681.8977682143234],
+  [5331.323842661976,1681.8977682143234],
+  [5331.323842661976,1516.2977682143232],
+  [5331.323842661976,1350.697768214323],
+  [5232.023842661976,1350.697768214323],
+  [5232.023842661976,1516.2977682143232],
+  [5132.723842661976,1516.2977682143232],
+  [5132.723842661976,1681.8977682143234],
+  [5033.423842661976,1847.4977682143235],
+  [5132.723842661976,1847.4977682143235],
+  [5033.423842661976,2013.0977682143237],
+  [4934.123842661976,2178.697768214324],
+  [5033.423842661976,2344.2977682143237],
+  [4934.123842661976,2344.2977682143237],
+  [4834.8238426619755,2178.697768214324],
+  [4834.8238426619755,2344.2977682143237],
+  [4735.523842661975,2344.2977682143237],
+  [4636.223842661975,2344.2977682143237],
+  [4536.923842661975,2178.697768214324],
+  [4437.623842661975,2013.0977682143237],
+  [4338.323842661975,2178.697768214324],
+  [4437.623842661975,2344.2977682143237],
+  [4536.923842661975,2509.8977682143236],
+  [4636.223842661975,2675.4977682143235],
+  [4636.223842661975,2509.8977682143236],
+  [4536.923842661975,2675.4977682143235],
+  [4636.223842661975,2841.0977682143234],
+  [4536.923842661975,2841.0977682143234],
+  [4636.223842661975,3006.6977682143233],
+  [4735.523842661975,3172.2977682143232],
+  [4834.8238426619755,3006.6977682143233],
+  [4735.523842661975,2841.0977682143234],
+  [4735.523842661975,3006.6977682143233],
+  [4636.223842661975,3172.2977682143232],
+  [4735.523842661975,3337.897768214323],
+  [4834.8238426619755,3503.497768214323],
+  [4735.523842661975,3669.097768214323],
+  [4834.8238426619755,3834.697768214323],
+  [4834.8238426619755,3669.097768214323],
+  [4934.123842661976,3503.497768214323],
+  [5033.423842661976,3503.497768214323],
+  [5033.423842661976,3337.897768214323],
+  [4934.123842661976,3337.897768214323],
+  [4834.8238426619755,3172.2977682143232],
+  [4834.8238426619755,3337.897768214323],
+  [4934.123842661976,3172.2977682143232],
+  [5033.423842661976,3006.6977682143233],
+  [5132.723842661976,2841.0977682143234],
+  [5132.723842661976,3006.6977682143233],
+  [5232.023842661976,3172.2977682143232],
+  [5232.023842661976,3337.897768214323],
+  [5132.723842661976,3337.897768214323],
+  [5232.023842661976,3503.497768214323],
+  [5331.323842661976,3337.897768214323],
+  [5331.323842661976,3503.497768214323],
+  [5430.623842661977,3669.097768214323],
+  [5331.323842661976,3669.097768214323],
+  [5430.623842661977,3503.497768214323],
+  [5430.623842661977,3337.897768214323],
+  [5529.923842661977,3172.2977682143232],
+  [5529.923842661977,3337.897768214323],
+  [5629.223842661977,3337.897768214323],
+  [5728.523842661977,3337.897768214323],
+  [5728.523842661977,3503.497768214323],
+  [5827.823842661977,3503.497768214323],
+  [5927.1238426619775,3669.097768214323],
+  [6026.423842661978,3669.097768214323],
+  [6125.723842661978,3503.497768214323],
+  [6125.723842661978,3669.097768214323],
+  [6225.023842661978,3503.497768214323],
+  [6225.023842661978,3337.897768214323],
+  [6324.323842661978,3337.897768214323],
+  [6423.623842661978,3503.497768214323],
+  [6324.323842661978,3669.097768214323],
+  [6225.023842661978,3669.097768214323],
+  [6324.323842661978,3834.697768214323],
+  [6423.623842661978,3834.697768214323],
+  [6324.323842661978,4000.297768214323],
+  [6225.023842661978,3834.697768214323],
+  [6125.723842661978,3834.697768214323],
+  [6125.723842661978,4000.297768214323],
+  [6225.023842661978,4000.297768214323],
+  [6225.023842661978,4165.897768214322],
+  [6225.023842661978,4331.497768214322],
+  [6125.723842661978,4165.897768214322],
+  [6026.423842661978,4000.2977682143223],
+  [5927.1238426619775,4165.897768214322],
+  [6026.423842661978,4331.497768214322],
+  [6026.423842661978,4497.097768214321],
+  [5927.1238426619775,4497.097768214321],
+  [5827.823842661977,4662.697768214321],
+  [5728.523842661977,4828.29776821432],
+  [5827.823842661977,4828.29776821432],
+  [5927.1238426619775,4828.29776821432],
+  [5927.1238426619775,4662.697768214321],
+  [5827.823842661977,4497.097768214321],
+  [5927.1238426619775,4331.497768214322],
+  [5827.823842661977,4165.897768214322],
+  [5728.523842661977,4331.497768214322],
+  [5728.523842661977,4165.897768214322],
+  [5629.223842661977,4000.2977682143223],
+  [5629.223842661977,3834.6977682143224],
+  [5529.923842661977,3669.0977682143225],
+  [5629.223842661977,3503.4977682143226],
+  [5728.523842661977,3669.0977682143225],
+  [5827.823842661977,3669.0977682143225],
+  [5927.1238426619775,3834.6977682143224],
+  [5927.1238426619775,4000.2977682143223],
+  [6026.423842661978,4165.897768214322],
+  [6125.723842661978,4331.497768214322],
+  [6225.023842661978,4497.097768214321],
+  [6225.023842661978,4662.697768214321],
+  [6324.323842661978,4662.697768214321],
+  [6225.023842661978,4828.29776821432],
+  [6324.323842661978,4828.29776821432],
+  [6423.623842661978,4828.29776821432],
+  [6324.323842661978,4993.8977682143195],
+  [6225.023842661978,5159.497768214319],
+  [6125.723842661978,5159.497768214319],
+  [6026.423842661978,5325.097768214318],
+  [5927.1238426619775,5490.697768214318],
+  [6026.423842661978,5656.297768214317],
+  [5927.1238426619775,5821.897768214317],
+  [5927.1238426619775,5987.497768214316],
+  [6026.423842661978,5987.497768214316],
+  [6026.423842661978,5821.897768214317],
+  [5927.1238426619775,5656.297768214317],
+  [5827.823842661977,5656.297768214317],
+  [5827.823842661977,5490.697768214318],
+  [5728.523842661977,5490.697768214318],
+  [5629.223842661977,5325.097768214318],
+  [5629.223842661977,5159.497768214319],
+  [5529.923842661977,4993.8977682143195],
+  [5529.923842661977,5159.497768214319],
+  [5629.223842661977,4993.8977682143195],
+  [5629.223842661977,4828.29776821432],
+  [5529.923842661977,4662.697768214321],
+  [5430.623842661977,4828.29776821432],
+  [5529.923842661977,4828.29776821432],
+  [5629.223842661977,4662.697768214321],
+  [5728.523842661977,4662.697768214321],
+  [5629.223842661977,4497.097768214321],
+  [5728.523842661977,4497.097768214321],
+  [5827.823842661977,4331.497768214322],
+  [10216.161365168813,2951.605409896135],
+  [10116.861365168812,2951.605409896135],
+  [10017.56136516881,3117.205409896135],
+  [9918.26136516881,3117.205409896135],
+  [9818.961365168809,3117.205409896135],
+  [9719.661365168808,3282.8054098961347],
+  [9620.361365168807,3282.8054098961347],
+  [9620.361365168807,3117.205409896135],
+  [9521.061365168805,2951.605409896135],
+  [9521.061365168805,2786.005409896135],
+  [9620.361365168807,2786.005409896135],
+  [9719.661365168808,2786.005409896135],
+  [9818.961365168809,2620.405409896135],
+  [9918.26136516881,2786.005409896135],
+  [9818.961365168809,2951.605409896135],
+  [9818.961365168809,2786.005409896135],
+  [9719.661365168808,2620.405409896135],
+  [9719.661365168808,2454.805409896135],
+  [9620.361365168807,2289.2054098961353],
+  [9521.061365168805,2123.6054098961354],
+  [9620.361365168807,1958.0054098961352],
+  [9719.661365168808,2123.6054098961354],
+  [9818.961365168809,2289.2054098961353],
+  [9818.961365168809,2123.6054098961354],
+  [9818.961365168809,1958.0054098961352],
+  [9719.661365168808,1958.0054098961352],
+  [9620.361365168807,1792.405409896135],
+  [9620.361365168807,1626.805409896135],
+  [9521.061365168805,1461.2054098961348],
+  [9421.761365168804,1295.6054098961347],
+  [9521.061365168805,1130.0054098961346],
+  [9521.061365168805,964.4054098961345],
+  [9421.761365168804,964.4054098961345],
+  [9521.061365168805,798.8054098961346],
+  [9620.361365168807,798.8054098961346],
+  [9620.361365168807,964.4054098961345],
+  [9620.361365168807,1130.0054098961346],
+  [9620.361365168807,1295.6054098961347],
+  [9620.361365168807,1461.2054098961348],
+  [9719.661365168808,1295.6054098961347],
+  [9818.961365168809,1130.0054098961346],
+  [9918.26136516881,964.4054098961345],
+  [9818.961365168809,964.4054098961345],
+  [9918.26136516881,798.8054098961346],
+  [10017.56136516881,633.2054098961347],
+  [9918.26136516881,467.60540989613474],
+  [9918.26136516881,302.0054098961348],
+  [10017.56136516881,302.0054098961348],
+  [10116.861365168812,136.40540989613478],
+  [10116.861365168812,302.0054098961348],
+  [10116.861365168812,467.60540989613474],
+  [10116.861365168812,633.2054098961347],
+  [10216.161365168813,633.2054098961347],
+  [10216.161365168813,798.8054098961346],
+  [10315.461365168814,633.2054098961347],
+  [10315.461365168814,798.8054098961346],
+  [10414.761365168815,798.8054098961346],
+  [10514.061365168816,633.2054098961347],
+  [10514.061365168816,798.8054098961346],
+  [10414.761365168815,964.4054098961345],
+  [10315.461365168814,964.4054098961345],
+  [10216.161365168813,964.4054098961345],
+  [10116.861365168812,798.8054098961346],
+  [10017.56136516881,798.8054098961346],
+  [10116.861365168812,964.4054098961345],
+  [10216.161365168813,1130.0054098961346],
+  [10116.861365168812,1130.0054098961346],
+  [10216.161365168813,1295.6054098961347],
+  [10216.161365168813,1461.2054098961348],
+  [10315.461365168814,1626.805409896135],
+  [10315.461365168814,1792.405409896135],
+  [10216.161365168813,1958.0054098961352],
+  [10216.161365168813,1792.405409896135],
+  [10116.861365168812,1792.405409896135],
+  [10017.56136516881,1958.0054098961352],
+  [9918.26136516881,2123.6054098961354],
+  [9918.26136516881,1958.0054098961352],
+  [10017.56136516881,2123.6054098961354],
+  [10116.861365168812,2123.6054098961354],
+  [10017.56136516881,2289.2054098961353],
+  [10017.56136516881,2454.805409896135],
+  [10116.861365168812,2289.2054098961353],
+  [10216.161365168813,2454.805409896135],
+  [10315.461365168814,2620.405409896135],
+  [10315.461365168814,2454.805409896135],
+  [10315.461365168814,2289.2054098961353],
+  [10414.761365168815,2454.805409896135],
+  [10514.061365168816,2620.405409896135],
+  [10613.361365168817,2786.005409896135],
+  [10514.061365168816,2786.005409896135],
+  [10613.361365168817,2620.405409896135],
+  [10514.061365168816,2454.805409896135],
+  [10514.061365168816,2289.2054098961353],
+  [10613.361365168817,2289.2054098961353],
+  [10712.661365168819,2289.2054098961353],
+  [10811.96136516882,2454.805409896135],
+  [10911.26136516882,2289.2054098961353],
+  [10811.96136516882,2289.2054098961353],
+  [10712.661365168819,2454.805409896135],
+  [10712.661365168819,2620.405409896135],
+  [10811.96136516882,2786.005409896135],
+  [10911.26136516882,2620.405409896135],
+  [10911.26136516882,2786.005409896135],
+  [11010.561365168822,2620.405409896135],
+  [10911.26136516882,2454.805409896135],
+  [10811.96136516882,2620.405409896135],
+  [10712.661365168819,2786.005409896135],
+  [10811.96136516882,2951.605409896135],
+  [10911.26136516882,2951.605409896135],
+  [10811.96136516882,3117.205409896135],
+  [10712.661365168819,2951.605409896135],
+  [10613.361365168817,2951.605409896135],
+  [10514.061365168816,2951.605409896135],
+  [10414.761365168815,3117.205409896135],
+  [10414.761365168815,2951.605409896135],
+  [10315.461365168814,2786.005409896135],
+  [10216.161365168813,2620.405409896135],
+  [10216.161365168813,2786.005409896135],
+  [10315.461365168814,2951.605409896135],
+  [10315.461365168814,3117.205409896135],
+  [10216.161365168813,3117.205409896135],
+  [10116.861365168812,3117.205409896135],
+  [10017.56136516881,3282.8054098961347],
+  [9918.26136516881,3448.4054098961346],
+  [9818.961365168809,3448.4054098961346],
+  [9818.961365168809,3614.0054098961346],
+  [9719.661365168808,3448.4054098961346],
+  [9818.961365168809,3282.8054098961347],
+  [9719.661365168808,3117.205409896135],
+  [9620.361365168807,2951.605409896135],
+  [9521.061365168805,3117.205409896135],
+  [9521.061365168805,3282.8054098961347],
+  [9421.761365168804,3117.205409896135],
+  [9421.761365168804,3282.8054098961347],
+  [9322.461365168803,3117.205409896135],
+  [9421.761365168804,2951.605409896135],
+  [9322.461365168803,2951.605409896135],
+  [9223.161365168802,2786.005409896135],
+  [9322.461365168803,2620.405409896135],
+  [9421.761365168804,2454.805409896135],
+  [9521.061365168805,2289.2054098961353],
+  [9421.761365168804,2123.6054098961354],
+  [9421.761365168804,1958.0054098961352],
+  [9421.761365168804,1792.405409896135],
+  [9521.061365168805,1626.805409896135],
+  [9421.761365168804,1626.805409896135],
+  [9322.461365168803,1792.405409896135],
+  [9322.461365168803,1626.805409896135],
+  [9322.461365168803,1461.2054098961348],
+  [9421.761365168804,1461.2054098961348],
+  [9521.061365168805,1295.6054098961347],
+  [9421.761365168804,1130.0054098961346],
+  [9322.461365168803,964.4054098961345],
+  [9223.161365168802,964.4054098961345],
+  [9223.161365168802,798.8054098961346],
+  [9322.461365168803,633.2054098961347],
+  [9421.761365168804,798.8054098961346],
+  [9421.761365168804,633.2054098961347],
+  [9521.061365168805,633.2054098961347],
+  [9421.761365168804,467.60540989613474],
+  [9421.761365168804,302.0054098961348],
+  [9322.461365168803,136.40540989613478],
+  [9223.161365168802,302.0054098961348],
+  [9123.861365168801,302.0054098961348],
+  [9024.5613651688,136.40540989613478],
+  [9123.861365168801,136.40540989613478],
+  [9223.161365168802,136.40540989613478],
+  [9322.461365168803,302.0054098961348],
+  [9421.761365168804,136.40540989613478],
+  [9521.061365168805,136.40540989613478],
+  [9620.361365168807,136.40540989613478],
+  [9620.361365168807,302.0054098961348],
+  [9521.061365168805,302.0054098961348],
+  [9521.061365168805,467.60540989613474],
+  [9620.361365168807,467.60540989613474],
+  [9719.661365168808,302.0054098961348],
+  [9719.661365168808,136.40540989613478],
+  [9818.961365168809,136.40540989613478],
+  [9918.26136516881,136.40540989613478],
+  [10017.56136516881,136.40540989613478],
+  [366.07287160549004,5394.185440937868],
+  [465.37287160549005,5394.185440937868],
+  [465.37287160549005,5559.785440937868],
+  [366.0728716054901,5559.785440937868],
+  [366.0728716054901,5725.385440937867],
+  [266.77287160549014,5725.385440937867],
+  [167.47287160549016,5559.785440937868],
+  [266.77287160549014,5559.785440937868],
+  [266.77287160549014,5394.185440937868],
+  [266.77287160549014,5228.585440937869],
+  [167.47287160549016,5394.185440937868],
+  [68.17287160549016,5228.585440937869],
+  [167.47287160549013,5062.9854409378695],
+  [68.17287160549013,4897.38544093787],
+  [167.47287160549013,4731.785440937871],
+  [266.77287160549014,4731.785440937871],
+  [167.47287160549016,4566.185440937871],
+  [68.17287160549016,4566.185440937871],
+  [68.17287160549016,4731.785440937871],
+  [167.47287160549013,4897.38544093787],
+  [68.17287160549013,5062.9854409378695],
+  [167.47287160549013,5228.585440937869],
+  [266.77287160549014,5062.9854409378695],
+  [366.0728716054901,4897.38544093787],
+  [266.77287160549014,4897.38544093787],
+  [366.0728716054901,4731.785440937871],
+  [465.37287160549005,4897.38544093787],
+  [366.0728716054901,5062.9854409378695],
+  [465.37287160549005,5062.9854409378695],
+  [366.0728716054901,5228.585440937869],
+  [465.37287160549005,5228.585440937869],
+  [564.6728716054901,5394.185440937868],
+  [663.9728716054901,5228.585440937869],
+  [564.6728716054901,5062.9854409378695],
+  [663.9728716054901,4897.38544093787],
+  [763.2728716054902,4731.785440937871],
+  [862.5728716054903,4566.185440937871],
+  [961.8728716054903,4731.785440937871],
+  [862.5728716054903,4731.785440937871],
+  [961.8728716054903,4566.185440937871],
+  [862.5728716054903,4400.585440937872],
+  [961.8728716054903,4234.985440937872],
+  [1061.1728716054904,4400.585440937872],
+  [1160.4728716054904,4234.985440937872],
+  [1160.4728716054904,4400.585440937872],
+  [1259.7728716054903,4234.985440937872],
+  [1359.0728716054903,4069.3854409378723],
+  [1458.3728716054902,4069.3854409378723],
+  [1557.6728716054902,4234.985440937872],
+  [1656.9728716054901,4400.585440937872],
+  [1557.6728716054902,4400.585440937872],
+  [1458.3728716054902,4400.585440937872],
+  [1359.0728716054903,4566.185440937871],
+  [1359.0728716054903,4731.785440937871],
+  [1259.7728716054903,4731.785440937871],
+  [1359.0728716054903,4897.38544093787],
+  [1458.3728716054902,4731.785440937871],
+  [1458.3728716054902,4897.38544093787],
+  [1359.0728716054903,5062.9854409378695],
+  [1259.7728716054903,5228.585440937869],
+  [1259.7728716054903,5062.9854409378695],
+  [1259.7728716054903,4897.38544093787],
+  [1160.4728716054904,5062.9854409378695],
+  [1160.4728716054904,5228.585440937869],
+  [1061.1728716054904,5228.585440937869],
+  [1061.1728716054904,5062.9854409378695],
+  [961.8728716054903,5228.585440937869],
+  [862.5728716054903,5062.9854409378695],
+  [961.8728716054903,5062.9854409378695],
+  [961.8728716054903,4897.38544093787],
+  [1061.1728716054904,4897.38544093787],
+  [1160.4728716054904,4731.785440937871],
+  [1259.7728716054903,4566.185440937871],
+  [1359.0728716054903,4400.585440937872],
+  [1458.3728716054902,4566.185440937871],
+  [1557.6728716054902,4566.185440937871],
+  [1656.9728716054901,4731.785440937871],
+  [1557.6728716054902,4897.38544093787],
+  [1458.3728716054902,5062.9854409378695],
+  [1557.6728716054902,5228.585440937869],
+  [1656.9728716054901,5062.9854409378695],
+  [1756.27287160549,5062.9854409378695],
+  [1756.27287160549,4897.38544093787],
+  [1855.57287160549,5062.9854409378695],
+  [1954.87287160549,4897.38544093787],
+  [2054.17287160549,5062.9854409378695],
+  [1954.87287160549,5062.9854409378695],
+  [2054.17287160549,5228.585440937869],
+  [2153.4728716054897,5228.585440937869],
+  [2252.7728716054894,5062.9854409378695],
+  [2352.072871605489,5228.585440937869],
+  [2451.372871605489,5394.185440937868],
+  [2352.072871605489,5394.185440937868],
+  [2252.7728716054894,5228.585440937869],
+  [2153.4728716054897,5062.9854409378695],
+  [2153.4728716054897,4897.38544093787],
+  [2252.7728716054894,4897.38544093787],
+  [2352.072871605489,4731.785440937871],
+  [2252.7728716054894,4731.785440937871],
+  [2153.4728716054897,4731.785440937871],
+  [2054.17287160549,4566.185440937871],
+  [1954.87287160549,4731.785440937871],
+  [1855.57287160549,4897.38544093787],
+  [1756.27287160549,4731.785440937871],
+  [1855.57287160549,4731.785440937871],
+  [1855.57287160549,4566.185440937871],
+  [1756.27287160549,4566.185440937871],
+  [1656.9728716054901,4566.185440937871],
+  [1557.6728716054902,4731.785440937871],
+  [1656.9728716054901,4897.38544093787],
+  [1557.6728716054902,5062.9854409378695],
+  [1458.3728716054902,5228.585440937869],
+  [1359.0728716054903,5228.585440937869],
+  [1259.7728716054903,5394.185440937868],
+  [1259.7728716054903,5559.785440937868],
+  [1160.4728716054904,5559.785440937868],
+  [1061.1728716054904,5559.785440937868],
+  [1160.4728716054904,5725.385440937867],
+  [1259.7728716054903,5725.385440937867],
+  [1359.0728716054903,5559.785440937868],
+  [1458.3728716054902,5725.385440937867],
+  [1458.3728716054902,5559.785440937868],
+  [1359.0728716054903,5725.385440937867],
+  [1259.7728716054903,5890.985440937867],
+  [1359.0728716054903,5890.985440937867],
+  [1259.7728716054903,6056.585440937866],
+  [1359.0728716054903,6222.185440937866],
+  [1458.3728716054902,6222.185440937866],
+  [1458.3728716054902,6387.785440937865],
+  [1557.6728716054902,6222.185440937866],
+  [1557.6728716054902,6387.785440937865],
+  [1656.9728716054901,6222.185440937866],
+  [1756.27287160549,6056.585440937866],
+  [1855.57287160549,5890.985440937867],
+  [1756.27287160549,5890.985440937867],
+  [1656.9728716054901,6056.585440937866],
+  [1557.6728716054902,5890.985440937867],
+  [1458.3728716054902,5890.985440937867],
+  [1359.0728716054903,6056.585440937866],
+  [1259.7728716054903,6222.185440937866],
+  [1160.4728716054904,6056.585440937866],
+  [1061.1728716054904,5890.985440937867],
+  [1061.1728716054904,6056.585440937866],
+  [1160.4728716054904,6222.185440937866],
+  [1061.1728716054904,6222.185440937866],
+  [961.8728716054903,6222.185440937866],
+  [961.8728716054903,6056.585440937866],
+  [961.8728716054903,5890.985440937867],
+  [961.8728716054903,5725.385440937867],
+  [862.5728716054903,5559.785440937868],
+  [763.2728716054902,5725.385440937867],
+  [862.5728716054903,5725.385440937867],
+  [763.2728716054902,5890.985440937867],
+  [663.9728716054901,5725.385440937867],
+  [763.2728716054902,5559.785440937868],
+  [763.2728716054902,5394.185440937868],
+  [862.5728716054903,5228.585440937869],
+  [961.8728716054903,5394.185440937868],
+  [1061.1728716054904,5394.185440937868],
+  [961.8728716054903,5559.785440937868],
+  [862.5728716054903,5394.185440937868],
+  [763.2728716054902,5228.585440937869],
+  [663.9728716054901,5062.9854409378695],
+  [763.2728716054902,5062.9854409378695],
+  [763.2728716054902,4897.38544093787],
+  [663.9728716054901,4731.785440937871],
+  [564.6728716054901,4731.785440937871],
+  [465.37287160549005,4566.185440937871],
+  [366.0728716054901,4566.185440937871],
+  [465.37287160549005,4731.785440937871],
+  [564.6728716054901,4566.185440937871],
+  [465.37287160549005,4400.585440937872],
+  [366.0728716054901,4400.585440937872],
+  [266.77287160549014,4234.985440937872],
+  [167.47287160549016,4234.985440937872],
+  [266.77287160549014,4400.585440937872],
+  [266.77287160549014,4566.185440937871],
+  [167.47287160549016,4400.585440937872],
+  [68.17287160549016,4234.985440937872],
+  [167.47287160549013,4069.3854409378723],
+  [68.17287160549013,3903.7854409378724],
+  [68.17287160549013,4069.3854409378723],
+  [167.47287160549013,3903.7854409378724],
+  [266.77287160549014,3903.7854409378724],
+  [366.0728716054901,3738.1854409378725],
+  [266.77287160549014,3738.1854409378725],
+  [266.77287160549014,3572.5854409378726],
+  [167.47287160549016,3406.9854409378727],
+  [167.47287160549016,3241.3854409378728],
+  [266.77287160549014,3241.3854409378728],
+  [266.77287160549014,3406.9854409378727],
+  [366.0728716054901,3572.5854409378726],
+  [465.37287160549005,3738.1854409378725],
+  [465.37287160549005,3903.7854409378724],
+  [366.0728716054901,4069.3854409378723],
+  [366.0728716054901,4234.985440937872],
+  [465.37287160549005,4234.985440937872],
+  [564.6728716054901,4069.3854409378723],
+  [465.37287160549005,4069.3854409378723],
+  [564.6728716054901,4234.985440937872],
+  [663.9728716054901,4069.3854409378723],
+  [663.9728716054901,4234.985440937872],
+  [663.9728716054901,4400.585440937872],
+  [763.2728716054902,4566.185440937871],
+  [763.2728716054902,4400.585440937872],
+  [663.9728716054901,4566.185440937871],
+  [564.6728716054901,4400.585440937872],
+  [19431.915041401327,3495.506142643713],
+  [19332.61504140133,3661.1061426437127],
+  [19431.915041401327,3661.1061426437127],
+  [19531.215041401327,3661.1061426437127],
+  [19630.515041401326,3495.506142643713],
+  [19630.515041401326,3661.1061426437127],
+  [19729.815041401325,3826.7061426437126],
+  [19630.515041401326,3826.7061426437126],
+  [19729.815041401325,3992.3061426437125],
+  [19630.515041401326,3992.3061426437125],
+  [19630.515041401326,4157.906142643712],
+  [19630.515041401326,4323.506142643711],
+  [19531.215041401327,4157.906142643712],
+  [19431.915041401327,4323.506142643711],
+  [19531.215041401327,4489.106142643711],
+  [19431.915041401327,4654.70614264371],
+  [19332.61504140133,4654.70614264371],
+  [19332.61504140133,4820.30614264371],
+  [19332.61504140133,4985.906142643709],
+  [19233.31504140133,4985.906142643709],
+  [19134.01504140133,5151.506142643709],
+  [19034.71504140133,5151.506142643709],
+  [19134.01504140133,5317.106142643708],
+  [19034.71504140133,5317.106142643708],
+  [19034.71504140133,5482.706142643708],
+  [18935.41504140133,5648.306142643707],
+  [18836.115041401332,5813.9061426437065],
+  [18836.115041401332,5979.506142643706],
+  [18935.41504140133,5979.506142643706],
+  [19034.71504140133,6145.106142643705],
+  [19034.71504140133,5979.506142643706],
+  [19034.71504140133,5813.9061426437065],
+  [19134.01504140133,5648.306142643707],
+  [19233.31504140133,5648.306142643707],
+  [19134.01504140133,5813.9061426437065],
+  [19134.01504140133,5979.506142643706],
+  [19233.31504140133,5813.9061426437065],
+  [19233.31504140133,5979.506142643706],
+  [19332.61504140133,6145.106142643705],
+  [19332.61504140133,6310.706142643705],
+  [19233.31504140133,6310.706142643705],
+  [19233.31504140133,6476.306142643704],
+  [19332.61504140133,6476.306142643704],
+  [19431.915041401327,6641.906142643704],
+  [19332.61504140133,6807.506142643703],
+  [19332.61504140133,6641.906142643704],
+  [19431.915041401327,6476.306142643704],
+  [19431.915041401327,6310.706142643705],
+  [19531.215041401327,6145.106142643705],
+  [19431.915041401327,5979.506142643706],
+  [19431.915041401327,6145.106142643705],
+  [19531.215041401327,5979.506142643706],
+  [19630.515041401326,5813.9061426437065],
+  [19630.515041401326,5979.506142643706],
+  [19729.815041401325,5813.9061426437065],
+  [19829.115041401325,5979.506142643706],
+  [19729.815041401325,5979.506142643706],
+  [19729.815041401325,6145.106142643705],
+  [19729.815041401325,6310.706142643705],
+  [19630.515041401326,6476.306142643704],
+  [19729.815041401325,6476.306142643704],
+  [19630.515041401326,6310.706142643705],
+  [19531.215041401327,6310.706142643705],
+  [19531.215041401327,6476.306142643704],
+  [19630.515041401326,6641.906142643704],
+  [19729.815041401325,6807.506142643703],
+  [19829.115041401325,6973.106142643703],
+  [19928.415041401324,6973.106142643703],
+  [19928.415041401324,7138.706142643702],
+  [20027.715041401323,7138.706142643702],
+  [20027.715041401323,7304.306142643702],
+  [19928.415041401324,7304.306142643702],
+  [19829.115041401325,7304.306142643702],
+  [19829.115041401325,7469.906142643701],
+  [19928.415041401324,7469.906142643701],
+  [19928.415041401324,7635.5061426437005],
+  [19928.415041401324,7801.1061426437],
+  [20027.715041401323,7635.5061426437005],
+  [20027.715041401323,7801.1061426437],
+  [20127.015041401322,7801.1061426437],
+  [20226.31504140132,7801.1061426437],
+  [20325.61504140132,7801.1061426437],
+  [20226.31504140132,7635.5061426437005],
+  [20226.31504140132,7469.906142643701],
+  [20226.31504140132,7304.306142643702],
+  [20127.015041401322,7304.306142643702],
+  [20027.715041401323,7469.906142643701],
+  [20127.015041401322,7469.906142643701],
+  [20127.015041401322,7635.5061426437005],
+  [2748.790306732237,2362.9553147492866],
+  [2848.0903067322365,2528.5553147492865],
+  [2748.790306732237,2694.1553147492864],
+  [2649.490306732237,2859.7553147492863],
+  [2748.790306732237,3025.355314749286],
+  [2848.0903067322365,2859.7553147492863],
+  [2848.0903067322365,2694.1553147492864],
+  [2947.3903067322362,2694.1553147492864],
+  [3046.690306732236,2859.7553147492863],
+  [3145.9903067322357,2694.1553147492864],
+  [3145.9903067322357,2528.5553147492865],
+  [3046.690306732236,2694.1553147492864],
+  [3145.9903067322357,2859.7553147492863],
+  [3046.690306732236,3025.355314749286],
+  [3145.9903067322357,3025.355314749286],
+  [3245.2903067322354,3190.955314749286],
+  [3245.2903067322354,3356.555314749286],
+  [3344.590306732235,3522.155314749286],
+  [3443.890306732235,3356.555314749286],
+  [3543.1903067322346,3356.555314749286],
+  [3642.4903067322343,3190.955314749286],
+  [3741.790306732234,3025.355314749286],
+  [3741.790306732234,2859.7553147492863],
+  [3841.090306732234,3025.355314749286],
+  [3841.090306732234,3190.955314749286],
+  [3741.790306732234,3190.955314749286],
+  [3642.4903067322343,3025.355314749286],
+  [3543.1903067322346,3025.355314749286],
+  [3543.1903067322346,2859.7553147492863],
+  [3443.890306732235,3025.355314749286],
+  [3443.890306732235,3190.955314749286],
+  [3543.1903067322346,3190.955314749286],
+  [3642.4903067322343,3356.555314749286],
+  [3543.1903067322346,3522.155314749286],
+  [3443.890306732235,3687.755314749286],
+  [3443.890306732235,3853.3553147492858],
+  [3344.590306732235,3687.755314749286],
+  [3245.2903067322354,3853.3553147492858],
+  [3245.2903067322354,3687.755314749286],
+  [3145.9903067322357,3687.755314749286],
+  [3046.690306732236,3853.3553147492858],
+  [3145.9903067322357,4018.9553147492857],
+  [3145.9903067322357,3853.3553147492858],
+  [3046.690306732236,3687.755314749286],
+  [3145.9903067322357,3522.155314749286],
+  [3145.9903067322357,3356.555314749286],
+  [3145.9903067322357,3190.955314749286],
+  [3046.690306732236,3190.955314749286],
+  [3046.690306732236,3356.555314749286],
+  [2947.3903067322362,3356.555314749286],
+  [2848.0903067322365,3190.955314749286],
+  [2947.3903067322362,3025.355314749286],
+  [2848.0903067322365,3025.355314749286],
+  [2748.790306732237,2859.7553147492863],
+  [2649.490306732237,2694.1553147492864],
+  [2748.790306732237,2528.5553147492865],
+  [2848.0903067322365,2362.9553147492866],
+  [2748.790306732237,2197.3553147492867],
+  [2649.490306732237,2362.9553147492866],
+  [2649.490306732237,2197.3553147492867],
+  [2550.1903067322373,2362.9553147492866],
+  [2450.8903067322376,2362.9553147492866],
+  [2351.590306732238,2528.5553147492865],
+  [2252.290306732238,2528.5553147492865],
+  [2351.590306732238,2362.9553147492866],
+  [2252.290306732238,2197.3553147492867],
+  [2351.590306732238,2197.3553147492867],
+  [2351.590306732238,2031.7553147492865],
+  [2351.590306732238,1866.1553147492864],
+  [2252.290306732238,1866.1553147492864],
+  [2351.590306732238,1700.5553147492863],
+  [2450.8903067322376,1534.9553147492861],
+  [2351.590306732238,1369.355314749286],
+  [2252.290306732238,1203.7553147492858],
+  [2252.290306732238,1369.355314749286],
+  [2252.290306732238,1534.9553147492861],
+  [2152.9903067322384,1369.355314749286],
+  [2053.6903067322387,1369.355314749286],
+  [1954.3903067322387,1203.7553147492858],
+  [1855.0903067322388,1203.7553147492858],
+  [1755.7903067322388,1038.1553147492857],
+  [1656.4903067322389,1038.1553147492857],
+  [1557.190306732239,872.5553147492857],
+  [1457.890306732239,1038.1553147492857],
+  [1457.890306732239,872.5553147492857],
+  [1457.890306732239,706.9553147492858],
+  [1557.190306732239,706.9553147492858],
+  [1656.4903067322389,872.5553147492857],
+  [1656.4903067322389,706.9553147492858],
+  [1755.7903067322388,706.9553147492858],
+  [1656.4903067322389,541.3553147492859],
+  [1557.190306732239,375.7553147492859],
+  [1656.4903067322389,210.1553147492859],
+  [1755.7903067322388,44.55531474928592],
+  [1656.4903067322389,44.55531474928592],
+  [1557.190306732239,210.1553147492859],
+  [1457.890306732239,210.1553147492859],
+  [1457.890306732239,44.55531474928592],
+  [1358.590306732239,210.1553147492859],
+  [1358.590306732239,375.75531474928584],
+  [1259.290306732239,210.15531474928585],
+  [1259.290306732239,375.75531474928584],
+  [1259.290306732239,541.3553147492859],
+  [1358.590306732239,706.9553147492858],
+  [1358.590306732239,872.5553147492857],
+  [1259.290306732239,706.9553147492858],
+  [1259.290306732239,872.5553147492857],
+  [1259.290306732239,1038.1553147492857],
+  [1358.590306732239,1203.7553147492858],
+  [1358.590306732239,1038.1553147492857],
+  [1457.890306732239,1203.7553147492858],
+  [1557.190306732239,1369.355314749286],
+  [1656.4903067322389,1203.7553147492858],
+  [1557.190306732239,1203.7553147492858],
+  [1557.190306732239,1038.1553147492857],
+  [17254.572515546668,1460.5807801244923],
+  [17353.872515546667,1626.1807801244925],
+  [17453.172515546667,1791.7807801244926],
+  [17552.472515546666,1791.7807801244926],
+  [17453.172515546667,1626.1807801244925],
+  [17353.872515546667,1791.7807801244926],
+  [17453.172515546667,1957.3807801244927],
+  [17353.872515546667,2122.980780124493],
+  [17453.172515546667,2288.580780124493],
+  [17353.872515546667,2454.1807801244927],
+  [17453.172515546667,2619.7807801244926],
+  [17552.472515546666,2619.7807801244926],
+  [17453.172515546667,2785.3807801244925],
+  [17353.872515546667,2619.7807801244926],
+  [17254.572515546668,2454.1807801244927],
+  [17254.572515546668,2288.580780124493],
+  [17353.872515546667,2288.580780124493],
+  [17453.172515546667,2122.980780124493],
+  [17552.472515546666,2288.580780124493],
+  [17552.472515546666,2454.1807801244927],
+  [17453.172515546667,2454.1807801244927],
+  [4447.67624466283,4761.1416826913],
+  [4546.97624466283,4595.541682691301],
+  [4546.97624466283,4429.941682691301],
+  [4447.67624466283,4429.941682691301],
+  [4447.67624466283,4595.541682691301],
+  [4348.37624466283,4595.541682691301],
+  [4249.07624466283,4595.541682691301],
+  [4348.37624466283,4761.1416826913],
+  [4249.07624466283,4761.1416826913],
+  [4348.37624466283,4926.7416826912995],
+  [4348.37624466283,5092.341682691299],
+  [4447.67624466283,5257.941682691298],
+  [4546.97624466283,5257.941682691298],
+  [4646.27624466283,5092.341682691299],
+  [4546.97624466283,5092.341682691299],
+  [4646.27624466283,4926.7416826912995],
+  [4646.27624466283,4761.1416826913],
+  [4546.97624466283,4761.1416826913],
+  [4646.27624466283,4595.541682691301],
+  [4745.5762446628305,4595.541682691301],
+  [4646.27624466283,4429.941682691301],
+  [4745.5762446628305,4429.941682691301],
+  [4844.876244662831,4595.541682691301],
+  [4745.5762446628305,4761.1416826913],
+  [4745.5762446628305,4926.7416826912995],
+  [4844.876244662831,4761.1416826913],
+  [4944.176244662831,4761.1416826913],
+  [5043.476244662831,4926.7416826912995],
+  [5043.476244662831,4761.1416826913],
+  [5142.776244662831,4926.7416826912995],
+  [5142.776244662831,4761.1416826913],
+  [5242.076244662831,4595.541682691301],
+  [5142.776244662831,4595.541682691301],
+  [5242.076244662831,4429.941682691301],
+  [5242.076244662831,4264.341682691302],
+  [5142.776244662831,4429.941682691301],
+  [5043.476244662831,4595.541682691301],
+  [5043.476244662831,4429.941682691301],
+  [5043.476244662831,4264.341682691302],
+  [5142.776244662831,4098.741682691302],
+  [5043.476244662831,4098.741682691302],
+  [4944.176244662831,3933.1416826913023],
+  [4944.176244662831,4098.741682691302],
+  [4944.176244662831,4264.341682691302],
+  [4844.876244662831,4098.741682691302],
+  [4745.5762446628305,4264.341682691302],
+  [4646.27624466283,4098.741682691302],
+  [4546.97624466283,3933.1416826913023],
+  [4447.67624466283,4098.741682691302],
+  [4546.97624466283,4264.341682691302],
+  [4447.67624466283,4264.341682691302],
+  [4546.97624466283,4098.741682691302],
+  [4646.27624466283,3933.1416826913023],
+  [4546.97624466283,3767.5416826913024],
+  [4447.67624466283,3601.9416826913025],
+  [4447.67624466283,3767.5416826913024],
+  [4348.37624466283,3767.5416826913024],
+  [4348.37624466283,3933.1416826913023],
+  [4249.07624466283,3767.5416826913024],
+  [4249.07624466283,3933.1416826913023],
+  [4149.776244662829,3933.1416826913023],
+  [4050.4762446628297,4098.741682691302],
+  [4050.4762446628297,3933.1416826913023],
+  [3951.17624466283,3933.1416826913023],
+  [3951.17624466283,4098.741682691302],
+  [3851.8762446628302,4264.341682691302],
+  [3851.8762446628302,4098.741682691302],
+  [3752.5762446628305,4098.741682691302],
+  [3653.276244662831,4264.341682691302],
+  [3553.976244662831,4429.941682691301],
+  [3553.976244662831,4595.541682691301],
+  [3454.6762446628313,4429.941682691301],
+  [3553.976244662831,4264.341682691302],
+  [3653.276244662831,4429.941682691301],
+  [3752.5762446628305,4264.341682691302],
+  [3752.5762446628305,4429.941682691301],
+  [3851.8762446628302,4595.541682691301],
+  [3851.8762446628302,4429.941682691301],
+  [3951.17624466283,4429.941682691301],
+  [4050.4762446628297,4264.341682691302],
+  [4149.776244662829,4098.741682691302],
+  [4249.07624466283,4264.341682691302],
+  [4348.37624466283,4098.741682691302],
+  [4447.67624466283,3933.1416826913023],
+  [9574.088902135607,7352.26293905581],
+  [9474.788902135606,7352.26293905581],
+  [9375.488902135605,7186.662939055811],
+  [9474.788902135606,7021.0629390558115],
+  [9574.088902135607,7021.0629390558115],
+  [9474.788902135606,7186.662939055811],
+  [9574.088902135607,7186.662939055811],
+  [9673.388902135608,7021.0629390558115],
+  [9673.388902135608,6855.462939055812],
+  [9772.68890213561,6689.862939055813],
+  [9673.388902135608,6689.862939055813],
+  [9772.68890213561,6524.262939055813],
+  [9871.98890213561,6358.662939055814],
+  [9971.288902135611,6524.262939055813],
+  [10070.588902135612,6358.662939055814],
+  [10070.588902135612,6193.062939055814],
+  [9971.288902135611,6027.462939055815],
+  [9971.288902135611,5861.862939055815],
+  [9871.98890213561,5861.862939055815],
+  [9871.98890213561,5696.262939055816],
+  [9971.288902135611,5530.662939055816],
+  [10070.588902135612,5530.662939055816],
+  [10070.588902135612,5696.262939055816],
+  [10169.888902135614,5861.862939055815],
+  [10169.888902135614,5696.262939055816],
+  [10070.588902135612,5861.862939055815],
+  [10169.888902135614,6027.462939055815],
+  [10169.888902135614,6193.062939055814],
+  [10269.188902135615,6027.462939055815],
+  [10269.188902135615,5861.862939055815],
+  [10368.488902135616,6027.462939055815],
+  [10269.188902135615,6193.062939055814],
+  [10269.188902135615,6358.662939055814],
+  [10169.888902135614,6358.662939055814],
+  [10070.588902135612,6524.262939055813],
+  [10070.588902135612,6689.862939055813],
+  [9971.288902135611,6855.462939055812],
+  [9971.288902135611,7021.0629390558115],
+  [10070.588902135612,7186.662939055811],
+  [10169.888902135614,7186.662939055811],
+  [10269.188902135615,7186.662939055811],
+  [10169.888902135614,7352.26293905581],
+  [10070.588902135612,7352.26293905581],
+  [10169.888902135614,7517.86293905581],
+  [10169.888902135614,7683.462939055809],
+  [10269.188902135615,7517.86293905581],
+  [10368.488902135616,7683.462939055809],
+  [10467.788902135617,7683.462939055809],
+  [10368.488902135616,7517.86293905581],
+  [10269.188902135615,7352.26293905581],
+  [10368.488902135616,7352.26293905581],
+  [10368.488902135616,7186.662939055811],
+  [10368.488902135616,7021.0629390558115],
+  [10368.488902135616,6855.462939055812],
+  [10269.188902135615,6855.462939055812],
+  [10169.888902135614,6855.462939055812],
+  [10169.888902135614,7021.0629390558115],
+  [10070.588902135612,7021.0629390558115],
+  [10070.588902135612,6855.462939055812],
+  [10169.888902135614,6689.862939055813],
+  [10269.188902135615,6689.862939055813],
+  [10169.888902135614,6524.262939055813],
+  [10269.188902135615,6524.262939055813],
+  [10368.488902135616,6524.262939055813],
+  [10368.488902135616,6358.662939055814],
+  [10467.788902135617,6358.662939055814],
+  [10467.788902135617,6193.062939055814],
+  [10567.088902135618,6358.662939055814],
+  [10567.088902135618,6193.062939055814],
+  [10666.388902135619,6193.062939055814],
+  [10666.388902135619,6358.662939055814],
+  [10567.088902135618,6524.262939055813],
+  [10467.788902135617,6524.262939055813],
+  [10567.088902135618,6689.862939055813],
+  [10467.788902135617,6855.462939055812],
+  [10567.088902135618,7021.0629390558115],
+  [10467.788902135617,7021.0629390558115],
+  [10567.088902135618,6855.462939055812],
+  [10467.788902135617,6689.862939055813],
+  [10368.488902135616,6689.862939055813],
+  [1073.6944354374714,1154.3681204032646],
+  [974.3944354374713,1319.9681204032647],
+  [875.0944354374712,1319.9681204032647],
+  [775.7944354374712,1154.3681204032646],
+  [775.7944354374712,988.7681204032646],
+  [875.0944354374712,823.1681204032647],
+  [875.0944354374712,657.5681204032647],
+  [775.7944354374712,823.1681204032647],
+  [676.4944354374711,657.5681204032647],
+  [676.4944354374711,491.9681204032648],
+  [775.7944354374712,657.5681204032647],
+  [676.4944354374711,823.1681204032647],
+  [676.4944354374711,988.7681204032646],
+  [577.194435437471,823.1681204032647],
+  [577.194435437471,988.7681204032646],
+  [577.194435437471,1154.3681204032646],
+  [676.4944354374711,1319.9681204032647],
+  [577.194435437471,1319.9681204032647],
+  [477.89443543747103,1319.9681204032647],
+  [577.194435437471,1485.5681204032649],
+  [477.89443543747103,1651.168120403265],
+  [577.194435437471,1816.7681204032651],
+  [477.89443543747103,1816.7681204032651],
+  [378.5944354374711,1982.3681204032653],
+  [378.5944354374711,2147.9681204032654],
+  [279.2944354374711,2313.5681204032653],
+  [179.99443543747114,2147.9681204032654],
+  [80.69443543747114,2313.5681204032653],
+  [80.69443543747114,2479.168120403265],
+  [179.9944354374711,2644.768120403265],
+  [179.9944354374711,2479.168120403265],
+  [179.9944354374711,2313.5681204032653],
+  [80.69443543747111,2147.9681204032654],
+  [80.69443543747111,1982.3681204032653],
+  [179.9944354374711,1982.3681204032653],
+  [179.9944354374711,1816.7681204032651],
+  [80.69443543747111,1816.7681204032651],
+  [179.9944354374711,1651.168120403265],
+  [80.69443543747111,1485.5681204032649],
+  [80.69443543747111,1319.9681204032647],
+  [179.9944354374711,1154.3681204032646],
+  [80.69443543747111,1154.3681204032646],
+  [179.9944354374711,988.7681204032646],
+  [279.2944354374711,823.1681204032647],
+  [378.5944354374711,657.5681204032647],
+  [378.5944354374711,823.1681204032647],
+  [477.89443543747103,823.1681204032647],
+  [477.89443543747103,657.5681204032647],
+  [378.5944354374711,491.9681204032648],
+  [477.89443543747103,326.3681204032648],
+  [477.89443543747103,160.76812040326482],
+  [378.5944354374711,160.76812040326482],
+  [279.2944354374711,326.3681204032648],
+  [179.99443543747114,491.9681204032648],
+  [179.99443543747114,326.3681204032648],
+  [279.2944354374711,491.9681204032648],
+  [279.2944354374711,657.5681204032647],
+  [179.99443543747114,823.1681204032647],
+  [279.2944354374711,988.7681204032646],
+  [279.2944354374711,1154.3681204032646],
+  [378.5944354374711,1319.9681204032647],
+  [477.89443543747103,1485.5681204032649],
+  [577.194435437471,1651.168120403265],
+  [676.4944354374711,1651.168120403265],
+  [775.7944354374712,1816.7681204032651],
+  [676.4944354374711,1816.7681204032651],
+  [775.7944354374712,1651.168120403265],
+  [875.0944354374712,1651.168120403265],
+  [974.3944354374713,1651.168120403265],
+  [875.0944354374712,1485.5681204032649],
+  [775.7944354374712,1485.5681204032649],
+  [676.4944354374711,1485.5681204032649],
+  [775.7944354374712,1319.9681204032647],
+  [676.4944354374711,1154.3681204032646],
+  [3138.413562431697,2355.845602060523],
+  [3039.113562431697,2521.445602060523],
+  [3039.113562431697,2355.845602060523],
+  [3039.113562431697,2190.245602060523],
+  [3138.413562431697,2024.645602060523],
+  [3237.7135624316966,1859.045602060523],
+  [3237.7135624316966,2024.645602060523],
+  [3337.0135624316963,1859.045602060523],
+  [3337.0135624316963,1693.4456020605228],
+  [3436.313562431696,1527.8456020605227],
+  [3535.6135624316958,1693.4456020605228],
+  [3535.6135624316958,1859.045602060523],
+  [3634.9135624316955,2024.645602060523],
+  [3734.213562431695,2190.245602060523],
+  [3634.9135624316955,2190.245602060523],
+  [3535.6135624316958,2190.245602060523],
+  [3535.6135624316958,2355.845602060523],
+  [3535.6135624316958,2521.445602060523],
+  [3436.313562431696,2687.045602060523],
+  [3436.313562431696,2852.645602060523],
+  [3535.6135624316958,2687.045602060523],
+  [3634.9135624316955,2521.445602060523],
+  [3634.9135624316955,2355.845602060523],
+  [3734.213562431695,2355.845602060523],
+  [3833.513562431695,2190.245602060523],
+  [3932.8135624316947,2024.645602060523],
+  [3833.513562431695,1859.045602060523],
+  [3833.513562431695,1693.4456020605228],
+  [3734.213562431695,1859.045602060523],
+  [3734.213562431695,1693.4456020605228],
+  [3734.213562431695,1527.8456020605227],
+  [3634.9135624316955,1527.8456020605227],
+  [3634.9135624316955,1693.4456020605228],
+  [3535.6135624316958,1527.8456020605227],
+  [3634.9135624316955,1362.2456020605225],
+  [3535.6135624316958,1362.2456020605225],
+  [3436.313562431696,1196.6456020605224],
+  [3535.6135624316958,1196.6456020605224],
+  [3535.6135624316958,1031.0456020605222],
+  [3436.313562431696,1031.0456020605222],
+  [3535.6135624316958,865.4456020605222],
+  [3436.313562431696,865.4456020605222],
+  [3535.6135624316958,699.8456020605223],
+  [3634.9135624316955,699.8456020605223],
+  [3535.6135624316958,534.2456020605224],
+  [3436.313562431696,368.64560206052244],
+  [3436.313562431696,203.04560206052244],
+  [3337.0135624316963,37.445602060522454],
+  [3436.313562431696,37.445602060522454],
+  [3337.0135624316963,203.04560206052244],
+  [3237.7135624316966,37.445602060522454],
+  [3138.413562431697,37.445602060522454],
+  [3237.7135624316966,203.04560206052244],
+  [3337.0135624316963,368.6456020605224],
+  [3436.313562431696,534.2456020605224],
+  [3337.0135624316963,699.8456020605223],
+  [3237.7135624316966,534.2456020605224],
+  [3337.0135624316963,534.2456020605224],
+  [3436.313562431696,699.8456020605223],
+  [3337.0135624316963,865.4456020605222],
+  [3237.7135624316966,865.4456020605222],
+  [3337.0135624316963,1031.0456020605222],
+  [3237.7135624316966,1196.6456020605224],
+  [3138.413562431697,1362.2456020605225],
+  [3039.113562431697,1527.8456020605227],
+  [3138.413562431697,1527.8456020605227],
+  [3039.113562431697,1693.4456020605228],
+  [2939.8135624316974,1527.8456020605227],
+  [2840.5135624316977,1362.2456020605225],
+  [2840.5135624316977,1527.8456020605227],
+  [2840.5135624316977,1693.4456020605228],
+  [2939.8135624316974,1859.045602060523],
+  [2840.5135624316977,2024.645602060523],
+  [2840.5135624316977,1859.045602060523],
+  [2939.8135624316974,1693.4456020605228],
+  [3039.113562431697,1859.045602060523],
+  [3039.113562431697,2024.645602060523],
+  [2939.8135624316974,2190.245602060523],
+  [2939.8135624316974,2024.645602060523],
+  [16388.412117675925,1839.818884803299],
+  [16289.112117675924,1839.818884803299],
+  [16388.412117675925,1674.2188848032988],
+  [16487.712117675925,1508.6188848032987],
+  [16487.712117675925,1674.2188848032988],
+  [16388.412117675925,1508.6188848032987],
+  [16289.112117675924,1343.0188848032985],
+  [16289.112117675924,1508.6188848032987],
+  [16189.812117675923,1674.2188848032988],
+  [16090.512117675922,1839.818884803299],
+  [16090.512117675922,2005.418884803299],
+  [15991.212117675921,2171.018884803299],
+  [16090.512117675922,2336.618884803299],
+  [16090.512117675922,2502.218884803299],
+  [16090.512117675922,2667.8188848032987],
+  [15991.212117675921,2833.4188848032986],
+  [15991.212117675921,2999.0188848032985],
+  [15891.91211767592,3164.6188848032984],
+  [15891.91211767592,3330.2188848032984],
+  [15991.212117675921,3330.2188848032984],
+  [16090.512117675922,3330.2188848032984],
+  [16189.812117675923,3495.8188848032983],
+  [16289.112117675924,3495.8188848032983],
+  [16189.812117675923,3330.2188848032984],
+  [16189.812117675923,3164.6188848032984],
+  [16289.112117675924,3164.6188848032984],
+  [16388.412117675925,3164.6188848032984],
+  [16388.412117675925,3330.2188848032984],
+  [16487.712117675925,3330.2188848032984],
+  [16587.012117675924,3495.8188848032983],
+  [16587.012117675924,3661.418884803298],
+  [16686.312117675923,3661.418884803298],
+  [16785.612117675922,3661.418884803298],
+  [16884.91211767592,3661.418884803298],
+  [16984.21211767592,3661.418884803298],
+  [16884.91211767592,3827.018884803298],
+  [16884.91211767592,3992.618884803298],
+  [16984.21211767592,3827.018884803298],
+  [17083.51211767592,3661.418884803298],
+  [17182.81211767592,3495.8188848032983],
+  [17182.81211767592,3330.2188848032984],
+  [17282.11211767592,3164.6188848032984],
+  [17282.11211767592,3330.2188848032984],
+  [17182.81211767592,3164.6188848032984],
+  [17083.51211767592,3164.6188848032984],
+  [16984.21211767592,3330.2188848032984],
+  [16984.21211767592,3495.8188848032983],
+  [17083.51211767592,3330.2188848032984],
+  [16984.21211767592,3164.6188848032984],
+  [16984.21211767592,2999.0188848032985],
+  [17083.51211767592,2833.4188848032986],
+  [17083.51211767592,2667.8188848032987],
+  [17182.81211767592,2667.8188848032987],
+  [17182.81211767592,2833.4188848032986],
+  [17083.51211767592,2999.0188848032985],
+  [16984.21211767592,2833.4188848032986],
+  [16884.91211767592,2833.4188848032986],
+  [16884.91211767592,2999.0188848032985],
+  [16785.612117675922,2999.0188848032985],
+  [16884.91211767592,3164.6188848032984],
+  [16785.612117675922,3164.6188848032984],
+  [16686.312117675923,3164.6188848032984],
+  [16587.012117675924,3164.6188848032984],
+  [16587.012117675924,2999.0188848032985],
+  [16487.712117675925,3164.6188848032984],
+  [16587.012117675924,3330.2188848032984],
+  [16686.312117675923,3495.8188848032983],
+  [16686.312117675923,3330.2188848032984],
+  [16785.612117675922,3330.2188848032984],
+  [16884.91211767592,3495.8188848032983],
+  [16785.612117675922,3495.8188848032983],
+  [16884.91211767592,3330.2188848032984],
+  [1272.175991128079,3842.7700224365044],
+  [1371.475991128079,3842.7700224365044],
+  [1272.175991128079,3677.1700224365045],
+  [1172.875991128079,3511.5700224365046],
+  [1272.175991128079,3511.5700224365046],
+  [1172.875991128079,3345.9700224365047],
+  [1073.575991128079,3180.3700224365048],
+  [1073.575991128079,3014.770022436505],
+  [974.275991128079,3014.770022436505],
+  [874.9759911280789,3014.770022436505],
+  [775.6759911280789,2849.170022436505],
+  [775.6759911280789,3014.770022436505],
+  [775.6759911280789,3180.3700224365048],
+  [676.3759911280788,3345.9700224365047],
+  [676.3759911280788,3511.5700224365046],
+  [775.6759911280789,3677.1700224365045],
+  [676.3759911280788,3842.7700224365044],
+  [577.0759911280787,3842.7700224365044],
+  [577.0759911280787,3677.1700224365045],
+  [676.3759911280788,3677.1700224365045],
+  [775.6759911280789,3511.5700224365046],
+  [775.6759911280789,3345.9700224365047],
+  [874.9759911280789,3345.9700224365047],
+  [874.9759911280789,3180.3700224365048],
+  [974.275991128079,3180.3700224365048],
+  [974.275991128079,3345.9700224365047],
+  [1073.575991128079,3511.5700224365046],
+  [1073.575991128079,3677.1700224365045],
+  [1172.875991128079,3677.1700224365045],
+  [1172.875991128079,3842.7700224365044],
+  [1073.575991128079,3842.7700224365044],
+  [1172.875991128079,4008.3700224365043],
+  [1073.575991128079,4008.3700224365043],
+  [974.275991128079,3842.7700224365044],
+  [974.275991128079,4008.3700224365043],
+  [874.9759911280789,4008.3700224365043],
+  [775.6759911280789,4008.3700224365043],
+  [874.9759911280789,3842.7700224365044],
+  [974.275991128079,3677.1700224365045],
+  [974.275991128079,3511.5700224365046],
+  [1073.575991128079,3345.9700224365047],
+  [1172.875991128079,3180.3700224365048],
+  [1272.175991128079,3180.3700224365048],
+  [1272.175991128079,3345.9700224365047],
+  [1371.475991128079,3180.3700224365048],
+  [1470.7759911280789,3345.9700224365047],
+  [1371.475991128079,3345.9700224365047],
+  [1371.475991128079,3511.5700224365046],
+  [1470.7759911280789,3511.5700224365046],
+  [1570.0759911280788,3677.1700224365045],
+  [1470.7759911280789,3677.1700224365045],
+  [1570.0759911280788,3511.5700224365046],
+  [1669.3759911280788,3511.5700224365046],
+  [1669.3759911280788,3677.1700224365045],
+  [1768.6759911280787,3842.7700224365044],
+  [1669.3759911280788,3842.7700224365044],
+  [1768.6759911280787,4008.3700224365043],
+  [1867.9759911280787,3842.7700224365044],
+  [1967.2759911280787,3677.1700224365045],
+  [2066.5759911280784,3842.7700224365044],
+  [2165.875991128078,3677.1700224365045],
+  [2066.5759911280784,3511.5700224365046],
+  [2165.875991128078,3511.5700224365046],
+  [2066.5759911280784,3677.1700224365045],
+  [2165.875991128078,3842.7700224365044],
+  [2265.175991128078,4008.3700224365043],
+  [2364.4759911280776,4008.3700224365043],
+  [2265.175991128078,3842.7700224365044],
+  [2364.4759911280776,3677.1700224365045],
+  [2463.7759911280773,3842.7700224365044],
+  [2463.7759911280773,4008.3700224365043],
+  [2364.4759911280776,3842.7700224365044]
+];
+
+@AssumeDynamic()
+@NoInline()
+confuse(x) => x;
+
+main() {
+  print(confuse(panels).length);
+}
diff --git a/tests/language/lazy_static7_test.dart b/tests/language/lazy_static7_test.dart
new file mode 100644
index 0000000..ff74912
--- /dev/null
+++ b/tests/language/lazy_static7_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+var sideEffect = 0;
+var x = (() { sideEffect++; return 499; })();
+
+main() {
+  if (new DateTime.now().day >= -1) {
+    x = 42;
+  }
+  Expect.equals(42, x);
+  Expect.equals(0, sideEffect);
+}
diff --git a/tests/language/many_method_calls_test.dart b/tests/language/many_method_calls_test.dart
new file mode 100644
index 0000000..25a7c89
--- /dev/null
+++ b/tests/language/many_method_calls_test.dart
@@ -0,0 +1,6644 @@
+// 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.
+
+// Test that compiler does not crash for very long chains of method calls.
+
+var field = false;
+
+foo() {
+  if (field) {
+    print('foo');
+  }
+}
+
+main() {
+  manyMethodCalls();
+  field = true;
+}
+
+manyMethodCalls() {
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+  foo();
+}
\ No newline at end of file
diff --git a/tests/language/mixin_super_bound2_test.dart b/tests/language/mixin_super_bound2_test.dart
index 543a029..87e8b7a 100644
--- a/tests/language/mixin_super_bound2_test.dart
+++ b/tests/language/mixin_super_bound2_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--supermixin
+// SharedOptions=--supermixin
 
 import "package:expect/expect.dart";
 
@@ -15,13 +15,21 @@
   return false;
 }
 
-class MS<U, V extends U> { }
+class MS<U, V
+    extends U /// 01: static type warning
+    > { }
 
-class M<U extends V, V> extends MS<V, U> { }
+class M<U
+    extends V /// 01: continued
+    , V> extends MS<V, U> { }
 
-class NS<U extends V, V> { }
+class NS<U
+    extends V /// 01: continued
+    , V> { }
 
-class N<U, V extends U> extends NS<V, U> { }
+class N<U, V
+    extends U /// 01: continued
+    > extends NS<V, U> { }
 
 class S<T> { }
 
@@ -42,7 +50,10 @@
   new MNA2<num, int, bool>();
   new MNA3<num, int, bool>();
   new MNA4<num, int, bool>();
-  if (inCheckedMode()) {
+  bool shouldThrow = false
+      || inCheckedMode() /// 01: continued
+      ;
+  if (shouldThrow) {
     // Type parameter U of M must extend type parameter V, but
     // type argument List<num> is not a subtype of List<int>.
     Expect.throws(() => new MNA<int, num, bool>(), (e) => e is TypeError);
diff --git a/tests/language/mixin_super_test.dart b/tests/language/mixin_super_test.dart
index 85e53e7..8a4ee98 100644
--- a/tests/language/mixin_super_test.dart
+++ b/tests/language/mixin_super_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--supermixin
+// SharedOptions=--supermixin
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/multiline_newline_cr.dart b/tests/language/multiline_newline_cr.dart
new file mode 100644
index 0000000..c5c48bc
--- /dev/null
+++ b/tests/language/multiline_newline_cr.dart
Binary files differ
diff --git a/tests/language/multiline_newline_crlf.dart b/tests/language/multiline_newline_crlf.dart
new file mode 100644
index 0000000..64cd255
--- /dev/null
+++ b/tests/language/multiline_newline_crlf.dart
@@ -0,0 +1,15 @@
+// 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 multiline_newline_crlf;

+

+const constantMultilineString = """

+a

+b

+""";

+

+var nonConstantMultilineString = """

+a

+b

+""";

diff --git a/tests/language/multiline_newline_lf.dart b/tests/language/multiline_newline_lf.dart
new file mode 100644
index 0000000..48b6901
--- /dev/null
+++ b/tests/language/multiline_newline_lf.dart
@@ -0,0 +1,15 @@
+// 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 multiline_newline_lf;
+
+const constantMultilineString = """
+a
+b
+""";
+
+var nonConstantMultilineString = """
+a
+b
+""";
diff --git a/tests/language/multiline_newline_test.dart b/tests/language/multiline_newline_test.dart
new file mode 100644
index 0000000..f250b28
--- /dev/null
+++ b/tests/language/multiline_newline_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+import 'multiline_newline_cr.dart' as cr;
+import 'multiline_newline_crlf.dart' as crlf;
+import 'multiline_newline_lf.dart' as lf;
+
+main() {
+  Expect.equals(4, cr.constantMultilineString.length);
+  Expect.equals(4, crlf.constantMultilineString.length);
+  Expect.equals(4, lf.constantMultilineString.length);
+  Expect.equals(cr.constantMultilineString, crlf.constantMultilineString);
+  Expect.equals(crlf.constantMultilineString, lf.constantMultilineString);
+  Expect.equals(lf.constantMultilineString, cr.constantMultilineString);
+
+  Expect.equals(4, cr.nonConstantMultilineString.length);
+  Expect.equals(4, crlf.nonConstantMultilineString.length);
+  Expect.equals(4, lf.nonConstantMultilineString.length);
+  Expect.equals(cr.nonConstantMultilineString, crlf.nonConstantMultilineString);
+  Expect.equals(crlf.nonConstantMultilineString, lf.nonConstantMultilineString);
+  Expect.equals(lf.nonConstantMultilineString, cr.nonConstantMultilineString);
+
+  const c1 =
+      cr.constantMultilineString == crlf.constantMultilineString ? true : null;
+  const c2 =
+      crlf.constantMultilineString == lf.constantMultilineString ? true : null;
+  const c3 =
+      lf.constantMultilineString == cr.constantMultilineString ? true : null;
+  Expect.isTrue(c1);
+  Expect.isTrue(c2);
+  Expect.isTrue(c3);
+
+  const c4 = c1 ? 1 : 2;  /// 01: ok
+  Expect.equals(1, c4);   /// 01: continued
+
+  const c5 = c2 ? 2 : 3;  /// 02: ok
+  Expect.equals(2, c5);   /// 02: continued
+
+  const c6 = c3 ? 3 : 4;  /// 03: ok
+  Expect.equals(3, c6);   /// 03: continued
+
+  const c7 =
+      cr.constantMultilineString != crlf.constantMultilineString ? true : null;
+  const c8 =
+      crlf.constantMultilineString != lf.constantMultilineString ? true : null;
+  const c9 =
+      lf.constantMultilineString != cr.constantMultilineString ? true : null;
+  Expect.isNull(c7);
+  Expect.isNull(c8);
+  Expect.isNull(c9);
+
+  const c10 = c7 ? 1 : 2;  /// 04: compile-time error
+  const c11 = c8 ? 2 : 3;  /// 05: compile-time error
+  const c12 = c9 ? 3 : 4;  /// 06: compile-time error
+}
\ No newline at end of file
diff --git a/tests/language/nullaware_opt_test.dart b/tests/language/nullaware_opt_test.dart
index 05b57e8..5446171 100644
--- a/tests/language/nullaware_opt_test.dart
+++ b/tests/language/nullaware_opt_test.dart
@@ -27,7 +27,6 @@
   Expect.equals(null, c?.m(bomb()));
   Expect.equals(null, getNull()?.anything(bomb()));
   Expect.equals(1, d?.m(1));
-  Expect.equals("C", C?.toString());
 
   Expect.equals(1, new C(1)?.f);
   Expect.equals(null, c?.v);
diff --git a/tests/language/symbol_conflict_test.dart b/tests/language/symbol_conflict_test.dart
index d896c9e..10b949e 100644
--- a/tests/language/symbol_conflict_test.dart
+++ b/tests/language/symbol_conflict_test.dart
@@ -26,6 +26,13 @@
 /**
  The following constant was generated with the following program:
 
+   const RESERVED_WORDS = const [
+     'assert', 'break', 'case', 'catch', 'class', 'const', 'continue',
+     'default', 'do', 'else', 'enum', 'extends', 'false', 'final',
+     'finally', 'for', 'if', 'in', 'is', 'new', 'null', 'rethrow',
+     'return', 'super', 'switch', 'this', 'throw', 'true', 'try',
+     'var', 'void', 'while', 'with'];
+
    get chars sync* {
       for (int i = "a".codeUnitAt(0); i <= "z".codeUnitAt(0); i++) {
         yield new String.fromCharCodes([i]);
@@ -44,7 +51,9 @@
       // Two character symbols.
       for (String c1 in chars) {
         for (String c2 in chars) {
-          print("  const Symbol('$c1$c2'),");
+          if (!RESERVED_WORDS.contains('$c1$c2')) {
+            print("  const Symbol('$c1$c2'),");
+          }
         }
       }
       print("];");
@@ -273,7 +282,6 @@
   const Symbol('dl'),
   const Symbol('dm'),
   const Symbol('dn'),
-  const Symbol('do'),
   const Symbol('dp'),
   const Symbol('dq'),
   const Symbol('dr'),
@@ -524,7 +532,6 @@
   const Symbol('ic'),
   const Symbol('id'),
   const Symbol('ie'),
-  const Symbol('if'),
   const Symbol('ig'),
   const Symbol('ih'),
   const Symbol('ii'),
@@ -532,12 +539,10 @@
   const Symbol('ik'),
   const Symbol('il'),
   const Symbol('im'),
-  const Symbol('in'),
   const Symbol('io'),
   const Symbol('ip'),
   const Symbol('iq'),
   const Symbol('ir'),
-  const Symbol('is'),
   const Symbol('it'),
   const Symbol('iu'),
   const Symbol('iv'),
diff --git a/tests/language/tearoff_basic_lib.dart b/tests/language/tearoff_basic_lib.dart
new file mode 100644
index 0000000..fe9fc07
--- /dev/null
+++ b/tests/language/tearoff_basic_lib.dart
@@ -0,0 +1,17 @@
+// 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 tearoff_basic_lib;
+
+cfunc() => "cfunc";
+
+set cset(a) { cvar = a; }
+
+get cget => "cget";
+
+var cvar = 1+2+3;
+
+final cfinvar = "set in stone";
+
+class ZZ { }
diff --git a/tests/language/tearoff_basic_test.dart b/tests/language/tearoff_basic_test.dart
new file mode 100644
index 0000000..303d38e
--- /dev/null
+++ b/tests/language/tearoff_basic_test.dart
@@ -0,0 +1,166 @@
+// 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.
+
+// Basic test for tear-off closures.
+
+import "package:expect/expect.dart";
+import "tearoff_basic_lib.dart" as P;
+import "tearoff_basic_lib.dart" deferred as D;
+
+class C {
+  var v = 99;
+  final fv = 444;
+
+  operator + (a) { return v + a; }
+  get sugus => "sugus";
+  set frosch(a) { v = "ribbit $a"; }
+  foo() => "kuh";
+
+  static var st;
+  static final stfin = 1000;
+  static stfoo([p1 = 100]) => p1 * 10;
+  static get stg => "stg";
+  static set sts(x) { st = x; }
+}
+
+
+testStatic() {
+  // Closurize static variable.
+  var a = C#st=;
+  a(100);
+  Expect.equals(100, C.st);
+  var b = C#st;
+  Expect.equals(100, b());
+
+  // Closurize static final variable.
+  a = C#stfin;
+  Expect.equals(1000, a());
+  Expect.throws(() => C#stfin= );  // Final variable has no setter.
+
+  // Closurize static method.
+  a = C#stfoo;
+  Expect.equals(1000, a());
+  Expect.equals(90, a(9));
+
+  // Closurize static getter.
+  a = C#stg;
+  Expect.equals("stg", a());
+
+  // Closurize static setter.
+  Expect.throws(() => C#sts);  // No setter/method named sts exists.
+  a = C#sts=;
+  a("pflug");
+  Expect.equals("pflug", C.st);
+
+  // Can't closurize instance method via class literal.
+  Expect.throws(() => C#foo);
+
+  // Extracted closures must be equal.
+  Expect.isTrue(C#st == C#st);
+  Expect.isTrue(C#st= == C#st=);
+  Expect.isTrue(C#stfin == C#stfin);
+  Expect.isTrue(C#stfoo == C#stfoo);
+  Expect.isTrue(C#stg == C#stg);
+  Expect.isTrue(C#sts= == C#sts=);
+}
+
+testInstance() {
+  var o = new C();
+  var p = new C();
+  var a, b;
+
+  // Closurize instance variable.
+  a = o#v;
+  Expect.equals(99, a());
+  b = p#v=;
+  b(999);
+  Expect.equals(999, p.v);
+  Expect.equals(99, a());
+
+  // Closurize final instance variable.
+  Expect.throws(() => o#fv=);  // Final variable has not setter.
+  a = o#fv;
+  Expect.equals(444, a());
+
+  // Closurize instance method.
+  a = o#foo;
+  Expect.equals("kuh", a());
+
+  // Closurize operator.
+  a = o#+;
+  Expect.equals(100, o + 1);
+  Expect.equals(100, a(1));
+
+  // Closurize instance getter.
+  a = o#sugus;
+  Expect.equals("sugus", a());
+  Expect.throws(() => o#sugus=);
+
+  // Closurize instance setter.
+  a = o#frosch=;
+  a("!");
+  Expect.equals("ribbit !", o.v);
+  Expect.throws(() => o#frosch);
+
+  // Extracted closures must be equal.
+  Expect.isTrue(o#v == o#v);
+  Expect.isTrue(o#v= == o#v=);
+  Expect.isTrue(o#fv == o#fv);
+  Expect.isTrue(o#foo == o#foo);
+  Expect.isTrue(o#+ == o#+);
+  Expect.isTrue(o#sugus == o#sugus);
+  Expect.isTrue(o#frosch= == o#frosch=);
+}
+
+testPrefix() {
+  // Closurize top-level variable.
+  var a = P#cvar;
+  Expect.equals(6, a());
+  var b = P#cvar=;
+  b(7);
+  Expect.equals(7, a());
+
+  // Closurize final top-level variable.
+  a = P#cfinvar;
+  Expect.equals("set in stone", a());
+  Expect.throws(() => P#cfinvar=);
+
+  // Closurize top-level function.
+  a = P#cfunc;
+  Expect.equals("cfunc", a());
+
+  // Closurize top-level getter.
+  a = P#cget;
+  Expect.equals("cget", a());
+
+  // Closurize top-level getter.
+  a = P#cset=;
+  a(99);
+  Expect.equals(99, P.cvar);
+
+  Expect.throws(() => P#ZZ);  // Cannot closurize class.
+
+  // Extracted closures must be equal.
+  Expect.isTrue(P#cvar == P#cvar);
+  Expect.isTrue(P#cvar= == P#cvar=);
+  Expect.isTrue(P#cfinvar == P#cfinvar);
+  Expect.isTrue(P#cfunc == P#cfunc);
+  Expect.isTrue(P#cget == P#cget);
+  Expect.isTrue(P#cset= == P#cset=);
+}
+
+testDeferred() {
+  Expect.throws(() => D#cfunc);
+  D.loadLibrary().then((_) {
+    var a = D#cfunc;
+    Expect.equals("cfunc", a());
+  });
+}
+
+main() {
+  testStatic();
+  testInstance();
+  testPrefix();
+  testDeferred();
+}
diff --git a/tests/language/tearoff_constructor_basic_test.dart b/tests/language/tearoff_constructor_basic_test.dart
new file mode 100644
index 0000000..27c34d9
--- /dev/null
+++ b/tests/language/tearoff_constructor_basic_test.dart
@@ -0,0 +1,80 @@
+// 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.
+
+// Basic test for tear-off constructor closures.
+
+import "package:expect/expect.dart";
+
+class A {
+  // Implicit constructor A();
+  var f1 = "A.f1";
+}
+
+class P {
+  var x, y;
+  P(this.x, this.y);
+  factory P.origin() { return new P(0,0); }
+  factory P.ursprung() = P.origin;
+  P.onXAxis(x) : this(x, 0);
+}
+
+class C<T> {
+  T f1;
+  C(T p) : f1 = p;
+  C.n([T p]) : f1 = p;
+  listMaker() { return new List<T>#; }  // Closurize type parameter.
+}
+
+
+testMalformed() {
+  Expect.throws(() => new NoSuchClass#);
+  Expect.throws(() => new A#noSuchContstructor);
+}
+
+testA() {
+  var cc = new A#;  // Closurize implicit constructor.
+  var o = cc();
+  Expect.equals("A.f1", o.f1);
+  Expect.equals("A.f1", (new A#)().f1);
+  Expect.throws(() => new A#foo);
+}
+
+testP() {
+  var cc = new P#origin;
+  var o = cc();
+  Expect.equals(0, o.x);
+  cc = new P#ursprung;
+  o = cc();
+  Expect.equals(0, o.x);
+  cc = new P#onXAxis;
+  o = cc(5);
+  Expect.equals(0, o.y);
+  Expect.equals(5, o.x);
+  Expect.throws(() => cc(1, 1));  // Too many arguments.
+}
+
+testC() {
+  var cc = new C<int>#;
+  var o = cc(5);
+  Expect.equals("int", "${o.f1.runtimeType}");
+  Expect.throws(() => cc());  // Missing constructor parameter.
+
+  cc = new C<String>#n;
+  o = cc("foo");
+  Expect.equals("String", "${o.f1.runtimeType}");
+  o = cc();
+  Expect.equals(null, o.f1);
+
+  cc = o.listMaker();
+  Expect.isTrue(cc is Function);
+  var l = cc();
+  Expect.equals("List<String>", "${l.runtimeType}");
+}
+
+main() {
+  testA();
+  testC();
+  testP();
+  testMalformed();
+}
diff --git a/tests/lib/async/stream_type_test.dart b/tests/lib/async/stream_type_test.dart
new file mode 100644
index 0000000..a8bc2e9
--- /dev/null
+++ b/tests/lib/async/stream_type_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/expect.dart";
+
+class TypeTest<T, NT> {
+  void call(object, name) {
+    Expect.isTrue(object is T, "$name is $T");
+    Expect.isFalse(object is NT, "$name is! $NT");
+  }
+}
+
+main() {
+  var checkIntStream = new TypeTest<Stream<int>, Stream<String>>();
+  var checkIntFuture = new TypeTest<Future<int>, Future<String>>();
+  var checkBoolFuture = new TypeTest<Future<bool>, Future<String>>();
+  var checkStringFuture = new TypeTest<Future<String>, Future<int>>();
+  var checkIntSetFuture = new TypeTest<Future<Set<int>>, Future<Set<String>>>();
+  var checkIntListFuture = new TypeTest<Future<List<int>>,
+                                        Future<List<String>>>();
+  var checkIntSubscription = new TypeTest<StreamSubscription<int>,
+                                          StreamSubscription<String>>();
+
+  // Generic function used as parameter for, e.g., `skipWhile` and `reduce`.
+  f([_1, _2]) => throw "unreachable";
+
+  bool testIntStream(stream(), name, int recursionDepth) {
+    checkIntStream(stream(), name);
+    if (recursionDepth > 0) {
+      checkIntSubscription(stream().listen(null), "$name.listen");
+
+      checkIntFuture(stream().first, "$name.first");
+      checkIntFuture(stream().last, "$name.last");
+      checkIntFuture(stream().single, "$name.single");
+      checkIntFuture(stream().singleWhere(f), "$name.singleWhere");
+      checkIntFuture(stream().elementAt(2), "$name.elementAt");
+      checkIntFuture(stream().reduce(f), "$name.reduce");
+      checkIntListFuture(stream().toList(), "$name.toList");
+      checkIntSetFuture(stream().toSet(), "$name.toSert");
+
+      checkIntFuture(stream().length, "$name.length");
+      checkBoolFuture(stream().isEmpty, "$name.is");
+      checkBoolFuture(stream().any(f) , "$name.any");
+      checkBoolFuture(stream().every(f), "$name.every");
+      checkBoolFuture(stream().contains(null), "$name.contains");
+      checkStringFuture(stream().join(), "$name.join");
+
+      var n = recursionDepth - 1;
+      testIntStream(() => stream().where(f), "$name.where", n);
+      testIntStream(() => stream().take(2), "$name.take", n);
+      testIntStream(() => stream().takeWhile(f), "$name.takeWhile", n);
+      testIntStream(() => stream().skip(2), "$name.skip", n);
+      testIntStream(() => stream().skipWhile(f), "$name.skipWhile", n);
+      testIntStream(() => stream().distinct(f), "$name.distinct", n);
+      testIntStream(() => stream().handleError(f), "$name.handleError", n);
+      testIntStream(() => stream().asBroadcastStream(),
+                    "$name.asBroadcastStream", n);
+    }
+  }
+
+  testIntStream(() => new StreamController<int>().stream, "Stream<int>", 3);
+  testIntStream(() => new StreamController<int>.broadcast().stream,
+                "BroadcastStream<int>", 3);
+}
diff --git a/tests/lib/mirrors/hot_get_field_test.dart b/tests/lib/mirrors/hot_get_field_test.dart
index ca798d3..6673818 100644
--- a/tests/lib/mirrors/hot_get_field_test.dart
+++ b/tests/lib/mirrors/hot_get_field_test.dart
@@ -10,6 +10,7 @@
 class C {
   var field;
   var _field;
+  operator +(other) => field + other;
 }
 
 const int optimizationThreshold = 20;
@@ -44,8 +45,22 @@
   }
 }
 
+testOperator() {
+  var plus = const Symbol("+");
+  var c = new C();
+  var im = reflect(c);
+
+  for (int i = 0; i < (2 * optimizationThreshold); i++) {
+    c.field = i;
+    var closurizedPlus = im.getField(plus).reflectee;
+    Expect.isTrue(closurizedPlus is Function);
+    Expect.equals(2 * i, closurizedPlus(i));
+  }
+}
+
 main() {
   testPublic();
   testPrivate();
   testPrivateWrongLibrary();
+  testOperator();
 }
diff --git a/tests/lib/mirrors/io_html_mutual_exclusion_test.dart b/tests/lib/mirrors/io_html_mutual_exclusion_test.dart
new file mode 100644
index 0000000..087b8a6
--- /dev/null
+++ b/tests/lib/mirrors/io_html_mutual_exclusion_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.io_html_mutual_exclusion;
+
+import 'dart:mirrors';
+
+main() {
+  var libraries = currentMirrorSystem().libraries;
+  bool has_io = libraries[Uri.parse('dart:io')] != null;
+  bool has_html = libraries[Uri.parse('dart:html')] != null;
+
+  if (has_io && has_html) {
+    throw "No embedder should have both dart:io and dart:html accessible";
+  }
+}
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index 9ae1758..ae38307 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -42,6 +42,13 @@
   Future<WebSocket> createClient(int port) =>
     WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
 
+  checkCloseStatus(webSocket, closeStatus, closeReason) {
+    Expect.equals(closeStatus == null ? WebSocketStatus.NO_STATUS_RECEIVED
+                                      : closeStatus, webSocket.closeCode);
+    Expect.equals(closeReason == null ? ""
+                                      : closeReason, webSocket.closeReason);
+  }
+
   void testRequestResponseClientCloses(int totalConnections,
                                        int closeStatus,
                                        String closeReason,
@@ -55,12 +62,7 @@
         webSocket.listen(
             webSocket.add,
             onDone: () {
-              Expect.equals(closeStatus == null
-                            ? WebSocketStatus.NO_STATUS_RECEIVED
-                            : closeStatus, webSocket.closeCode);
-              Expect.equals(
-                  closeReason == null ? ""
-                                      : closeReason, webSocket.closeReason);
+              checkCloseStatus(webSocket, closeStatus, closeReason);
               asyncEnd();
             });
         }, onDone: () {
@@ -85,10 +87,7 @@
                 }
               },
               onDone: () {
-                Expect.equals(closeStatus == null
-                              ? WebSocketStatus.NO_STATUS_RECEIVED
-                              : closeStatus, webSocket.closeCode);
-                Expect.equals("", webSocket.closeReason);
+                checkCloseStatus(webSocket, closeStatus, closeReason);
                 closeCount++;
                 if (closeCount == totalConnections) {
                   server.close();
@@ -119,10 +118,7 @@
               }
             },
             onDone: () {
-              Expect.equals(closeStatus == null
-                            ? WebSocketStatus.NO_STATUS_RECEIVED
-                            : closeStatus, webSocket.closeCode);
-              Expect.equals("", webSocket.closeReason);
+              checkCloseStatus(webSocket, closeStatus, closeReason);
               closeCount++;
               if (closeCount == totalConnections) {
                 server.close();
@@ -136,12 +132,7 @@
             webSocket.listen(
                 webSocket.add,
                 onDone: () {
-                  Expect.equals(closeStatus == null
-                                ? WebSocketStatus.NO_STATUS_RECEIVED
-                                : closeStatus, webSocket.closeCode);
-                  Expect.equals(closeReason == null
-                                ? ""
-                                : closeReason, webSocket.closeReason);
+                  checkCloseStatus(webSocket, closeStatus, closeReason);
                 });
             });
       }
@@ -363,8 +354,7 @@
               }
             },
             onDone: () {
-              Expect.equals(closeStatus, webSocket.closeCode);
-              Expect.equals("", webSocket.closeReason);
+              checkCloseStatus(webSocket, closeStatus, closeReason);
               closeCount++;
               if (closeCount == totalConnections) {
                 server.close();
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index c438459..f793816 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -29,6 +29,6 @@
 source_mirrors_test: Pass, RuntimeError # Issue 17662
 
 [ $compiler == dart2js && $cps_ir ]
-dummy_compiler_test: Crash # The null object does not have a getter '_element'.
-recursive_import_test: Crash # The null object does not have a getter '_element'.
-source_mirrors_test: Crash # The null object does not have a getter '_element'.
+dummy_compiler_test: Crash # (switch (function.na...  continue to a labeled switch case
+recursive_import_test: Crash # (switch (function.na...  continue to a labeled switch case
+source_mirrors_test: Crash # (switch (function.na...  continue to a labeled switch case
diff --git a/tools/VERSION b/tools/VERSION
index c43f1ce..1800f31 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 12
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index afdbaa2..1977d7a 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -12,8 +12,8 @@
   "dartium_chromium_branch": "master",
   "dartium_chromium_commit": "62a7524d4f71c9e0858d24b0aa1bbff3a2d09bff",
   "chromium_base_revision": "297060",
-  "dartium_webkit_branch": "/blink/branches/dart/dartium",
-  "dartium_webkit_revision": "198020",
+  "dartium_webkit_branch": "/blink/branches/dart/2171_3/dartium",
+  "dartium_webkit_revision": "199763",
 
   "args_tag": "@0.13.0",
   "barback_rev" : "@29ee90dbcf77cfd64632fa2797a4c8a4f29a4b51",
diff --git a/tools/gyp_dart.py b/tools/gyp_dart.py
index cce1b34..708d403 100644
--- a/tools/gyp_dart.py
+++ b/tools/gyp_dart.py
@@ -33,11 +33,6 @@
           '--depth=.', '-Itools/gyp/all.gypi',
           component_gyp_files[component]]
 
-  if sys.platform == 'win32':
-    # Generate Visual Studio 2010 compatible files by default.
-    if not os.environ.get('GYP_MSVS_VERSION'):
-      args.extend(['-G', 'msvs_version=2010'])
-
   sys.exit(execute(args))
 
 if __name__ == '__main__':
diff --git a/tools/utils.py b/tools/utils.py
index cc37f6a..2301d9b 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -97,7 +97,7 @@
 
 # Try to guess Visual Studio location when buiding on Windows.
 def GuessVisualStudioPath():
-  defaultPath = r"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7" \
+  defaultPath = r"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7" \
                 r"\IDE"
   defaultExecutable = "devenv.com"
 
@@ -142,8 +142,8 @@
               # Can't find value under the key - continue to the next key.
               continue
             isExpress = executable != 'devenv.com'
-            if not isExpress and subkeyName == '10.0':
-              # Stop search since if we found non-Express VS2010 version
+            if not isExpress and subkeyName == '12.0':
+              # Stop search since if we found non-Express VS2013 version
               # installed, which is preferred version.
               return installDir, executable
             else: