Version 1.21.0-dev.7.0

Merge de8e04d76a8974a5c18f34820b23b381565dec72 into dev
diff --git a/.packages b/.packages
index 3c252bb1..721c67e 100644
--- a/.packages
+++ b/.packages
@@ -72,7 +72,6 @@
 pool:third_party/pkg/pool/lib
 protobuf:third_party/pkg/protobuf/lib
 pub:third_party/pkg/pub/lib
-pub_cache:third_party/pkg/pub_cache/lib
 pub_semver:third_party/pkg/pub_semver/lib
 quiver:third_party/pkg/quiver/lib
 resource:third_party/pkg/resource/lib
diff --git a/.travis.yml b/.travis.yml
index ef84927..2f868f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -70,7 +70,7 @@
   - if [[ -z "$TEST" ]]; then ./tool/presubmit.sh ; fi
   - if [[ "$TEST" == coverage ]]; then ./tool/build_sdk.sh && ./tool/coverage.sh ; fi
   - if [[ "$TEST" == node ]]; then ./tool/node_test.sh ; fi
-  - if [[ "$TEST" == package ]]; then ./tool/build_sdk.sh && ./tool/build_pkgs.sh ; fi
+  - if [[ "$TEST" == package ]]; then ./tool/build_sdk.sh && ./tool/build_pkgs.dart ; fi
 env:
   - ANALYZER=master
   - ANALYZER=master DDC_BROWSERS=Firefox
diff --git a/DEPS b/DEPS
index ef26510..bfad3e5 100644
--- a/DEPS
+++ b/DEPS
@@ -91,7 +91,6 @@
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "@1.2.4",
   "protobuf_tag": "@0.5.3",
-  "pub_cache_tag": "@v0.1.0",
   "pub_rev": "@3dd04bd17ba269ccdd34502a253041dd96ded3be",
   "pub_semver_tag": "@1.3.0",
   "quiver_tag": "@0.22.0",
@@ -279,8 +278,6 @@
       (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("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"
diff --git a/dart.gyp b/dart.gyp
index 1bbf75e..5e1508d 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -42,6 +42,7 @@
       'dependencies': [
         'runtime/dart-runtime.gyp:dart_precompiled_runtime',
         'runtime/dart-runtime.gyp:dart_bootstrap#host',
+        'runtime/dart-runtime.gyp:process_test',
         'runtime/dart-runtime.gyp:generate_patched_sdk#host',
       ],
     },
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 4e37d5d..dad9113 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -1238,10 +1238,10 @@
  \end{grammar}
 
 \LMHash{}
-A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters. A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal. An {\em initializing formal} has the form \code{\THIS{}.$id$}, where $id$ is the name of an instance variable of the immediately enclosing class.  It is a compile-time error if \code{id} is not an instance variable of the immediately enclosing class. It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor.
+A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters. A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal. An {\em initializing formal} has the form \code{\THIS{}.$id$}, where $id$ is the name of an instance variable of the immediately enclosing class.  It is a compile-time error if $id$ is not an instance variable of the immediately enclosing class. It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor.
 
 \LMHash{}
-If an explicit type is attached to the initializing formal, that is its static type. Otherwise, the type of an initializing formal named \code{id} is $T_{id}$, where $T_{id}$ is the type of the field named \code{id} in the immediately enclosing class. It is a static warning if the static type of \code{id} is not assignable to $T_{id}$.
+If an explicit type is attached to the initializing formal, that is its static type. Otherwise, the type of an initializing formal named $id$ is $T_{id}$, where $T_{id}$ is the type of the field named $id$ in the immediately enclosing class. It is a static warning if the static type of $id$ is not assignable to $T_{id}$.
 
 \LMHash{}
 Initializing formals constitute an exception to the rule that every formal parameter introduces a local variable into the formal parameter scope (\ref{formalParameters}).
@@ -3154,7 +3154,7 @@
 
 The  exception to that would be a type $X$ that extended or implemented \code{Future}. In that case, only one unwrapping takes place. As an example of why this is done, consider
 
-\cd{\CLASS{} C<T>  \IMPLEMENTS{}  Future<C<C<T$>>>$ \ldots }
+\cd{\CLASS{} C<T>  \IMPLEMENTS{}  Future<C<C<T>>> \ldots }
 
 Here, a naive definition of $flatten$ diverges; there is not even a fixed point. A more sophisticated definition of $flatten$ is possible, but the existing rule deals with most realistic examples while remaining relatively simple to understand.
 
@@ -3713,10 +3713,15 @@
 If there exists a lexically visible declaration named $id$, let $f_{id}$ be the innermost such declaration. Then:
 \begin{itemize}
 \item
+If $id$ is a type literal, then $i$ is interpreted as a function expression invocation (ref{functionExpressionInvociation}) with $(id)$ as the expression $e_f$.
+\commentary{
+The expression $(id)$ where $id$ is a type literal always evaluates to an instance of class \code{Type} which is not a function. This ensures that a runtime error occurs when trying to call a type literal.
+}
+\item
 If $f_{id}$ is a prefix object, a compile-time error occurs.
 \item
- If $f_{id}$ is a local function, a library function, a library or static getter or a variable then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}).
- \item
+If $f_{id}$ is a local function, a library function, a library or static getter or a variable then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}).
+\item
 Otherwise, if $f_{id}$ is a static method of the enclosing class $C$, $i$ is equivalent to $C.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 \item Otherwise, $f_{id}$ is considered equivalent to the ordinary method invocation $\THIS{}.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 \end{itemize}
@@ -3743,7 +3748,14 @@
 
 $e_f(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
-where $e_f$ is an expression. If $e_f$ is an identifier $id$, then $id$ must necessarily denote a local function, a library function, a library or static getter or a variable as described above, or $i$ is not considered a function expression invocation. If $e_f$ is a property extraction expression (\ref{propertyExtraction}), then $i$ is is not a function expression invocation and is instead recognized as an ordinary method invocation (\ref{ordinaryInvocation}).
+where $e_f$ is an expression. If $e_f$ is an identifier $id$, then $id$ must necessarily denote a local function, a library function, a library or static getter or a variable as described above, or $i$ is not considered a function expression invocation.
+If $e_f$ is a type literal, then it is equivalent to the expression $(e_f)$.
+
+\commentary{
+The expression $(e_f)$ where $e_f$ is a type literal always evaluates to an instance of class \code{Type} which is not a function. This ensures that a runtime error occurs when trying to call a type literal.
+}
+
+If $e_f$ is a property extraction expression (\ref{propertyExtraction}), then $i$ is is not a function expression invocation and is instead recognized as an ordinary method invocation (\ref{ordinaryInvocation}).
 
 \commentary{
 \code{$a.b(x)$} is parsed as a method invocation of method \code{$b()$} on object \code{$a$}, not as an invocation of getter \code{$b$} on \code{$a$} followed by a function call \code{$(a.b)(x)$}.  If a method or getter \code{$b$} exists, the two will be equivalent. However, if \code{$b$} is not defined on \code{$a$}, the resulting invocation of \code{noSuchMethod()} would differ.  The \code{Invocation} passed to \code{noSuchMethod()} would describe a call to a method \code{$b$} with argument \code{$x$} in the former case, and a call to a getter \code{$b$} (with no arguments) in the latter.
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 391a76a..7d70974 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -29,6 +29,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/pub_package_map_provider.dart';
@@ -367,10 +368,15 @@
     defaultContextOptions.generateImplicitErrors = false;
     operationQueue = new ServerOperationQueue();
     _analysisPerformanceLogger = new nd.PerformanceLog(io.stdout);
-    byteStore = new MemoryCachingByteStore(
-        new FileByteStore(
-            resourceProvider.getStateLocation('.analysis-driver')),
-        64 * 1024 * 1024);
+    if (resourceProvider is PhysicalResourceProvider) {
+      byteStore = new MemoryCachingByteStore(
+          new FileByteStore(
+              resourceProvider.getStateLocation('.analysis-driver').path,
+              1024 * 1024 * 1024 /*1 GiB*/),
+          64 * 1024 * 1024 /*64 MiB*/);
+    } else {
+      byteStore = new MemoryByteStore();
+    }
     analysisDriverScheduler =
         new nd.AnalysisDriverScheduler(_analysisPerformanceLogger);
     analysisDriverScheduler.status.listen(sendStatusNotificationNew);
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index f47e10a..137d374 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.30.0-alpha.0
+* Changed the API for creating BazelWorkspace.  It should now be constructed using BazelWorkspace.find().  Note that this might return `null` in the event that the given path is not part of a BazelWorkspace.
+* Added an AST structure to support asserts in constructor initializers (AssertInitializer).  AstVisitor classes must now implement visitAssertInitializer().
+
 ## 0.29.0-alpha.0
 * Removed `Element.docRange`.
 
diff --git a/pkg/analyzer/lib/dart/ast/syntactic_entity.dart b/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
index 5ab6c78..8d6d0dc 100644
--- a/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
+++ b/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
@@ -4,5 +4,4 @@
 
 library analyzer.dart.ast.syntactic_entity;
 
-export 'package:front_end/src/scanner/syntactic_entity.dart'
-    show SyntacticEntity;
+export 'package:front_end/src/base/syntactic_entity.dart' show SyntacticEntity;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 388e0c8..8a4f9e8 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -13,9 +13,10 @@
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:front_end/src/base/errors.dart';
 import 'package:front_end/src/scanner/errors.dart';
 
-export 'package:front_end/src/scanner/errors.dart'
+export 'package:front_end/src/base/errors.dart'
     show ErrorCode, ErrorSeverity, ErrorType;
 
 const List<ErrorCode> errorCodeValues = const [
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index cdd912c..808c835 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -8,12 +8,20 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/source_resource.dart';
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:source_span/source_span.dart';
 import 'package:yaml/yaml.dart';
 
 /// Provide the options found in the analysis options file.
 class AnalysisOptionsProvider {
+  /// The source factory used to resolve include declarations
+  /// in analysis options files or `null` if include is not supported.
+  SourceFactory sourceFactory;
+
+  AnalysisOptionsProvider([this.sourceFactory]);
+
   /// Provide the options found in either
   /// [root]/[AnalysisEngine.ANALYSIS_OPTIONS_FILE] or
   /// [root]/[AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE].
@@ -30,15 +38,29 @@
         break;
       }
     }
-    String optionsText = _readAnalysisOptionsFile(resource);
-    return getOptionsFromString(optionsText);
+    return getOptionsFromFile(resource);
   }
 
   /// Provide the options found in [file].
   /// Return an empty options map if the file does not exist.
   Map<String, YamlNode> getOptionsFromFile(File file) {
-    var optionsSource = _readAnalysisOptionsFile(file);
-    return getOptionsFromString(optionsSource);
+    return getOptionsFromSource(new FileSource(file));
+  }
+
+  /// Provide the options found in [source].
+  /// Return an empty options map if the file does not exist.
+  Map<String, YamlNode> getOptionsFromSource(Source source) {
+    Map<String, YamlNode> options =
+        getOptionsFromString(_readAnalysisOptions(source));
+    YamlNode node = options.remove('include');
+    if (sourceFactory != null && node is YamlScalar) {
+      var path = node.value;
+      if (path is String) {
+        Source parent = sourceFactory.resolveUri(source, path);
+        options = merge(getOptionsFromSource(parent), options);
+      }
+    }
+    return options;
   }
 
   /// Provide the options found in [optionsSource].
@@ -110,13 +132,13 @@
           Map<String, YamlNode> defaults, Map<String, YamlNode> overrides) =>
       new Merger().merge(defaults, overrides) as Map<String, YamlNode>;
 
-  /// Read the contents of [file] as a string.
-  /// Returns null if file does not exist.
-  String _readAnalysisOptionsFile(File file) {
+  /// Read the contents of [source] as a string.
+  /// Returns null if source is null or does not exist.
+  String _readAnalysisOptions(Source source) {
     try {
-      return file.readAsStringSync();
-    } on FileSystemException {
-      // File can't be read.
+      return source.contents.data;
+    } catch (e) {
+      // Source can't be read.
       return null;
     }
   }
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index d0d9b1e..75875f7 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -336,9 +336,20 @@
     if (optionsFile != null) {
       List<OptionsProcessor> optionsProcessors =
           AnalysisEngine.instance.optionsPlugin.optionsProcessors;
+      // TODO(danrubel) restructure so that we don't recalculate the package map
+      // more than once per path.
+      Packages packages = createPackageMap(path);
+      Map<String, List<Folder>> packageMap = convertPackagesToMap(packages);
+      List<UriResolver> resolvers = <UriResolver>[
+        new ResourceUriResolver(resourceProvider),
+        new PackageMapUriResolver(resourceProvider, packageMap),
+      ];
+      SourceFactory sourceFactory =
+          new SourceFactory(resolvers, packages, resourceProvider);
       try {
         Map<String, YamlNode> optionMap =
-            new AnalysisOptionsProvider().getOptionsFromFile(optionsFile);
+            new AnalysisOptionsProvider(sourceFactory)
+                .getOptionsFromFile(optionsFile);
         optionsProcessors.forEach(
             (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
         applyToAnalysisOptions(options, optionMap);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index f18e767..543e382 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -342,8 +342,9 @@
   }
 
   /**
-   * Return the [Future] that completes with a [AnalysisResult] for the file
-   * with the given [path].
+   * Return the [Future] that completes with a [AnalysisResult] for the Dart
+   * file with the given [path]. If the file is not a Dart file, the [Future]
+   * completes with `null`.
    *
    * The [path] must be absolute and normalized.
    *
@@ -356,13 +357,16 @@
    * transitions to "idle".
    */
   Future<AnalysisResult> getResult(String path) {
-    var completer = new Completer<AnalysisResult>();
-    _requestedFiles
-        .putIfAbsent(path, () => <Completer<AnalysisResult>>[])
-        .add(completer);
-    _statusSupport.transitionToAnalyzing();
-    _scheduler._notify(this);
-    return completer.future;
+    if (AnalysisEngine.isDartFileName(path)) {
+      var completer = new Completer<AnalysisResult>();
+      _requestedFiles
+          .putIfAbsent(path, () => <Completer<AnalysisResult>>[])
+          .add(completer);
+      _statusSupport.transitionToAnalyzing();
+      _scheduler._notify(this);
+      return completer.future;
+    }
+    return new Future.value();
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
index 49e668f..46f4648 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
@@ -2,24 +2,35 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/file_system/file_system.dart';
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
+import 'package:path/path.dart';
 
 /**
- * [ByteStore] that stores values as [File]s.
- *
- * TODO(scheglov) Add some eviction policies.
+ * [ByteStore] that stores values as files.
  */
 class FileByteStore implements ByteStore {
-  final Folder folder;
+  static bool _cleanUpSendPortShouldBePrepared = true;
+  static SendPort _cleanUpSendPort;
 
-  FileByteStore(this.folder);
+  final String _cachePath;
+  final String _tempName = 'temp_${pid}';
+  final int _maxSizeBytes;
+
+  int _bytesWrittenSinceCleanup = 0;
+  bool _evictionIsolateIsRunning = false;
+
+  FileByteStore(this._cachePath, this._maxSizeBytes) {
+    _requestCacheCleanUp();
+  }
 
   @override
   List<int> get(String key) {
     try {
-      File file = folder.getChildAssumingFile(key);
-      return file.readAsBytesSync();
+      return _getFileForKey(key).readAsBytesSync();
     } catch (_) {
       return null;
     }
@@ -28,8 +39,103 @@
   @override
   void put(String key, List<int> bytes) {
     try {
-      File file = folder.getChildAssumingFile(key);
-      file.writeAsBytesSync(bytes);
+      File tempFile = _getFileForKey(_tempName);
+      tempFile.writeAsBytesSync(bytes);
+      File file = _getFileForKey(key);
+      tempFile.renameSync(file.path);
+      // Update the current size.
+      _bytesWrittenSinceCleanup += bytes.length;
+      if (_bytesWrittenSinceCleanup > _maxSizeBytes ~/ 8) {
+        _requestCacheCleanUp();
+      }
     } catch (_) {}
   }
+
+  File _getFileForKey(String key) {
+    return new File(join(_cachePath, key));
+  }
+
+  /**
+   * If the cache clean up process has not been requested yet, request it.
+   */
+  Future<Null> _requestCacheCleanUp() async {
+    if (_cleanUpSendPortShouldBePrepared) {
+      _cleanUpSendPortShouldBePrepared = false;
+      ReceivePort response = new ReceivePort();
+      await Isolate.spawn(_cacheCleanUpFunction, response.sendPort);
+      _cleanUpSendPort = await response.first as SendPort;
+    } else {
+      while (_cleanUpSendPort == null) {
+        await new Future.delayed(new Duration(milliseconds: 100), () {});
+      }
+    }
+
+    if (!_evictionIsolateIsRunning) {
+      _evictionIsolateIsRunning = true;
+      try {
+        ReceivePort response = new ReceivePort();
+        _cleanUpSendPort.send([_cachePath, _maxSizeBytes, response.sendPort]);
+        await response.first;
+      } finally {
+        _evictionIsolateIsRunning = false;
+        _bytesWrittenSinceCleanup = 0;
+      }
+    }
+  }
+
+  /**
+   * This function is started in a new isolate, receives cache folder clean up
+   * requests and evicts older files from the folder.
+   */
+  static void _cacheCleanUpFunction(SendPort initialReplyTo) {
+    ReceivePort port = new ReceivePort();
+    initialReplyTo.send(port.sendPort);
+    port.listen((args) async {
+      if (args is List &&
+          args.length == 3 &&
+          args[0] is String &&
+          args[1] is int &&
+          args[2] is SendPort) {
+        String cachePath = args[0] as String;
+        int maxSizeBytes = args[1] as int;
+        await _cleanUpFolder(cachePath, maxSizeBytes);
+        // Let that client know that we're done.
+        SendPort replyTo = args[2] as SendPort;
+        replyTo.send(true);
+      }
+    });
+  }
+
+  static Future<Null> _cleanUpFolder(String cachePath, int maxSizeBytes) async {
+    // Prepare the list of files and their statistics.
+    List<File> files = <File>[];
+    Map<File, FileStat> fileStatMap = {};
+    int currentSizeBytes = 0;
+    List<FileSystemEntity> resources = new Directory(cachePath).listSync();
+    for (FileSystemEntity resource in resources) {
+      if (resource is File) {
+        try {
+          FileStat fileStat = await resource.stat();
+          files.add(resource);
+          fileStatMap[resource] = fileStat;
+          currentSizeBytes += fileStat.size;
+        } catch (_) {}
+      }
+    }
+    files.sort((a, b) {
+      return fileStatMap[a].accessed.millisecondsSinceEpoch -
+          fileStatMap[b].accessed.millisecondsSinceEpoch;
+    });
+
+    // Delete files until the current size is less than the max.
+    for (File file in files) {
+      if (currentSizeBytes < maxSizeBytes) {
+        break;
+      }
+      try {
+        await file.delete();
+      } catch (_) {}
+      currentSizeBytes -= fileStatMap[file].size;
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/scanner/reader.dart b/pkg/analyzer/lib/src/dart/scanner/reader.dart
index 54f367b..6e111e2 100644
--- a/pkg/analyzer/lib/src/dart/scanner/reader.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/reader.dart
@@ -6,7 +6,8 @@
 
 import 'package:front_end/src/scanner/reader.dart';
 
-export 'package:front_end/src/scanner/reader.dart' show CharacterReader;
+export 'package:front_end/src/scanner/reader.dart'
+    show CharacterReader, CharSequenceReader, SubSequenceReader;
 
 /**
  * A [CharacterReader] that reads a range of characters from another character
@@ -59,92 +60,3 @@
     return baseReader.peek();
   }
 }
-
-/**
- * A [CharacterReader] that reads characters from a character sequence.
- */
-class CharSequenceReader implements CharacterReader {
-  /**
-   * The sequence from which characters will be read.
-   */
-  final String _sequence;
-
-  /**
-   * The number of characters in the string.
-   */
-  int _stringLength;
-
-  /**
-   * The index, relative to the string, of the next character to be read.
-   */
-  int _charOffset;
-
-  /**
-   * Initialize a newly created reader to read the characters in the given
-   * [_sequence].
-   */
-  CharSequenceReader(this._sequence) {
-    this._stringLength = _sequence.length;
-    this._charOffset = 0;
-  }
-
-  @override
-  int get offset => _charOffset - 1;
-
-  @override
-  void set offset(int offset) {
-    _charOffset = offset + 1;
-  }
-
-  @override
-  int advance() {
-    if (_charOffset >= _stringLength) {
-      return -1;
-    }
-    return _sequence.codeUnitAt(_charOffset++);
-  }
-
-  @override
-  String getString(int start, int endDelta) =>
-      _sequence.substring(start, _charOffset + endDelta);
-
-  @override
-  int peek() {
-    if (_charOffset >= _stringLength) {
-      return -1;
-    }
-    return _sequence.codeUnitAt(_charOffset);
-  }
-}
-
-/**
- * A [CharacterReader] that reads characters from a character sequence, but adds
- * a delta when reporting the current character offset so that the character
- * sequence can be a subsequence from a larger sequence.
- */
-class SubSequenceReader extends CharSequenceReader {
-  /**
-   * The offset from the beginning of the file to the beginning of the source
-   * being scanned.
-   */
-  final int _offsetDelta;
-
-  /**
-   * Initialize a newly created reader to read the characters in the given
-   * [sequence]. The [_offsetDelta] is the offset from the beginning of the file
-   * to the beginning of the source being scanned
-   */
-  SubSequenceReader(String sequence, this._offsetDelta) : super(sequence);
-
-  @override
-  int get offset => _offsetDelta + super.offset;
-
-  @override
-  void set offset(int offset) {
-    super.offset = offset - _offsetDelta;
-  }
-
-  @override
-  String getString(int start, int endDelta) =>
-      super.getString(start - _offsetDelta, endDelta);
-}
diff --git a/pkg/analyzer/lib/src/generated/bazel.dart b/pkg/analyzer/lib/src/generated/bazel.dart
index b81a0c8..8d014c7 100644
--- a/pkg/analyzer/lib/src/generated/bazel.dart
+++ b/pkg/analyzer/lib/src/generated/bazel.dart
@@ -143,6 +143,12 @@
   static const String _WORKSPACE = 'WORKSPACE';
   static const String _READONLY = 'READONLY';
 
+  /**
+   * Default prefix for "-genfiles" and "-bin" that will be assumed if no build
+   * output symlinks are found.
+   */
+  static const defaultSymlinkPrefix = 'bazel';
+
   final ResourceProvider provider;
 
   /**
@@ -197,6 +203,11 @@
           return file;
         }
       }
+      // Writable
+      File writableFile = provider.getFile(absolutePath);
+      if (writableFile.exists) {
+        return writableFile;
+      }
       // READONLY
       if (readonly != null) {
         File file = provider.getFile(context.join(readonly, relative));
@@ -205,7 +216,7 @@
         }
       }
       // Not generated, return the default one.
-      return provider.getFile(absolutePath);
+      return writableFile;
     } catch (_) {
       return null;
     }
@@ -281,8 +292,9 @@
 
   /**
    * Return the symlink prefix for folders `X-bin` or `X-genfiles` by probing
-   * the internal `blaze-genfiles` and `bazel-genfiles`. Return `null` if
-   * neither of the folders exists.
+   * the internal `blaze-genfiles` and `bazel-genfiles`. Make a default
+   * assumption according to defaultSymlinkPrefix if neither of the folders
+   * exists.
    */
   static String _findSymlinkPrefix(ResourceProvider provider, String root) {
     Context context = provider.pathContext;
@@ -292,6 +304,7 @@
     if (provider.getFolder(context.join(root, 'bazel-genfiles')).exists) {
       return 'bazel';
     }
-    return null;
+    // Couldn't find it.  Make a default assumption.
+    return defaultSymlinkPrefix;
   }
 }
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index a33beba..6a78ba5 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -29,12 +29,14 @@
 import 'package:analyzer/src/task/manager.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/model.dart';
+import 'package:front_end/src/base/timestamped_data.dart';
 import 'package:html/dom.dart' show Document;
 import 'package:path/path.dart' as pathos;
 import 'package:plugin/manager.dart';
 import 'package:plugin/plugin.dart';
 
 export 'package:analyzer/error/listener.dart' show RecordingErrorListener;
+export 'package:front_end/src/base/timestamped_data.dart' show TimestampedData;
 
 /**
  * Used by [AnalysisOptions] to allow function bodies to be analyzed in some
@@ -2720,24 +2722,3 @@
       _changeSet.removedSources.length > 0 ||
       _changeSet.removedContainers.length > 0;
 }
-
-/**
- * Analysis data for which we have a modification time.
- */
-class TimestampedData<E> {
-  /**
-   * The modification time of the source from which the data was created.
-   */
-  final int modificationTime;
-
-  /**
-   * The data that was created from the source.
-   */
-  final E data;
-
-  /**
-   * Initialize a newly created holder to associate the given [data] with the
-   * given [modificationTime].
-   */
-  TimestampedData(this.modificationTime, this.data);
-}
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index d847a7b..b718661 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -665,6 +665,14 @@
             } else if (oldParent is FunctionBody && newParent is FunctionBody) {
               if (oldParent is BlockFunctionBody &&
                   newParent is BlockFunctionBody) {
+                if (oldParent.isAsynchronous != newParent.isAsynchronous) {
+                  logger.log('Failure: body async mismatch.');
+                  return false;
+                }
+                if (oldParent.isGenerator != newParent.isGenerator) {
+                  logger.log('Failure: body generator mismatch.');
+                  return false;
+                }
                 oldNode = oldParent;
                 newNode = newParent;
                 found = true;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7a36d85..8208abb 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -424,7 +424,8 @@
 
   void _checkForAbstractSuperMemberReference(
       Expression target, SimpleIdentifier name) {
-    if (target is SuperExpression) {
+    if (target is SuperExpression &&
+        !_currentLibrary.context.analysisOptions.enableSuperMixins) {
       Element element = name.staticElement;
       if (element is ExecutableElement && element.isAbstract) {
         if (!_enclosingClass.hasNoSuchMethod) {
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 7f95c01..e4ceae7 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -8,17 +8,20 @@
 import "dart:math" as math;
 
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource;
-import 'package:analyzer/task/model.dart';
+import 'package:front_end/src/base/source.dart';
+import 'package:front_end/src/base/uri_kind.dart';
 import 'package:package_config/packages.dart';
 import 'package:path/path.dart' as pathos;
 
+export 'package:front_end/src/base/source.dart' show Source;
+export 'package:front_end/src/base/uri_kind.dart' show UriKind;
+
 /**
  * A function that is used to visit [ContentCache] entries.
  */
@@ -411,147 +414,6 @@
 }
 
 /**
- * The interface `Source` defines the behavior of objects representing source code that can be
- * analyzed by the analysis engine.
- *
- * Implementations of this interface need to be aware of some assumptions made by the analysis
- * engine concerning sources:
- * * Sources are not required to be unique. That is, there can be multiple instances representing
- * the same source.
- * * Sources are long lived. That is, the engine is allowed to hold on to a source for an extended
- * period of time and that source must continue to report accurate and up-to-date information.
- * Because of these assumptions, most implementations will not maintain any state but will delegate
- * to an authoritative system of record in order to implement this API. For example, a source that
- * represents files on disk would typically query the file system to determine the state of the
- * file.
- *
- * If the instances that implement this API are the system of record, then they will typically be
- * unique. In that case, sources that are created that represent non-existent files must also be
- * retained so that if those files are created at a later date the long-lived sources representing
- * those files will know that they now exist.
- */
-abstract class Source implements AnalysisTarget {
-  /**
-   * An empty list of sources.
-   */
-  static const List<Source> EMPTY_LIST = const <Source>[];
-
-  /**
-   * Get the contents and timestamp of this source.
-   *
-   * Clients should consider using the method [AnalysisContext.getContents]
-   * because contexts can have local overrides of the content of a source that the source is not
-   * aware of.
-   *
-   * @return the contents and timestamp of the source
-   * @throws Exception if the contents of this source could not be accessed
-   */
-  TimestampedData<String> get contents;
-
-  /**
-   * Return an encoded representation of this source that can be used to create a source that is
-   * equal to this source.
-   *
-   * @return an encoded representation of this source
-   * See [SourceFactory.fromEncoding].
-   */
-  String get encoding;
-
-  /**
-   * Return the full (long) version of the name that can be displayed to the user to denote this
-   * source. For example, for a source representing a file this would typically be the absolute path
-   * of the file.
-   *
-   * @return a name that can be displayed to the user to denote this source
-   */
-  String get fullName;
-
-  /**
-   * Return a hash code for this source.
-   *
-   * @return a hash code for this source
-   * See [Object.hashCode].
-   */
-  @override
-  int get hashCode;
-
-  /**
-   * Return `true` if this source is in one of the system libraries.
-   *
-   * @return `true` if this is in a system library
-   */
-  bool get isInSystemLibrary;
-
-  @override
-  Source get librarySource => null;
-
-  /**
-   * Return the modification stamp for this source, or a negative value if the
-   * source does not exist. A modification stamp is a non-negative integer with
-   * the property that if the contents of the source have not been modified
-   * since the last time the modification stamp was accessed then the same value
-   * will be returned, but if the contents of the source have been modified one
-   * or more times (even if the net change is zero) the stamps will be different.
-   *
-   * Clients should consider using the method
-   * [AnalysisContext.getModificationStamp] because contexts can have local
-   * overrides of the content of a source that the source is not aware of.
-   */
-  int get modificationStamp;
-
-  /**
-   * Return a short version of the name that can be displayed to the user to denote this source. For
-   * example, for a source representing a file this would typically be the name of the file.
-   *
-   * @return a name that can be displayed to the user to denote this source
-   */
-  String get shortName;
-
-  @override
-  Source get source => this;
-
-  /**
-   * Return the URI from which this source was originally derived.
-   *
-   * @return the URI from which this source was originally derived
-   */
-  Uri get uri;
-
-  /**
-   * Return the kind of URI from which this source was originally derived. If this source was
-   * created from an absolute URI, then the returned kind will reflect the scheme of the absolute
-   * URI. If it was created from a relative URI, then the returned kind will be the same as the kind
-   * of the source against which the relative URI was resolved.
-   *
-   * @return the kind of URI from which this source was originally derived
-   */
-  UriKind get uriKind;
-
-  /**
-   * Return `true` if the given object is a source that represents the same source code as
-   * this source.
-   *
-   * @param object the object to be compared with this object
-   * @return `true` if the given object is a source that represents the same source code as
-   *         this source
-   * See [Object.==].
-   */
-  @override
-  bool operator ==(Object object);
-
-  /**
-   * Return `true` if this source exists.
-   *
-   * Clients should consider using the method [AnalysisContext.exists] because
-   * contexts can have local overrides of the content of a source that the source is not aware of
-   * and a source with local content is considered to exist even if there is no file on disk.
-   *
-   * @return `true` if this source exists
-   */
-  bool exists();
-}
-
-/**
  * The interface `ContentReceiver` defines the behavior of objects that can receive the
  * content of a source.
  */
@@ -863,90 +725,6 @@
 }
 
 /**
- * The enumeration `UriKind` defines the different kinds of URI's that are known to the
- * analysis engine. These are used to keep track of the kind of URI associated with a given source.
- */
-class UriKind implements Comparable<UriKind> {
-  /**
-   * A 'dart:' URI.
-   */
-  static const UriKind DART_URI = const UriKind('DART_URI', 0, 0x64);
-
-  /**
-   * A 'file:' URI.
-   */
-  static const UriKind FILE_URI = const UriKind('FILE_URI', 1, 0x66);
-
-  /**
-   * A 'package:' URI.
-   */
-  static const UriKind PACKAGE_URI = const UriKind('PACKAGE_URI', 2, 0x70);
-
-  static const List<UriKind> values = const [DART_URI, FILE_URI, PACKAGE_URI];
-
-  /**
-   * The name of this URI kind.
-   */
-  final String name;
-
-  /**
-   * The ordinal value of the URI kind.
-   */
-  final int ordinal;
-
-  /**
-   * The single character encoding used to identify this kind of URI.
-   */
-  final int encoding;
-
-  /**
-   * Initialize a newly created URI kind to have the given encoding.
-   */
-  const UriKind(this.name, this.ordinal, this.encoding);
-
-  @override
-  int get hashCode => ordinal;
-
-  @override
-  int compareTo(UriKind other) => ordinal - other.ordinal;
-
-  @override
-  String toString() => name;
-
-  /**
-   * Return the URI kind represented by the given [encoding], or `null` if there
-   * is no kind with the given encoding.
-   */
-  static UriKind fromEncoding(int encoding) {
-    while (true) {
-      if (encoding == 0x64) {
-        return DART_URI;
-      } else if (encoding == 0x66) {
-        return FILE_URI;
-      } else if (encoding == 0x70) {
-        return PACKAGE_URI;
-      }
-      break;
-    }
-    return null;
-  }
-
-  /**
-   * Return the URI kind corresponding to the given scheme string.
-   */
-  static UriKind fromScheme(String scheme) {
-    if (scheme == PackageMapUriResolver.PACKAGE_SCHEME) {
-      return UriKind.PACKAGE_URI;
-    } else if (scheme == DartUriResolver.DART_SCHEME) {
-      return UriKind.DART_URI;
-    } else if (scheme == ResourceUriResolver.FILE_SCHEME) {
-      return UriKind.FILE_URI;
-    }
-    return UriKind.FILE_URI;
-  }
-}
-
-/**
  * The abstract class `UriResolver` defines the behavior of objects that are used to resolve
  * URI's for a source factory. Subclasses of this class are expected to resolve a single scheme of
  * absolute URI.
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index b9dca93..d13ad35 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -7,6 +7,8 @@
 import 'dart:collection';
 import 'dart:developer' show UserTag;
 
+export 'package:front_end/src/base/jenkins_smi_hash.dart' show JenkinsSmiHash;
+
 /**
  * Test if the given [value] is `false` or the string "false" (case-insensitive).
  */
@@ -50,31 +52,6 @@
 String toUpperCase(Object value) => value?.toString()?.toUpperCase();
 
 /**
- * Jenkins hash function, optimized for small integers.
- * Borrowed from sdk/lib/math/jenkins_smi_hash.dart.
- */
-class JenkinsSmiHash {
-  static int combine(int hash, int value) {
-    hash = 0x1fffffff & (hash + value);
-    hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
-    return hash ^ (hash >> 6);
-  }
-
-  static int finish(int hash) {
-    hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
-    hash = hash ^ (hash >> 11);
-    return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
-  }
-
-  static int hash2(a, b) => finish(combine(combine(0, a), b));
-
-  static int hash3(a, b, c) => finish(combine(combine(combine(0, a), b), c));
-
-  static int hash4(a, b, c, d) =>
-      finish(combine(combine(combine(combine(0, a), b), c), d));
-}
-
-/**
  * A simple limited queue.
  */
 class LimitedQueue<E> extends ListQueue<E> {
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 2a6f6c5..9d1f6ba 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -14,6 +14,9 @@
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/task/driver.dart';
 import 'package:analyzer/src/task/model.dart';
+import 'package:front_end/src/base/analysis_target.dart';
+
+export 'package:front_end/src/base/analysis_target.dart' show AnalysisTarget;
 
 /**
  * A function that converts the given [key] and [value] into a [TaskInput].
@@ -68,27 +71,6 @@
 }
 
 /**
- * An object with which an analysis result can be associated.
- *
- * Clients may implement this class when creating new kinds of targets.
- * Instances of this type are used in hashed data structures, so subtypes are
- * required to correctly implement [==] and [hashCode].
- */
-abstract class AnalysisTarget {
-  /**
-   * If this target is associated with a library, return the source of the
-   * library's defining compilation unit; otherwise return `null`.
-   */
-  Source get librarySource;
-
-  /**
-   * Return the source associated with this target, or `null` if this target is
-   * not associated with a source.
-   */
-  Source get source;
-}
-
-/**
  * An object used to compute one or more analysis results associated with a
  * single target.
  *
diff --git a/pkg/analyzer/test/generated/bazel_test.dart b/pkg/analyzer/test/generated/bazel_test.dart
index cc1a75a..884ffb5 100644
--- a/pkg/analyzer/test/generated/bazel_test.dart
+++ b/pkg/analyzer/test/generated/bazel_test.dart
@@ -570,10 +570,14 @@
   }
 
   void test_find_null_symlinkPrefix() {
+    String prefix = BazelWorkspace.defaultSymlinkPrefix;
     provider.newFile(_p('/workspace/WORKSPACE'), '');
     BazelWorkspace workspace =
         BazelWorkspace.find(provider, _p('/workspace/my/module'));
-    expect(workspace, isNull);
+    expect(workspace.root, _p('/workspace'));
+    expect(workspace.readonly, isNull);
+    expect(workspace.bin, _p('/workspace/$prefix-bin'));
+    expect(workspace.genfiles, _p('/workspace/$prefix-genfiles'));
   }
 
   void test_findFile_hasReadonlyFolder() {
@@ -612,6 +616,22 @@
         _p('/Users/user/test/READONLY/prime/other/module/test4.dart'));
   }
 
+  void test_findFile_main_overrides_readonly() {
+    provider.newFolder(_p('/Users/user/test/READONLY/prime'));
+    provider.newFolder(_p('/Users/user/test/prime'));
+    provider.newFolder(_p('/Users/user/test/prime/bazel-genfiles'));
+    provider.newFile(_p('/Users/user/test/prime/my/module/test.dart'), '');
+    provider.newFile(
+        _p('/Users/user/test/READONLY/prime/my/module/test.dart'), '');
+    BazelWorkspace workspace =
+        BazelWorkspace.find(provider, _p('/Users/user/test/prime/my/module'));
+    expect(
+        workspace
+            .findFile(_p('/Users/user/test/prime/my/module/test.dart'))
+            .path,
+        _p('/Users/user/test/prime/my/module/test.dart'));
+  }
+
   void test_findFile_noReadOnly() {
     provider.newFile(_p('/workspace/WORKSPACE'), '');
     provider.newFile(_p('/workspace/my/module/test1.dart'), '');
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index eba3450..5bfd2a9 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -1011,6 +1011,55 @@
         expectedSuccess: false);
   }
 
+  void test_false_inBody_addAsync() {
+    _resolveUnit(r'''
+class C {
+  test() {}
+}
+''');
+    _updateAndValidate(
+        r'''
+class C {
+  test() async {}
+}
+''',
+        expectedSuccess: false);
+  }
+
+  void test_false_inBody_async_addStar() {
+    _resolveUnit(r'''
+import 'dart:async';
+class C {
+  Stream test() async {}
+}
+''');
+    _updateAndValidate(
+        r'''
+import 'dart:async';
+class C {
+  Stream test() async* {}
+}
+''',
+        expectedSuccess: false);
+  }
+
+  void test_false_inBody_async_removeStar() {
+    _resolveUnit(r'''
+import 'dart:async';
+class C {
+  Stream test() async* {}
+}
+''');
+    _updateAndValidate(
+        r'''
+import 'dart:async';
+class C {
+  Stream test() async {}
+}
+''',
+        expectedSuccess: false);
+  }
+
   void test_false_inBody_functionExpression() {
     _resolveUnit(r'''
 class C extends D {
@@ -1034,6 +1083,36 @@
         expectedSuccess: false);
   }
 
+  void test_false_inBody_removeAsync() {
+    _resolveUnit(r'''
+class C {
+  test() async {}
+}
+''');
+    _updateAndValidate(
+        r'''
+class C {
+  test() {}
+}
+''',
+        expectedSuccess: false);
+  }
+
+  void test_false_inBody_sync_addStar() {
+    _resolveUnit(r'''
+class C {
+  test() {}
+}
+''');
+    _updateAndValidate(
+        r'''
+class C {
+  test() sync* {}
+}
+''',
+        expectedSuccess: false);
+  }
+
   void test_false_topLevelFunction_name() {
     _resolveUnit(r'''
 a() {}
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index eda3e13..2ef678b 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -19,6 +20,23 @@
 
 @reflectiveTest
 class NonHintCodeTest extends ResolverTestCase {
+  void test_() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+    Source source = addSource(r'''
+abstract class A {
+  void test();
+}
+class B extends A {
+  void test() {
+    super.test;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_deadCode_afterTryCatch() {
     Source source = addSource('''
 main() {
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 748bab4..92d6621 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -5,8 +5,6 @@
 library analyzer.test.generated.scanner_test;
 
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -18,10 +16,7 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(CharSequenceReaderTest);
-    defineReflectiveTests(KeywordStateTest);
-    defineReflectiveTests(ScannerTest);
-    defineReflectiveTests(TokenTypeTest);
+    defineReflectiveTests(LineInfoTest);
   });
 }
 
@@ -82,547 +77,7 @@
 }
 
 @reflectiveTest
-class CharSequenceReaderTest {
-  void test_advance() {
-    CharSequenceReader reader = new CharSequenceReader("x");
-    expect(reader.advance(), 0x78);
-    expect(reader.advance(), -1);
-    expect(reader.advance(), -1);
-  }
-
-  void test_creation() {
-    expect(new CharSequenceReader("x"), isNotNull);
-  }
-
-  void test_getOffset() {
-    CharSequenceReader reader = new CharSequenceReader("x");
-    expect(reader.offset, -1);
-    reader.advance();
-    expect(reader.offset, 0);
-    reader.advance();
-    expect(reader.offset, 0);
-  }
-
-  void test_getString() {
-    CharSequenceReader reader = new CharSequenceReader("xyzzy");
-    reader.offset = 3;
-    expect(reader.getString(1, 0), "yzz");
-    expect(reader.getString(2, 1), "zzy");
-  }
-
-  void test_peek() {
-    CharSequenceReader reader = new CharSequenceReader("xy");
-    expect(reader.peek(), 0x78);
-    expect(reader.peek(), 0x78);
-    reader.advance();
-    expect(reader.peek(), 0x79);
-    expect(reader.peek(), 0x79);
-    reader.advance();
-    expect(reader.peek(), -1);
-    expect(reader.peek(), -1);
-  }
-
-  void test_setOffset() {
-    CharSequenceReader reader = new CharSequenceReader("xyz");
-    reader.offset = 2;
-    expect(reader.offset, 2);
-  }
-}
-
-@reflectiveTest
-class KeywordStateTest {
-  void test_KeywordState() {
-    //
-    // Generate the test data to be scanned.
-    //
-    List<Keyword> keywords = Keyword.values;
-    int keywordCount = keywords.length;
-    List<String> textToTest = new List<String>(keywordCount * 3);
-    for (int i = 0; i < keywordCount; i++) {
-      String syntax = keywords[i].syntax;
-      textToTest[i] = syntax;
-      textToTest[i + keywordCount] = "${syntax}x";
-      textToTest[i + keywordCount * 2] = syntax.substring(0, syntax.length - 1);
-    }
-    //
-    // Scan each of the identifiers.
-    //
-    KeywordState firstState = KeywordState.KEYWORD_STATE;
-    for (int i = 0; i < textToTest.length; i++) {
-      String text = textToTest[i];
-      int index = 0;
-      int length = text.length;
-      KeywordState state = firstState;
-      while (index < length && state != null) {
-        state = state.next(text.codeUnitAt(index));
-        index++;
-      }
-      if (i < keywordCount) {
-        // keyword
-        expect(state, isNotNull);
-        expect(state.keyword(), isNotNull);
-        expect(state.keyword(), keywords[i]);
-      } else if (i < keywordCount * 2) {
-        // keyword + "x"
-        expect(state, isNull);
-      } else {
-        // keyword.substring(0, keyword.length() - 1)
-        expect(state, isNotNull);
-      }
-    }
-  }
-}
-
-@reflectiveTest
-class ScannerTest {
-  void fail_incomplete_string_interpolation() {
-    // https://code.google.com/p/dart/issues/detail?id=18073
-    _assertErrorAndTokens(
-        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9, "\"foo \${bar", [
-      new StringToken(TokenType.STRING, "\"foo ", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 5),
-      new StringToken(TokenType.IDENTIFIER, "bar", 7)
-    ]);
-  }
-
-  void test_ampersand() {
-    _assertToken(TokenType.AMPERSAND, "&");
-  }
-
-  void test_ampersand_ampersand() {
-    _assertToken(TokenType.AMPERSAND_AMPERSAND, "&&");
-  }
-
-  void test_ampersand_ampersand_eq() {
-    _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=",
-        lazyAssignmentOperators: true);
-  }
-
-  void test_ampersand_eq() {
-    _assertToken(TokenType.AMPERSAND_EQ, "&=");
-  }
-
-  void test_at() {
-    _assertToken(TokenType.AT, "@");
-  }
-
-  void test_backping() {
-    _assertToken(TokenType.BACKPING, "`");
-  }
-
-  void test_backslash() {
-    _assertToken(TokenType.BACKSLASH, "\\");
-  }
-
-  void test_bang() {
-    _assertToken(TokenType.BANG, "!");
-  }
-
-  void test_bang_eq() {
-    _assertToken(TokenType.BANG_EQ, "!=");
-  }
-
-  void test_bar() {
-    _assertToken(TokenType.BAR, "|");
-  }
-
-  void test_bar_bar() {
-    _assertToken(TokenType.BAR_BAR, "||");
-  }
-
-  void test_bar_bar_eq() {
-    _assertToken(TokenType.BAR_BAR_EQ, "||=", lazyAssignmentOperators: true);
-  }
-
-  void test_bar_eq() {
-    _assertToken(TokenType.BAR_EQ, "|=");
-  }
-
-  void test_caret() {
-    _assertToken(TokenType.CARET, "^");
-  }
-
-  void test_caret_eq() {
-    _assertToken(TokenType.CARET_EQ, "^=");
-  }
-
-  void test_close_curly_bracket() {
-    _assertToken(TokenType.CLOSE_CURLY_BRACKET, "}");
-  }
-
-  void test_close_paren() {
-    _assertToken(TokenType.CLOSE_PAREN, ")");
-  }
-
-  void test_close_quare_bracket() {
-    _assertToken(TokenType.CLOSE_SQUARE_BRACKET, "]");
-  }
-
-  void test_colon() {
-    _assertToken(TokenType.COLON, ":");
-  }
-
-  void test_comma() {
-    _assertToken(TokenType.COMMA, ",");
-  }
-
-  void test_comment_disabled_multi() {
-    Scanner scanner = new Scanner(
-        null,
-        new CharSequenceReader("/* comment */ "),
-        AnalysisErrorListener.NULL_LISTENER);
-    scanner.preserveComments = false;
-    Token token = scanner.tokenize();
-    expect(token, isNotNull);
-    expect(token.precedingComments, isNull);
-  }
-
-  void test_comment_generic_method_type_assign() {
-    _assertComment(TokenType.MULTI_LINE_COMMENT, "/*=comment*/");
-    _assertComment(TokenType.GENERIC_METHOD_TYPE_ASSIGN, "/*=comment*/",
-        genericMethodComments: true);
-  }
-
-  void test_comment_generic_method_type_list() {
-    _assertComment(TokenType.MULTI_LINE_COMMENT, "/*<comment>*/");
-    _assertComment(TokenType.GENERIC_METHOD_TYPE_LIST, "/*<comment>*/",
-        genericMethodComments: true);
-  }
-
-  void test_comment_multi() {
-    _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");
-  }
-
-  void test_comment_nested() {
-    _assertComment(
-        TokenType.MULTI_LINE_COMMENT, "/* comment /* within a */ comment */");
-  }
-
-  void test_comment_single() {
-    _assertComment(TokenType.SINGLE_LINE_COMMENT, "// comment");
-  }
-
-  void test_double_both_E() {
-    _assertToken(TokenType.DOUBLE, "0.123E4");
-  }
-
-  void test_double_both_e() {
-    _assertToken(TokenType.DOUBLE, "0.123e4");
-  }
-
-  void test_double_fraction() {
-    _assertToken(TokenType.DOUBLE, ".123");
-  }
-
-  void test_double_fraction_E() {
-    _assertToken(TokenType.DOUBLE, ".123E4");
-  }
-
-  void test_double_fraction_e() {
-    _assertToken(TokenType.DOUBLE, ".123e4");
-  }
-
-  void test_double_missingDigitInExponent() {
-    _assertError(ScannerErrorCode.MISSING_DIGIT, 1, "1e");
-  }
-
-  void test_double_whole_E() {
-    _assertToken(TokenType.DOUBLE, "12E4");
-  }
-
-  void test_double_whole_e() {
-    _assertToken(TokenType.DOUBLE, "12e4");
-  }
-
-  void test_eq() {
-    _assertToken(TokenType.EQ, "=");
-  }
-
-  void test_eq_eq() {
-    _assertToken(TokenType.EQ_EQ, "==");
-  }
-
-  void test_gt() {
-    _assertToken(TokenType.GT, ">");
-  }
-
-  void test_gt_eq() {
-    _assertToken(TokenType.GT_EQ, ">=");
-  }
-
-  void test_gt_gt() {
-    _assertToken(TokenType.GT_GT, ">>");
-  }
-
-  void test_gt_gt_eq() {
-    _assertToken(TokenType.GT_GT_EQ, ">>=");
-  }
-
-  void test_hash() {
-    _assertToken(TokenType.HASH, "#");
-  }
-
-  void test_hexidecimal() {
-    _assertToken(TokenType.HEXADECIMAL, "0x1A2B3C");
-  }
-
-  void test_hexidecimal_missingDigit() {
-    _assertError(ScannerErrorCode.MISSING_HEX_DIGIT, 1, "0x");
-  }
-
-  void test_identifier() {
-    _assertToken(TokenType.IDENTIFIER, "result");
-  }
-
-  void test_illegalChar_cyrillicLetter_middle() {
-    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 5, "Shche\u0433lov");
-  }
-
-  void test_illegalChar_cyrillicLetter_start() {
-    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u0429");
-  }
-
-  void test_illegalChar_nbsp() {
-    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u00A0");
-  }
-
-  void test_illegalChar_notLetter() {
-    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u0312");
-  }
-
-  void test_index() {
-    _assertToken(TokenType.INDEX, "[]");
-  }
-
-  void test_index_eq() {
-    _assertToken(TokenType.INDEX_EQ, "[]=");
-  }
-
-  void test_int() {
-    _assertToken(TokenType.INT, "123");
-  }
-
-  void test_int_initialZero() {
-    _assertToken(TokenType.INT, "0123");
-  }
-
-  void test_keyword_abstract() {
-    _assertKeywordToken("abstract");
-  }
-
-  void test_keyword_as() {
-    _assertKeywordToken("as");
-  }
-
-  void test_keyword_assert() {
-    _assertKeywordToken("assert");
-  }
-
-  void test_keyword_break() {
-    _assertKeywordToken("break");
-  }
-
-  void test_keyword_case() {
-    _assertKeywordToken("case");
-  }
-
-  void test_keyword_catch() {
-    _assertKeywordToken("catch");
-  }
-
-  void test_keyword_class() {
-    _assertKeywordToken("class");
-  }
-
-  void test_keyword_const() {
-    _assertKeywordToken("const");
-  }
-
-  void test_keyword_continue() {
-    _assertKeywordToken("continue");
-  }
-
-  void test_keyword_default() {
-    _assertKeywordToken("default");
-  }
-
-  void test_keyword_deferred() {
-    _assertKeywordToken("deferred");
-  }
-
-  void test_keyword_do() {
-    _assertKeywordToken("do");
-  }
-
-  void test_keyword_dynamic() {
-    _assertKeywordToken("dynamic");
-  }
-
-  void test_keyword_else() {
-    _assertKeywordToken("else");
-  }
-
-  void test_keyword_enum() {
-    _assertKeywordToken("enum");
-  }
-
-  void test_keyword_export() {
-    _assertKeywordToken("export");
-  }
-
-  void test_keyword_extends() {
-    _assertKeywordToken("extends");
-  }
-
-  void test_keyword_factory() {
-    _assertKeywordToken("factory");
-  }
-
-  void test_keyword_false() {
-    _assertKeywordToken("false");
-  }
-
-  void test_keyword_final() {
-    _assertKeywordToken("final");
-  }
-
-  void test_keyword_finally() {
-    _assertKeywordToken("finally");
-  }
-
-  void test_keyword_for() {
-    _assertKeywordToken("for");
-  }
-
-  void test_keyword_get() {
-    _assertKeywordToken("get");
-  }
-
-  void test_keyword_if() {
-    _assertKeywordToken("if");
-  }
-
-  void test_keyword_implements() {
-    _assertKeywordToken("implements");
-  }
-
-  void test_keyword_import() {
-    _assertKeywordToken("import");
-  }
-
-  void test_keyword_in() {
-    _assertKeywordToken("in");
-  }
-
-  void test_keyword_is() {
-    _assertKeywordToken("is");
-  }
-
-  void test_keyword_library() {
-    _assertKeywordToken("library");
-  }
-
-  void test_keyword_new() {
-    _assertKeywordToken("new");
-  }
-
-  void test_keyword_null() {
-    _assertKeywordToken("null");
-  }
-
-  void test_keyword_operator() {
-    _assertKeywordToken("operator");
-  }
-
-  void test_keyword_part() {
-    _assertKeywordToken("part");
-  }
-
-  void test_keyword_rethrow() {
-    _assertKeywordToken("rethrow");
-  }
-
-  void test_keyword_return() {
-    _assertKeywordToken("return");
-  }
-
-  void test_keyword_set() {
-    _assertKeywordToken("set");
-  }
-
-  void test_keyword_static() {
-    _assertKeywordToken("static");
-  }
-
-  void test_keyword_super() {
-    _assertKeywordToken("super");
-  }
-
-  void test_keyword_switch() {
-    _assertKeywordToken("switch");
-  }
-
-  void test_keyword_this() {
-    _assertKeywordToken("this");
-  }
-
-  void test_keyword_throw() {
-    _assertKeywordToken("throw");
-  }
-
-  void test_keyword_true() {
-    _assertKeywordToken("true");
-  }
-
-  void test_keyword_try() {
-    _assertKeywordToken("try");
-  }
-
-  void test_keyword_typedef() {
-    _assertKeywordToken("typedef");
-  }
-
-  void test_keyword_var() {
-    _assertKeywordToken("var");
-  }
-
-  void test_keyword_void() {
-    _assertKeywordToken("void");
-  }
-
-  void test_keyword_while() {
-    _assertKeywordToken("while");
-  }
-
-  void test_keyword_with() {
-    _assertKeywordToken("with");
-  }
-
+class LineInfoTest extends EngineTestCase {
   void test_lineInfo_multilineComment() {
     String source = "/*\r *\r */";
     _assertLineInfo(source, [
@@ -668,503 +123,6 @@
     ]);
   }
 
-  void test_lt() {
-    _assertToken(TokenType.LT, "<");
-  }
-
-  void test_lt_eq() {
-    _assertToken(TokenType.LT_EQ, "<=");
-  }
-
-  void test_lt_lt() {
-    _assertToken(TokenType.LT_LT, "<<");
-  }
-
-  void test_lt_lt_eq() {
-    _assertToken(TokenType.LT_LT_EQ, "<<=");
-  }
-
-  void test_minus() {
-    _assertToken(TokenType.MINUS, "-");
-  }
-
-  void test_minus_eq() {
-    _assertToken(TokenType.MINUS_EQ, "-=");
-  }
-
-  void test_minus_minus() {
-    _assertToken(TokenType.MINUS_MINUS, "--");
-  }
-
-  void test_open_curly_bracket() {
-    _assertToken(TokenType.OPEN_CURLY_BRACKET, "{");
-  }
-
-  void test_open_paren() {
-    _assertToken(TokenType.OPEN_PAREN, "(");
-  }
-
-  void test_open_square_bracket() {
-    _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
-  }
-
-  void test_openSquareBracket() {
-    _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
-  }
-
-  void test_percent() {
-    _assertToken(TokenType.PERCENT, "%");
-  }
-
-  void test_percent_eq() {
-    _assertToken(TokenType.PERCENT_EQ, "%=");
-  }
-
-  void test_period() {
-    _assertToken(TokenType.PERIOD, ".");
-  }
-
-  void test_period_period() {
-    _assertToken(TokenType.PERIOD_PERIOD, "..");
-  }
-
-  void test_period_period_period() {
-    _assertToken(TokenType.PERIOD_PERIOD_PERIOD, "...");
-  }
-
-  void test_periodAfterNumberNotIncluded_identifier() {
-    _assertTokens("42.isEven()", [
-      new StringToken(TokenType.INT, "42", 0),
-      new Token(TokenType.PERIOD, 2),
-      new StringToken(TokenType.IDENTIFIER, "isEven", 3),
-      new Token(TokenType.OPEN_PAREN, 9),
-      new Token(TokenType.CLOSE_PAREN, 10)
-    ]);
-  }
-
-  void test_periodAfterNumberNotIncluded_period() {
-    _assertTokens("42..isEven()", [
-      new StringToken(TokenType.INT, "42", 0),
-      new Token(TokenType.PERIOD_PERIOD, 2),
-      new StringToken(TokenType.IDENTIFIER, "isEven", 4),
-      new Token(TokenType.OPEN_PAREN, 10),
-      new Token(TokenType.CLOSE_PAREN, 11)
-    ]);
-  }
-
-  void test_plus() {
-    _assertToken(TokenType.PLUS, "+");
-  }
-
-  void test_plus_eq() {
-    _assertToken(TokenType.PLUS_EQ, "+=");
-  }
-
-  void test_plus_plus() {
-    _assertToken(TokenType.PLUS_PLUS, "++");
-  }
-
-  void test_question() {
-    _assertToken(TokenType.QUESTION, "?");
-  }
-
-  void test_question_dot() {
-    _assertToken(TokenType.QUESTION_PERIOD, "?.");
-  }
-
-  void test_question_question() {
-    _assertToken(TokenType.QUESTION_QUESTION, "??");
-  }
-
-  void test_question_question_eq() {
-    _assertToken(TokenType.QUESTION_QUESTION_EQ, "??=");
-  }
-
-  void test_scriptTag_withArgs() {
-    _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart -debug");
-  }
-
-  void test_scriptTag_withoutSpace() {
-    _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart");
-  }
-
-  void test_scriptTag_withSpace() {
-    _assertToken(TokenType.SCRIPT_TAG, "#! /bin/dart");
-  }
-
-  void test_semicolon() {
-    _assertToken(TokenType.SEMICOLON, ";");
-  }
-
-  void test_setSourceStart() {
-    int offsetDelta = 42;
-    GatheringErrorListener listener = new GatheringErrorListener();
-    Scanner scanner =
-        new Scanner(null, new SubSequenceReader("a", offsetDelta), listener);
-    scanner.setSourceStart(3, 9);
-    scanner.tokenize();
-    List<int> lineStarts = scanner.lineStarts;
-    expect(lineStarts, isNotNull);
-    expect(lineStarts.length, 3);
-    expect(lineStarts[2], 33);
-  }
-
-  void test_slash() {
-    _assertToken(TokenType.SLASH, "/");
-  }
-
-  void test_slash_eq() {
-    _assertToken(TokenType.SLASH_EQ, "/=");
-  }
-
-  void test_star() {
-    _assertToken(TokenType.STAR, "*");
-  }
-
-  void test_star_eq() {
-    _assertToken(TokenType.STAR_EQ, "*=");
-  }
-
-  void test_startAndEnd() {
-    Token token = _scan("a");
-    Token previous = token.previous;
-    expect(previous.next, token);
-    expect(previous.previous, previous);
-    Token next = token.next;
-    expect(next.next, next);
-    expect(next.previous, token);
-  }
-
-  void test_string_multi_double() {
-    _assertToken(TokenType.STRING, "\"\"\"line1\nline2\"\"\"");
-  }
-
-  void test_string_multi_embeddedQuotes() {
-    _assertToken(TokenType.STRING, "\"\"\"line1\n\"\"\nline2\"\"\"");
-  }
-
-  void test_string_multi_embeddedQuotes_escapedChar() {
-    _assertToken(TokenType.STRING, "\"\"\"a\"\"\\tb\"\"\"");
-  }
-
-  void test_string_multi_interpolation_block() {
-    _assertTokens("\"Hello \${name}!\"", [
-      new StringToken(TokenType.STRING, "\"Hello ", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 7),
-      new StringToken(TokenType.IDENTIFIER, "name", 9),
-      new Token(TokenType.CLOSE_CURLY_BRACKET, 13),
-      new StringToken(TokenType.STRING, "!\"", 14)
-    ]);
-  }
-
-  void test_string_multi_interpolation_identifier() {
-    _assertTokens("\"Hello \$name!\"", [
-      new StringToken(TokenType.STRING, "\"Hello ", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 7),
-      new StringToken(TokenType.IDENTIFIER, "name", 8),
-      new StringToken(TokenType.STRING, "!\"", 12)
-    ]);
-  }
-
-  void test_string_multi_single() {
-    _assertToken(TokenType.STRING, "'''string'''");
-  }
-
-  void test_string_multi_slashEnter() {
-    _assertToken(TokenType.STRING, "'''\\\n'''");
-  }
-
-  void test_string_multi_unterminated() {
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8,
-        "'''string", [new StringToken(TokenType.STRING, "'''string", 0)]);
-  }
-
-  void test_string_multi_unterminated_interpolation_block() {
-    _assertErrorAndTokens(
-        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8, "'''\${name", [
-      new StringToken(TokenType.STRING, "'''", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 3),
-      new StringToken(TokenType.IDENTIFIER, "name", 5),
-      new StringToken(TokenType.STRING, "", 9)
-    ]);
-  }
-
-  void test_string_multi_unterminated_interpolation_identifier() {
-    _assertErrorAndTokens(
-        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7, "'''\$name", [
-      new StringToken(TokenType.STRING, "'''", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
-      new StringToken(TokenType.IDENTIFIER, "name", 4),
-      new StringToken(TokenType.STRING, "", 8)
-    ]);
-  }
-
-  void test_string_raw_multi_double() {
-    _assertToken(TokenType.STRING, "r\"\"\"line1\nline2\"\"\"");
-  }
-
-  void test_string_raw_multi_single() {
-    _assertToken(TokenType.STRING, "r'''string'''");
-  }
-
-  void test_string_raw_multi_unterminated() {
-    String source = "r'''string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9,
-        source, [new StringToken(TokenType.STRING, source, 0)]);
-  }
-
-  void test_string_raw_simple_double() {
-    _assertToken(TokenType.STRING, "r\"string\"");
-  }
-
-  void test_string_raw_simple_single() {
-    _assertToken(TokenType.STRING, "r'string'");
-  }
-
-  void test_string_raw_simple_unterminated_eof() {
-    String source = "r'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7,
-        source, [new StringToken(TokenType.STRING, source, 0)]);
-  }
-
-  void test_string_raw_simple_unterminated_eol() {
-    String source = "r'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8,
-        "$source\n", [new StringToken(TokenType.STRING, source, 0)]);
-  }
-
-  void test_string_simple_double() {
-    _assertToken(TokenType.STRING, "\"string\"");
-  }
-
-  void test_string_simple_escapedDollar() {
-    _assertToken(TokenType.STRING, "'a\\\$b'");
-  }
-
-  void test_string_simple_interpolation_adjacentIdentifiers() {
-    _assertTokens("'\$a\$b'", [
-      new StringToken(TokenType.STRING, "'", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
-      new StringToken(TokenType.IDENTIFIER, "a", 2),
-      new StringToken(TokenType.STRING, "", 3),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
-      new StringToken(TokenType.IDENTIFIER, "b", 4),
-      new StringToken(TokenType.STRING, "'", 5)
-    ]);
-  }
-
-  void test_string_simple_interpolation_block() {
-    _assertTokens("'Hello \${name}!'", [
-      new StringToken(TokenType.STRING, "'Hello ", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 7),
-      new StringToken(TokenType.IDENTIFIER, "name", 9),
-      new Token(TokenType.CLOSE_CURLY_BRACKET, 13),
-      new StringToken(TokenType.STRING, "!'", 14)
-    ]);
-  }
-
-  void test_string_simple_interpolation_blockWithNestedMap() {
-    _assertTokens("'a \${f({'b' : 'c'})} d'", [
-      new StringToken(TokenType.STRING, "'a ", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 3),
-      new StringToken(TokenType.IDENTIFIER, "f", 5),
-      new Token(TokenType.OPEN_PAREN, 6),
-      new Token(TokenType.OPEN_CURLY_BRACKET, 7),
-      new StringToken(TokenType.STRING, "'b'", 8),
-      new Token(TokenType.COLON, 12),
-      new StringToken(TokenType.STRING, "'c'", 14),
-      new Token(TokenType.CLOSE_CURLY_BRACKET, 17),
-      new Token(TokenType.CLOSE_PAREN, 18),
-      new Token(TokenType.CLOSE_CURLY_BRACKET, 19),
-      new StringToken(TokenType.STRING, " d'", 20)
-    ]);
-  }
-
-  void test_string_simple_interpolation_firstAndLast() {
-    _assertTokens("'\$greeting \$name'", [
-      new StringToken(TokenType.STRING, "'", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
-      new StringToken(TokenType.IDENTIFIER, "greeting", 2),
-      new StringToken(TokenType.STRING, " ", 10),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 11),
-      new StringToken(TokenType.IDENTIFIER, "name", 12),
-      new StringToken(TokenType.STRING, "'", 16)
-    ]);
-  }
-
-  void test_string_simple_interpolation_identifier() {
-    _assertTokens("'Hello \$name!'", [
-      new StringToken(TokenType.STRING, "'Hello ", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 7),
-      new StringToken(TokenType.IDENTIFIER, "name", 8),
-      new StringToken(TokenType.STRING, "!'", 12)
-    ]);
-  }
-
-  void test_string_simple_interpolation_missingIdentifier() {
-    _assertTokens("'\$x\$'", [
-      new StringToken(TokenType.STRING, "'", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
-      new StringToken(TokenType.IDENTIFIER, "x", 2),
-      new StringToken(TokenType.STRING, "", 3),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
-      new StringToken(TokenType.STRING, "'", 4)
-    ]);
-  }
-
-  void test_string_simple_interpolation_nonIdentifier() {
-    _assertTokens("'\$1'", [
-      new StringToken(TokenType.STRING, "'", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
-      new StringToken(TokenType.STRING, "1'", 2)
-    ]);
-  }
-
-  void test_string_simple_single() {
-    _assertToken(TokenType.STRING, "'string'");
-  }
-
-  void test_string_simple_unterminated_eof() {
-    String source = "'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 6,
-        source, [new StringToken(TokenType.STRING, source, 0)]);
-  }
-
-  void test_string_simple_unterminated_eol() {
-    String source = "'string";
-    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7,
-        "$source\r", [new StringToken(TokenType.STRING, source, 0)]);
-  }
-
-  void test_string_simple_unterminated_interpolation_block() {
-    _assertErrorAndTokens(
-        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 6, "'\${name", [
-      new StringToken(TokenType.STRING, "'", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 1),
-      new StringToken(TokenType.IDENTIFIER, "name", 3),
-      new StringToken(TokenType.STRING, "", 7)
-    ]);
-  }
-
-  void test_string_simple_unterminated_interpolation_identifier() {
-    _assertErrorAndTokens(
-        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 5, "'\$name", [
-      new StringToken(TokenType.STRING, "'", 0),
-      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
-      new StringToken(TokenType.IDENTIFIER, "name", 2),
-      new StringToken(TokenType.STRING, "", 6)
-    ]);
-  }
-
-  void test_tilde() {
-    _assertToken(TokenType.TILDE, "~");
-  }
-
-  void test_tilde_slash() {
-    _assertToken(TokenType.TILDE_SLASH, "~/");
-  }
-
-  void test_tilde_slash_eq() {
-    _assertToken(TokenType.TILDE_SLASH_EQ, "~/=");
-  }
-
-  void test_unclosedPairInInterpolation() {
-    GatheringErrorListener listener = new GatheringErrorListener();
-    _scanWithListener("'\${(}'", listener);
-  }
-
-  void _assertComment(TokenType commentType, String source,
-      {bool genericMethodComments: false}) {
-    //
-    // Test without a trailing end-of-line marker
-    //
-    Token token = _scan(source, genericMethodComments: genericMethodComments);
-    expect(token, isNotNull);
-    expect(token.type, TokenType.EOF);
-    Token comment = token.precedingComments;
-    expect(comment, isNotNull);
-    expect(comment.type, commentType);
-    expect(comment.offset, 0);
-    expect(comment.length, source.length);
-    expect(comment.lexeme, source);
-    //
-    // Test with a trailing end-of-line marker
-    //
-    token = _scan("$source\n", genericMethodComments: genericMethodComments);
-    expect(token, isNotNull);
-    expect(token.type, TokenType.EOF);
-    comment = token.precedingComments;
-    expect(comment, isNotNull);
-    expect(comment.type, commentType);
-    expect(comment.offset, 0);
-    expect(comment.length, source.length);
-    expect(comment.lexeme, source);
-  }
-
-  /**
-   * Assert that scanning the given [source] produces an error with the given
-   * code.
-   *
-   * [expectedError] the error that should be produced
-   * [expectedOffset] the string offset that should be associated with the error
-   * [source] the source to be scanned to produce the error
-   */
-  void _assertError(
-      ScannerErrorCode expectedError, int expectedOffset, String source) {
-    GatheringErrorListener listener = new GatheringErrorListener();
-    _scanWithListener(source, listener);
-    listener.assertErrors([
-      new AnalysisError(null, expectedOffset, 1, expectedError,
-          [source.codeUnitAt(expectedOffset)])
-    ]);
-  }
-
-  /**
-   * Assert that scanning the given [source] produces an error with the given
-   * code, and also produces the given tokens.
-   *
-   * [expectedError] the error that should be produced
-   * [expectedOffset] the string offset that should be associated with the error
-   * [source] the source to be scanned to produce the error
-   * [expectedTokens] the tokens that are expected to be in the source
-   */
-  void _assertErrorAndTokens(ScannerErrorCode expectedError, int expectedOffset,
-      String source, List<Token> expectedTokens) {
-    GatheringErrorListener listener = new GatheringErrorListener();
-    Token token = _scanWithListener(source, listener);
-    listener.assertErrors([
-      new AnalysisError(null, expectedOffset, 1, expectedError,
-          [source.codeUnitAt(expectedOffset)])
-    ]);
-    _checkTokens(token, expectedTokens);
-  }
-
-  /**
-   * Assert that when scanned the given [source] contains a single keyword token
-   * with the same lexeme as the original source.
-   */
-  void _assertKeywordToken(String source) {
-    Token token = _scan(source);
-    expect(token, isNotNull);
-    expect(token.type, TokenType.KEYWORD);
-    expect(token.offset, 0);
-    expect(token.length, source.length);
-    expect(token.lexeme, source);
-    Object value = token.value();
-    expect(value is Keyword, isTrue);
-    expect((value as Keyword).syntax, source);
-    token = _scan(" $source ");
-    expect(token, isNotNull);
-    expect(token.type, TokenType.KEYWORD);
-    expect(token.offset, 1);
-    expect(token.length, source.length);
-    expect(token.lexeme, source);
-    value = token.value();
-    expect(value is Keyword, isTrue);
-    expect((value as Keyword).syntax, source);
-    expect(token.next.type, TokenType.EOF);
-  }
-
   void _assertLineInfo(
       String source, List<ScannerTest_ExpectedLocation> expectedLocations) {
     GatheringErrorListener listener = new GatheringErrorListener();
@@ -1183,99 +141,6 @@
     }
   }
 
-  /**
-   * Assert that the token scanned from the given [source] has the
-   * [expectedType].
-   */
-  Token _assertToken(TokenType expectedType, String source,
-      {bool lazyAssignmentOperators: false}) {
-    Token originalToken =
-        _scan(source, lazyAssignmentOperators: lazyAssignmentOperators);
-    expect(originalToken, isNotNull);
-    expect(originalToken.type, expectedType);
-    expect(originalToken.offset, 0);
-    expect(originalToken.length, source.length);
-    expect(originalToken.lexeme, source);
-    if (expectedType == TokenType.SCRIPT_TAG) {
-      // Adding space before the script tag is not allowed, and adding text at
-      // the end changes nothing.
-      return originalToken;
-    } else if (expectedType == TokenType.SINGLE_LINE_COMMENT) {
-      // Adding space to an end-of-line comment changes the comment.
-      Token tokenWithSpaces =
-          _scan(" $source", lazyAssignmentOperators: lazyAssignmentOperators);
-      expect(tokenWithSpaces, isNotNull);
-      expect(tokenWithSpaces.type, expectedType);
-      expect(tokenWithSpaces.offset, 1);
-      expect(tokenWithSpaces.length, source.length);
-      expect(tokenWithSpaces.lexeme, source);
-      return originalToken;
-    } else if (expectedType == TokenType.INT ||
-        expectedType == TokenType.DOUBLE) {
-      Token tokenWithLowerD =
-          _scan("${source}d", lazyAssignmentOperators: lazyAssignmentOperators);
-      expect(tokenWithLowerD, isNotNull);
-      expect(tokenWithLowerD.type, expectedType);
-      expect(tokenWithLowerD.offset, 0);
-      expect(tokenWithLowerD.length, source.length);
-      expect(tokenWithLowerD.lexeme, source);
-      Token tokenWithUpperD =
-          _scan("${source}D", lazyAssignmentOperators: lazyAssignmentOperators);
-      expect(tokenWithUpperD, isNotNull);
-      expect(tokenWithUpperD.type, expectedType);
-      expect(tokenWithUpperD.offset, 0);
-      expect(tokenWithUpperD.length, source.length);
-      expect(tokenWithUpperD.lexeme, source);
-    }
-    Token tokenWithSpaces =
-        _scan(" $source ", lazyAssignmentOperators: lazyAssignmentOperators);
-    expect(tokenWithSpaces, isNotNull);
-    expect(tokenWithSpaces.type, expectedType);
-    expect(tokenWithSpaces.offset, 1);
-    expect(tokenWithSpaces.length, source.length);
-    expect(tokenWithSpaces.lexeme, source);
-    expect(originalToken.next.type, TokenType.EOF);
-    return originalToken;
-  }
-
-  /**
-   * Assert that when scanned the given [source] contains a sequence of tokens
-   * identical to the given list of [expectedTokens].
-   */
-  void _assertTokens(String source, List<Token> expectedTokens) {
-    Token token = _scan(source);
-    _checkTokens(token, expectedTokens);
-  }
-
-  void _checkTokens(Token firstToken, List<Token> expectedTokens) {
-    expect(firstToken, isNotNull);
-    Token token = firstToken;
-    for (int i = 0; i < expectedTokens.length; i++) {
-      Token expectedToken = expectedTokens[i];
-      expect(token.type, expectedToken.type, reason: "Wrong type for token $i");
-      expect(token.offset, expectedToken.offset,
-          reason: "Wrong offset for token $i");
-      expect(token.length, expectedToken.length,
-          reason: "Wrong length for token $i");
-      expect(token.lexeme, expectedToken.lexeme,
-          reason: "Wrong lexeme for token $i");
-      token = token.next;
-      expect(token, isNotNull);
-    }
-    expect(token.type, TokenType.EOF);
-  }
-
-  Token _scan(String source,
-      {bool genericMethodComments: false,
-      bool lazyAssignmentOperators: false}) {
-    GatheringErrorListener listener = new GatheringErrorListener();
-    Token token = _scanWithListener(source, listener,
-        genericMethodComments: genericMethodComments,
-        lazyAssignmentOperators: lazyAssignmentOperators);
-    listener.assertNoErrors();
-    return token;
-  }
-
   Token _scanWithListener(String source, GatheringErrorListener listener,
       {bool genericMethodComments: false,
       bool lazyAssignmentOperators: false}) {
@@ -1369,71 +234,3 @@
     buffer.write("]");
   }
 }
-
-@reflectiveTest
-class TokenTypeTest extends EngineTestCase {
-  void test_isOperator() {
-    expect(TokenType.AMPERSAND.isOperator, isTrue);
-    expect(TokenType.AMPERSAND_AMPERSAND.isOperator, isTrue);
-    expect(TokenType.AMPERSAND_EQ.isOperator, isTrue);
-    expect(TokenType.BANG.isOperator, isTrue);
-    expect(TokenType.BANG_EQ.isOperator, isTrue);
-    expect(TokenType.BAR.isOperator, isTrue);
-    expect(TokenType.BAR_BAR.isOperator, isTrue);
-    expect(TokenType.BAR_EQ.isOperator, isTrue);
-    expect(TokenType.CARET.isOperator, isTrue);
-    expect(TokenType.CARET_EQ.isOperator, isTrue);
-    expect(TokenType.EQ.isOperator, isTrue);
-    expect(TokenType.EQ_EQ.isOperator, isTrue);
-    expect(TokenType.GT.isOperator, isTrue);
-    expect(TokenType.GT_EQ.isOperator, isTrue);
-    expect(TokenType.GT_GT.isOperator, isTrue);
-    expect(TokenType.GT_GT_EQ.isOperator, isTrue);
-    expect(TokenType.INDEX.isOperator, isTrue);
-    expect(TokenType.INDEX_EQ.isOperator, isTrue);
-    expect(TokenType.IS.isOperator, isTrue);
-    expect(TokenType.LT.isOperator, isTrue);
-    expect(TokenType.LT_EQ.isOperator, isTrue);
-    expect(TokenType.LT_LT.isOperator, isTrue);
-    expect(TokenType.LT_LT_EQ.isOperator, isTrue);
-    expect(TokenType.MINUS.isOperator, isTrue);
-    expect(TokenType.MINUS_EQ.isOperator, isTrue);
-    expect(TokenType.MINUS_MINUS.isOperator, isTrue);
-    expect(TokenType.PERCENT.isOperator, isTrue);
-    expect(TokenType.PERCENT_EQ.isOperator, isTrue);
-    expect(TokenType.PERIOD_PERIOD.isOperator, isTrue);
-    expect(TokenType.PLUS.isOperator, isTrue);
-    expect(TokenType.PLUS_EQ.isOperator, isTrue);
-    expect(TokenType.PLUS_PLUS.isOperator, isTrue);
-    expect(TokenType.QUESTION.isOperator, isTrue);
-    expect(TokenType.SLASH.isOperator, isTrue);
-    expect(TokenType.SLASH_EQ.isOperator, isTrue);
-    expect(TokenType.STAR.isOperator, isTrue);
-    expect(TokenType.STAR_EQ.isOperator, isTrue);
-    expect(TokenType.TILDE.isOperator, isTrue);
-    expect(TokenType.TILDE_SLASH.isOperator, isTrue);
-    expect(TokenType.TILDE_SLASH_EQ.isOperator, isTrue);
-  }
-
-  void test_isUserDefinableOperator() {
-    expect(TokenType.AMPERSAND.isUserDefinableOperator, isTrue);
-    expect(TokenType.BAR.isUserDefinableOperator, isTrue);
-    expect(TokenType.CARET.isUserDefinableOperator, isTrue);
-    expect(TokenType.EQ_EQ.isUserDefinableOperator, isTrue);
-    expect(TokenType.GT.isUserDefinableOperator, isTrue);
-    expect(TokenType.GT_EQ.isUserDefinableOperator, isTrue);
-    expect(TokenType.GT_GT.isUserDefinableOperator, isTrue);
-    expect(TokenType.INDEX.isUserDefinableOperator, isTrue);
-    expect(TokenType.INDEX_EQ.isUserDefinableOperator, isTrue);
-    expect(TokenType.LT.isUserDefinableOperator, isTrue);
-    expect(TokenType.LT_EQ.isUserDefinableOperator, isTrue);
-    expect(TokenType.LT_LT.isUserDefinableOperator, isTrue);
-    expect(TokenType.MINUS.isUserDefinableOperator, isTrue);
-    expect(TokenType.PERCENT.isUserDefinableOperator, isTrue);
-    expect(TokenType.PLUS.isUserDefinableOperator, isTrue);
-    expect(TokenType.SLASH.isUserDefinableOperator, isTrue);
-    expect(TokenType.STAR.isUserDefinableOperator, isTrue);
-    expect(TokenType.TILDE.isUserDefinableOperator, isTrue);
-    expect(TokenType.TILDE_SLASH.isUserDefinableOperator, isTrue);
-  }
-}
diff --git a/pkg/analyzer/test/source/analysis_options_provider_test.dart b/pkg/analyzer/test/source/analysis_options_provider_test.dart
index 5ea408a..8ada91c 100644
--- a/pkg/analyzer/test/source/analysis_options_provider_test.dart
+++ b/pkg/analyzer/test/source/analysis_options_provider_test.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:yaml/yaml.dart';
@@ -115,7 +116,7 @@
   TestPathTranslator pathTranslator;
   ResourceProvider resourceProvider;
 
-  AnalysisOptionsProvider provider = new AnalysisOptionsProvider();
+  AnalysisOptionsProvider provider;
 
   String get optionsFileName;
 
@@ -123,6 +124,9 @@
     var rawProvider = new MemoryResourceProvider();
     resourceProvider = new TestResourceProvider(rawProvider);
     pathTranslator = new TestPathTranslator(rawProvider);
+    provider = new AnalysisOptionsProvider(new SourceFactory([
+      new ResourceUriResolver(rawProvider),
+    ]));
   }
 
   void test_getOptions_crawlUp_hasInFolder() {
@@ -188,6 +192,44 @@
     expect(options, isEmpty);
   }
 
+  void test_getOptions_include() {
+    pathTranslator.newFile(
+        '/foo.include',
+        r'''
+analyzer:
+  ignore:
+    - ignoreme.dart
+    - 'sdk_ext/**'
+''');
+    pathTranslator.newFile(
+        '/$optionsFileName',
+        r'''
+include: foo.include
+''');
+    Map<String, YamlNode> options = _getOptions('/');
+    expect(options, hasLength(1));
+    {
+      YamlMap analyzer = options['analyzer'];
+      expect(analyzer, hasLength(1));
+      {
+        YamlList ignore = analyzer['ignore'];
+        expect(ignore, hasLength(2));
+        expect(ignore[0], 'ignoreme.dart');
+        expect(ignore[1], 'sdk_ext/**');
+      }
+    }
+  }
+
+  void test_getOptions_include_missing() {
+    pathTranslator.newFile(
+        '/$optionsFileName',
+        r'''
+include: /foo.include
+''');
+    Map<String, YamlNode> options = _getOptions('/');
+    expect(options, hasLength(0));
+  }
+
   void test_getOptions_invalid() {
     pathTranslator.newFile('/$optionsFileName', r''':''');
     expect(() {
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index b05daa5..0c47bd0 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -555,6 +555,63 @@
     }
   }
 
+  void test_getAnalysisOptions_includes() {
+    AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl();
+    defaultOptions.enableGenericMethods = true;
+    builderOptions.defaultOptions = defaultOptions;
+    AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
+    expected.enableSuperMixins = true;
+    expected.enableGenericMethods = true;
+    resourceProvider.newFile(
+        resourceProvider.convertPath('/mypkgs/somepkg/lib/here.yaml'),
+        '''
+two: {boo: newt}
+''');
+    String path = resourceProvider.convertPath('/some/directory/path');
+    resourceProvider.newFile(
+        pathContext.join(path, '.packages'),
+        '''
+somepkg:../../../mypkgs/somepkg/lib
+''');
+    resourceProvider.newFile(
+        pathContext.join(path, 'bar.yaml'),
+        '''
+include: package:somepkg/here.yaml
+foo: {bar: baz}
+''');
+    String filePath =
+        pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
+    resourceProvider.newFile(
+        filePath,
+        '''
+include: bar.yaml
+analyzer:
+  language:
+    enableSuperMixins : true
+''');
+
+    AnalysisEngine engine = AnalysisEngine.instance;
+    OptionsPlugin plugin = engine.optionsPlugin;
+    plugin.registerExtensionPoints((_) {});
+    try {
+      _TestOptionsProcessor processor = new _TestOptionsProcessor();
+      processor.expectedOptions = <String, Object>{
+        'analyzer': {
+          'language': {'enableSuperMixins': true}
+        },
+        'foo': {'bar': 'baz'},
+        'two': {'boo': 'newt'},
+      };
+      (plugin.optionsProcessorExtensionPoint as ExtensionPointImpl)
+          .add(processor);
+      AnalysisContext context = engine.createAnalysisContext();
+      AnalysisOptions options = builder.getAnalysisOptions(context, path);
+      _expectEqualOptions(options, expected);
+    } finally {
+      plugin.registerExtensionPoints((_) {});
+    }
+  }
+
   void test_getAnalysisOptions_invalid() {
     String path = resourceProvider.convertPath('/some/directory/path');
     String filePath =
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 3b7d74d..ec693f4 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -602,6 +602,14 @@
     }
   }
 
+  test_getResult_notDartFile() async {
+    var path = _p('/test/lib/test.txt');
+    provider.newFile(path, 'foo bar');
+
+    AnalysisResult result = await driver.getResult(path);
+    expect(result, isNull);
+  }
+
   test_getResult_sameFile_twoUris() async {
     var a = _p('/test/lib/a.dart');
     var b = _p('/test/lib/b.dart');
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index 7147906..05c7a76 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -711,6 +711,43 @@
     expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
   }
 
+  test_classDelta_method_async_addStar() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  Stream test() async {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  Stream test() async* {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember oldNodeA = helper.oldMembers[0];
+    ClassMember newNodeA = helper.newMembers[0];
+    expect(newNodeA, isNot(same(oldNodeA)));
+    // elements
+    MethodElement oldElement = oldNodeA.element;
+    MethodElement newElement = newNodeA.element;
+    expect(newElement, isNotNull);
+    expect(newElement.name, 'test');
+    expect(oldElement.isAsynchronous, isTrue);
+    expect(oldElement.isGenerator, isFalse);
+    expect(newElement.isAsynchronous, isTrue);
+    expect(newElement.isGenerator, isTrue);
+    expect(helper.element.methods, [newElement]);
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, unorderedEquals([newElement]));
+    expect(helper.delta.removedMethods, unorderedEquals([oldElement]));
+  }
+
   test_classDelta_method_changeName() {
     var helper = new _ClassDeltaHelper('A');
     _buildOldUnit(r'''
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index f58ef31..b613093 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -33,7 +33,6 @@
 import '../universe/world_impact.dart'
     show ImpactStrategy, WorldImpact, WorldImpactBuilder;
 import 'codegen.dart' show CodegenWorkItem;
-import 'registry.dart' show Registry;
 import 'tasks.dart' show CompilerTask;
 
 abstract class Backend extends Target {
@@ -316,9 +315,6 @@
 
   void registerMainHasArguments(Enqueuer enqueuer) {}
 
-  void registerAsyncMarker(
-      FunctionElement element, Enqueuer enqueuer, Registry registry) {}
-
   /// Returns the location of the patch-file associated with [libraryName]
   /// resolved from [plaformConfigUri].
   ///
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 5214585..285e032 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -21,7 +21,6 @@
 import '../universe/world_impact.dart'
     show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
 import '../util/util.dart' show Pair, Setlet;
-import 'registry.dart' show Registry;
 import 'work.dart' show WorkItem;
 
 class CodegenImpact extends WorldImpact {
@@ -146,7 +145,7 @@
 
 // TODO(johnniwinther): Split this class into interface and implementation.
 // TODO(johnniwinther): Move this implementation to the JS backend.
-class CodegenRegistry extends Registry {
+class CodegenRegistry {
   final Compiler compiler;
   final Element currentElement;
   final _CodegenImpact worldImpact;
diff --git a/pkg/compiler/lib/src/common/registry.dart b/pkg/compiler/lib/src/common/registry.dart
deleted file mode 100644
index 08d6081..0000000
--- a/pkg/compiler/lib/src/common/registry.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.common.registry;
-
-import '../elements/elements.dart' show Element;
-
-// TODO(johnniwinther): Remove this.
-/// Interface for registration of element dependencies.
-abstract class Registry {
-  void registerDependency(Element element) {}
-}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index c2f91fe..ef0e751 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -13,7 +13,6 @@
 import 'common/codegen.dart' show CodegenWorkItem;
 import 'common/names.dart' show Selectors;
 import 'common/names.dart' show Identifiers, Uris;
-import 'common/registry.dart' show Registry;
 import 'common/resolution.dart'
     show
         ParsingContext,
@@ -850,10 +849,10 @@
 
   void processQueue(Enqueuer enqueuer, Element main) {
     selfTask.measureSubtask("Compiler.processQueue", () {
-      WorldImpactBuilderImpl nativeImpact = new WorldImpactBuilderImpl();
-      enqueuer.nativeEnqueuer
-          .processNativeClasses(nativeImpact, libraryLoader.libraries);
-      enqueuer.applyImpact(impactStrategy, nativeImpact);
+      enqueuer.applyImpact(
+          impactStrategy,
+          enqueuer.nativeEnqueuer
+              .processNativeClasses(libraryLoader.libraries));
       if (main != null && !main.isMalformed) {
         FunctionElement mainMethod = main;
         mainMethod.computeType(resolution);
@@ -2213,7 +2212,7 @@
   }
 }
 
-class GlobalDependencyRegistry extends Registry {
+class GlobalDependencyRegistry {
   Setlet<Element> _otherDependencies;
 
   GlobalDependencyRegistry();
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 06b58d9..178ba03 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -237,7 +237,7 @@
 
   /// `true` if this element is the body of a generative constructor.
   ///
-  /// This is a synthetic element kind used only be the JavaScript backend.
+  /// This is a synthetic element kind used only by the JavaScript backend.
   bool get isGenerativeConstructorBody;
 
   /// `true` if this element is a factory constructor,
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 66c3260..bb50941 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -10,7 +10,6 @@
 import 'common/backend_api.dart' show Backend;
 import 'common/names.dart' show Identifiers;
 import 'common/resolution.dart' show Resolution, ResolutionWorkItem;
-import 'common/registry.dart' show Registry;
 import 'common/tasks.dart' show CompilerTask;
 import 'common/work.dart' show WorkItem;
 import 'common.dart';
@@ -85,7 +84,6 @@
   void registerStaticUse(StaticUse staticUse);
   void registerStaticUseInternal(StaticUse staticUse);
   void registerDynamicUse(DynamicUse dynamicUse);
-  void registerTypeUse(TypeUse typeUse);
 
   /// Returns [:true:] if this enqueuer is the resolution enqueuer.
   bool get isResolutionQueue;
@@ -455,7 +453,7 @@
         break;
       case StaticUseKind.CONSTRUCTOR_INVOKE:
       case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
-        registerTypeUse(new TypeUse.instantiation(staticUse.type));
+        _registerTypeUse(new TypeUse.instantiation(staticUse.type));
         break;
       case StaticUseKind.DIRECT_INVOKE:
         invariant(
@@ -467,7 +465,7 @@
     }
   }
 
-  void registerTypeUse(TypeUse typeUse) {
+  void _registerTypeUse(TypeUse typeUse) {
     DartType type = typeUse.type;
     switch (typeUse.kind) {
       case TypeUseKind.INSTANTIATION:
@@ -743,7 +741,7 @@
 }
 
 class _EnqueuerImpactVisitor implements WorldImpactVisitor {
-  final Enqueuer enqueuer;
+  final ResolutionEnqueuer enqueuer;
 
   _EnqueuerImpactVisitor(this.enqueuer);
 
@@ -759,7 +757,7 @@
 
   @override
   void visitTypeUse(TypeUse typeUse) {
-    enqueuer.registerTypeUse(typeUse);
+    enqueuer._registerTypeUse(typeUse);
   }
 }
 
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index 4e96cd6..f6cdace 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -1473,8 +1473,9 @@
     isThisExposed = true;
     Selector selector = elements.getSelector(node);
     TypeMask mask = inTreeData.typeOfSend(node);
-    return handleStaticSend(
+    handleStaticSend(
         node, selector, mask, element, new ArgumentsTypes<T>([rhsType], null));
+    return rhsType;
   }
 
   @override
@@ -1684,13 +1685,13 @@
       return handleForeignSend(node, target);
     }
     Selector selector = elements.getSelector(node);
+    CallStructure callStructure = selector.callStructure;
     TypeMask mask = inTreeData.typeOfSend(node);
     // In erroneous code the number of arguments in the selector might not
     // match the function element.
     // TODO(polux): return nonNullEmpty and check it doesn't break anything
-    if (!selector.applies(target) ||
-        (mask != null &&
-            !mask.canHit(target, selector, compiler.closedWorld))) {
+    if (target.isMalformed ||
+        !callStructure.signatureApplies(target.functionSignature)) {
       return types.dynamicType;
     }
 
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 56e8e89..3aca346 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -19,7 +19,6 @@
         NativeRegistry;
 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
 import '../common/names.dart' show Identifiers, Selectors, Uris;
-import '../common/registry.dart' show Registry;
 import '../common/resolution.dart' show Frontend, Resolution, ResolutionImpact;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
@@ -1928,9 +1927,6 @@
     }
   }
 
-  /// Called when [:new Symbol(...):] is seen.
-  void registerNewSymbol(Registry registry) {}
-
   /// Should [element] (a getter) that would normally not be generated due to
   /// treeshaking be retained for reflection?
   bool shouldRetainGetter(Element element) {
@@ -2384,14 +2380,20 @@
     }
 
     if (isTreeShakingDisabled) {
-      mirrorsAnalysis.enqueueReflectiveElements(
-          enqueuer, recentClasses, compiler.libraryLoader.libraries);
+      enqueuer.applyImpact(
+          compiler.impactStrategy,
+          mirrorsAnalysis.computeImpactForReflectiveElements(recentClasses,
+              enqueuer.processedClasses, compiler.libraryLoader.libraries,
+              forResolution: enqueuer.isResolutionQueue));
     } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) {
       // Add all static elements (not classes) that have been requested for
       // reflection. If there is no mirror-usage these are probably not
       // necessary, but the backend relies on them being resolved.
-      mirrorsAnalysis.enqueueReflectiveStaticFields(
-          enqueuer, _findStaticFieldTargets());
+      enqueuer.applyImpact(
+          compiler.impactStrategy,
+          mirrorsAnalysis.computeImpactForReflectiveStaticFields(
+              _findStaticFieldTargets(),
+              forResolution: enqueuer.isResolutionQueue));
     }
 
     if (mustPreserveNames) reporter.log('Preserving names.');
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index c169537..179a65d 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -8,7 +8,6 @@
 
 import '../common/backend_api.dart' show Backend;
 import '../common/codegen.dart' show CodegenWorkItem;
-import '../common/registry.dart' show Registry;
 import '../common/names.dart' show Identifiers;
 import '../common/tasks.dart' show CompilerTask;
 import '../common/work.dart' show WorkItem;
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index c6e204d..fec60e3 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -8,7 +8,6 @@
 import 'package:pub_semver/pub_semver.dart';
 
 import '../common.dart';
-import '../common/registry.dart' show Registry;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart'
     show
diff --git a/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart b/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
index 930dba3..93344f6 100644
--- a/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
@@ -7,9 +7,9 @@
 import '../common/resolution.dart';
 import '../diagnostics/diagnostic_listener.dart';
 import '../elements/elements.dart';
-import '../enqueue.dart';
 import '../universe/selector.dart';
 import '../universe/use.dart';
+import '../universe/world_impact.dart';
 import 'backend.dart';
 
 class MirrorsAnalysis {
@@ -20,26 +20,26 @@
       : resolutionHandler = new MirrorsHandler(backend, resolution),
         codegenHandler = new MirrorsHandler(backend, resolution);
 
-  /// Enqueue all elements that are matched by the mirrors used
+  /// Compute the impact for elements that are matched by the mirrors used
   /// annotation or, in lack thereof, all elements.
-  // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
-  void enqueueReflectiveElements(
-      Enqueuer enqueuer,
+  WorldImpact computeImpactForReflectiveElements(
       Iterable<ClassElement> recents,
-      Iterable<LibraryElement> loadedLibraries) {
-    MirrorsHandler handler =
-        enqueuer.isResolutionQueue ? resolutionHandler : codegenHandler;
-    handler.enqueueReflectiveElements(enqueuer, recents, loadedLibraries);
+      Iterable<ClassElement> processedClasses,
+      Iterable<LibraryElement> loadedLibraries,
+      {bool forResolution}) {
+    MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
+    handler.enqueueReflectiveElements(
+        recents, processedClasses, loadedLibraries);
+    return handler.flush();
   }
 
-  /// Enqueue the static fields that have been marked as used by reflective
-  /// usage through `MirrorsUsed`.
-  // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
-  void enqueueReflectiveStaticFields(
-      Enqueuer enqueuer, Iterable<Element> elements) {
-    MirrorsHandler handler =
-        enqueuer.isResolutionQueue ? resolutionHandler : codegenHandler;
-    handler.enqueueReflectiveStaticFields(enqueuer, elements);
+  /// Compute the impact for the static fields that have been marked as used by
+  /// reflective usage through `MirrorsUsed`.
+  WorldImpact computeImpactForReflectiveStaticFields(Iterable<Element> elements,
+      {bool forResolution}) {
+    MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
+    handler.enqueueReflectiveStaticFields(elements);
+    return handler.flush();
   }
 }
 
@@ -53,10 +53,14 @@
   bool hasEnqueuedReflectiveElements = false;
   bool hasEnqueuedReflectiveStaticFields = false;
 
+  StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
+
   MirrorsHandler(this._backend, this._resolution);
 
   DiagnosticReporter get _reporter => _resolution.reporter;
 
+  WorldImpact flush() => impactBuilder.flush();
+
   void _logEnqueueReflectiveAction(action, [msg = ""]) {
     if (TRACE_MIRROR_ENQUEUING) {
       print("MIRROR_ENQUEUE (R): $action $msg");
@@ -80,15 +84,15 @@
   ///
   /// [enclosingWasIncluded] provides a hint whether the enclosing element was
   /// needed for reflection.
-  void _enqueueReflectiveConstructor(
-      Enqueuer enqueuer, ConstructorElement constructor,
+  void _enqueueReflectiveConstructor(ConstructorElement constructor,
       {bool enclosingWasIncluded}) {
     if (_shouldIncludeElementDueToMirrors(constructor,
         includedEnclosing: enclosingWasIncluded)) {
       _logEnqueueReflectiveAction(constructor);
       ClassElement cls = constructor.declaration.enclosingClass;
-      enqueuer.registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
-      enqueuer
+      impactBuilder
+          .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
+      impactBuilder
           .registerStaticUse(new StaticUse.foreignUse(constructor.declaration));
     }
   }
@@ -97,8 +101,7 @@
   ///
   /// [enclosingWasIncluded] provides a hint whether the enclosing element was
   /// needed for reflection.
-  void _enqueueReflectiveMember(
-      Enqueuer enqueuer, Element element, bool enclosingWasIncluded) {
+  void _enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
     if (_shouldIncludeElementDueToMirrors(element,
         includedEnclosing: enclosingWasIncluded)) {
       _logEnqueueReflectiveAction(element);
@@ -106,7 +109,7 @@
         TypedefElement typedef = element;
         typedef.ensureResolved(_resolution);
       } else if (Elements.isStaticOrTopLevel(element)) {
-        enqueuer
+        impactBuilder
             .registerStaticUse(new StaticUse.foreignUse(element.declaration));
       } else if (element.isInstanceMember) {
         // We need to enqueue all members matching this one in subclasses, as
@@ -114,13 +117,13 @@
         // TODO(herhut): Use TypedSelector.subtype for enqueueing
         DynamicUse dynamicUse =
             new DynamicUse(new Selector.fromElement(element), null);
-        enqueuer.registerDynamicUse(dynamicUse);
+        impactBuilder.registerDynamicUse(dynamicUse);
         if (element.isField) {
           DynamicUse dynamicUse = new DynamicUse(
               new Selector.setter(
                   new Name(element.name, element.library, isSetter: true)),
               null);
-          enqueuer.registerDynamicUse(dynamicUse);
+          impactBuilder.registerDynamicUse(dynamicUse);
         }
       }
     }
@@ -131,7 +134,7 @@
   /// [enclosingWasIncluded] provides a hint whether the enclosing element was
   /// needed for reflection.
   void _enqueueReflectiveElementsInClass(
-      Enqueuer enqueuer, ClassElement cls, Iterable<ClassElement> recents,
+      ClassElement cls, Iterable<ClassElement> recents,
       {bool enclosingWasIncluded}) {
     if (cls.library.isInternalLibrary || cls.isInjected) return;
     bool includeClass = _shouldIncludeElementDueToMirrors(cls,
@@ -140,7 +143,7 @@
       _logEnqueueReflectiveAction(cls, "register");
       ClassElement declaration = cls.declaration;
       declaration.ensureResolved(_resolution);
-      enqueuer.registerTypeUse(
+      impactBuilder.registerTypeUse(
           new TypeUse.mirrorInstantiation(declaration.rawType));
     }
     // If the class is never instantiated, we know nothing of it can possibly
@@ -149,11 +152,11 @@
     if (recents.contains(cls.declaration)) {
       _logEnqueueReflectiveAction(cls, "members");
       cls.constructors.forEach((Element element) {
-        _enqueueReflectiveConstructor(enqueuer, element,
+        _enqueueReflectiveConstructor(element,
             enclosingWasIncluded: includeClass);
       });
       cls.forEachClassMember((Member member) {
-        _enqueueReflectiveMember(enqueuer, member.element, includeClass);
+        _enqueueReflectiveMember(member.element, includeClass);
       });
     }
   }
@@ -165,13 +168,14 @@
   /// Although it is in an internal library, we mark it as reflectable. Note
   /// that none of its methods are reflectable, unless reflectable by
   /// inheritance.
-  void _enqueueReflectiveSpecialClasses(Enqueuer enqueuer) {
+  void _enqueueReflectiveSpecialClasses() {
     Iterable<ClassElement> classes = _backend.classesRequiredForReflection;
     for (ClassElement cls in classes) {
       if (_backend.referencedFromMirrorSystem(cls)) {
         _logEnqueueReflectiveAction(cls);
         cls.ensureResolved(_resolution);
-        enqueuer.registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
+        impactBuilder
+            .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
       }
     }
   }
@@ -179,16 +183,16 @@
   /// Enqeue all local members of the library [lib] if they are required for
   /// reflection.
   void _enqueueReflectiveElementsInLibrary(
-      Enqueuer enqueuer, LibraryElement lib, Iterable<ClassElement> recents) {
+      LibraryElement lib, Iterable<ClassElement> recents) {
     bool includeLibrary =
         _shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
     lib.forEachLocalMember((Element member) {
       if (member.isInjected) return;
       if (member.isClass) {
-        _enqueueReflectiveElementsInClass(enqueuer, member, recents,
+        _enqueueReflectiveElementsInClass(member, recents,
             enclosingWasIncluded: includeLibrary);
       } else {
-        _enqueueReflectiveMember(enqueuer, member, includeLibrary);
+        _enqueueReflectiveMember(member, includeLibrary);
       }
     });
   }
@@ -197,8 +201,8 @@
   /// annotation or, in lack thereof, all elements.
   // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
   void enqueueReflectiveElements(
-      Enqueuer enqueuer,
       Iterable<ClassElement> recents,
+      Iterable<ClassElement> processedClasses,
       Iterable<LibraryElement> loadedLibraries) {
     if (!hasEnqueuedReflectiveElements) {
       _logEnqueueReflectiveAction("!START enqueueAll");
@@ -208,12 +212,12 @@
       // as recently seen, as we do not know how many rounds of resolution might
       // have run before tree shaking is disabled and thus everything is
       // enqueued.
-      recents = enqueuer.processedClasses.toSet();
+      recents = processedClasses.toSet();
       _reporter.log('Enqueuing everything');
       for (LibraryElement lib in loadedLibraries) {
-        _enqueueReflectiveElementsInLibrary(enqueuer, lib, recents);
+        _enqueueReflectiveElementsInLibrary(lib, recents);
       }
-      _enqueueReflectiveSpecialClasses(enqueuer);
+      _enqueueReflectiveSpecialClasses();
       hasEnqueuedReflectiveElements = true;
       hasEnqueuedReflectiveStaticFields = true;
       _logEnqueueReflectiveAction("!DONE enqueueAll");
@@ -221,7 +225,7 @@
       // Keep looking at new classes until fixpoint is reached.
       _logEnqueueReflectiveAction("!START enqueueRecents");
       recents.forEach((ClassElement cls) {
-        _enqueueReflectiveElementsInClass(enqueuer, cls, recents,
+        _enqueueReflectiveElementsInClass(cls, recents,
             enclosingWasIncluded: _shouldIncludeElementDueToMirrors(cls.library,
                 includedEnclosing: false));
       });
@@ -232,12 +236,11 @@
   /// Enqueue the static fields that have been marked as used by reflective
   /// usage through `MirrorsUsed`.
   // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
-  void enqueueReflectiveStaticFields(
-      Enqueuer enqueuer, Iterable<Element> elements) {
+  void enqueueReflectiveStaticFields(Iterable<Element> elements) {
     if (hasEnqueuedReflectiveStaticFields) return;
     hasEnqueuedReflectiveStaticFields = true;
     for (Element element in elements) {
-      _enqueueReflectiveMember(enqueuer, element, true);
+      _enqueueReflectiveMember(element, true);
     }
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
index 97c6011..ff8822d 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common.dart';
-import '../common/registry.dart' show Registry;
 import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart';
 import '../constants/values.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/headers.dart b/pkg/compiler/lib/src/js_emitter/headers.dart
index 905cb04..ad9e783 100644
--- a/pkg/compiler/lib/src/js_emitter/headers.dart
+++ b/pkg/compiler/lib/src/js_emitter/headers.dart
@@ -32,4 +32,8 @@
 //    is loaded. It should load and eval the javascript of `uri`, and call
 //    successCallback. If it fails to do so, it should call errorCallback with
 //    an error.
+//
+// defaultPackagesBase:
+//    Override the location where `package:` uris are resolved from. By default
+//    they are resolved under "packages/" from the current window location.
 """;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 44d3be3..300a650 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -6,7 +6,6 @@
 
 import '../common.dart';
 import '../common/backend_api.dart' show ForeignResolver;
-import '../common/registry.dart' show Registry;
 import '../common/resolution.dart' show Resolution;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
@@ -14,7 +13,6 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart' show FunctionElementX;
-import '../enqueue.dart' show Enqueuer;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart';
 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
@@ -22,7 +20,8 @@
 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
 import '../tree/tree.dart';
 import '../universe/use.dart' show StaticUse, TypeUse;
-import '../universe/world_impact.dart' show WorldImpactBuilder;
+import '../universe/world_impact.dart'
+    show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
 import 'behavior.dart';
 
 /**
@@ -33,8 +32,8 @@
   void onInstantiatedType(InterfaceType type) {}
 
   /// Initial entry point to native enqueuer.
-  void processNativeClasses(
-      WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {}
+  WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) =>
+      const WorldImpact();
 
   /// Registers the [nativeBehavior]. Adds the liveness of its instantiated
   /// types to the world.
@@ -68,31 +67,19 @@
 abstract class NativeEnqueuerBase implements NativeEnqueuer {
   static final RegExp _identifier = new RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$');
 
-  /**
-   * The set of all native classes.  Each native class is in [nativeClasses] and
-   * exactly one of [unusedClasses], [pendingClasses] and [registeredClasses].
-   */
-  final Set<ClassElement> nativeClasses = new Set<ClassElement>();
+  /// The set of all native classes.  Each native class is in [nativeClasses]
+  /// and exactly one of [unusedClasses] and [registeredClasses].
+  final Set<ClassElement> _nativeClasses = new Set<ClassElement>();
 
-  final Set<ClassElement> registeredClasses = new Set<ClassElement>();
-  final Set<ClassElement> pendingClasses = new Set<ClassElement>();
-  final Set<ClassElement> unusedClasses = new Set<ClassElement>();
+  final Set<ClassElement> _registeredClasses = new Set<ClassElement>();
+  final Set<ClassElement> _unusedClasses = new Set<ClassElement>();
 
   final Set<LibraryElement> processedLibraries;
 
-  bool get hasInstantiatedNativeClasses => !registeredClasses.isEmpty;
+  bool get hasInstantiatedNativeClasses => !_registeredClasses.isEmpty;
 
   final Set<ClassElement> nativeClassesAndSubclasses = new Set<ClassElement>();
 
-  final Map<ClassElement, Set<ClassElement>> nonNativeSubclasses =
-      new Map<ClassElement, Set<ClassElement>>();
-
-  /**
-   * Records matched constraints ([SpecialType] or [DartType]).  Once a type
-   * constraint has been matched, there is no need to match it again.
-   */
-  final Set matchedTypeConstraints = new Set();
-
   final Compiler compiler;
   final bool enableLiveTypeAnalysis;
 
@@ -113,12 +100,18 @@
   CoreTypes get coreTypes => compiler.coreTypes;
 
   void onInstantiatedType(InterfaceType type) {
-    if (unusedClasses.remove(type.element)) {
-      registeredClasses.add(type.element);
+    if (_unusedClasses.remove(type.element)) {
+      _registeredClasses.add(type.element);
     }
   }
 
-  void processNativeClasses(
+  WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) {
+    WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
+    _processNativeClasses(impactBuilder, libraries);
+    return impactBuilder;
+  }
+
+  void _processNativeClasses(
       WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
     if (compiler.options.hasIncrementalSupport) {
       // Since [Set.add] returns bool if an element was added, this restricts
@@ -132,7 +125,7 @@
     }
     processSubclassesOfNativeClasses(libraries);
     if (!enableLiveTypeAnalysis) {
-      _registerTypeUses(impactBuilder, nativeClasses, 'forced');
+      _registerTypeUses(impactBuilder, _nativeClasses, 'forced');
     }
   }
 
@@ -146,8 +139,8 @@
   }
 
   void processNativeClass(ClassElement classElement) {
-    nativeClasses.add(classElement);
-    unusedClasses.add(classElement);
+    _nativeClasses.add(classElement);
+    _unusedClasses.add(classElement);
     // Resolve class to ensure the class has valid inheritance info.
     classElement.ensureResolved(resolution);
   }
@@ -190,11 +183,6 @@
       ClassElement nativeSuperclass = nativeSuperclassOf(element);
       if (nativeSuperclass != null) {
         nativeClassesAndSubclasses.add(element);
-        if (!backend.isNative(element)) {
-          nonNativeSubclasses
-              .putIfAbsent(nativeSuperclass, () => new Set<ClassElement>())
-              .add(element);
-        }
         Set<ClassElement> potentialSubclasses = potentialExtends[element.name];
         if (potentialSubclasses != null) {
           potentialSubclasses.forEach(walkPotentialSubclasses);
@@ -202,10 +190,10 @@
       }
     }
 
-    nativeClasses.forEach(walkPotentialSubclasses);
+    _nativeClasses.forEach(walkPotentialSubclasses);
 
-    nativeClasses.addAll(nativeClassesAndSubclasses);
-    unusedClasses.addAll(nativeClassesAndSubclasses);
+    _nativeClasses.addAll(nativeClassesAndSubclasses);
+    _unusedClasses.addAll(nativeClassesAndSubclasses);
   }
 
   /**
@@ -344,7 +332,7 @@
   void _registerTypeUses(
       WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
     for (ClassElement cls in classes) {
-      if (!unusedClasses.contains(cls)) {
+      if (!_unusedClasses.contains(cls)) {
         // No need to add [classElement] to [impactBuilder]: it has already been
         // instantiated and we don't track origins of native instantiations
         // precisely.
@@ -446,11 +434,9 @@
       impactBuilder.registerTypeUse(new TypeUse.nativeInstantiation(type));
     }
 
-    int unusedBefore = unusedClasses.length;
+    int unusedBefore = _unusedClasses.length;
     Set<ClassElement> matchingClasses = new Set<ClassElement>();
     for (var type in behavior.typesInstantiated) {
-      if (matchedTypeConstraints.contains(type)) continue;
-      matchedTypeConstraints.add(type);
       if (type is SpecialType) {
         if (type == SpecialType.JsObject) {
           registerInstantiation(compiler.coreTypes.objectType);
@@ -489,12 +475,12 @@
           return compiler.types.isSubtype(nativeType, specType);
         }));
       } else if (type.isDynamic) {
-        matchingClasses.addAll(unusedClasses);
+        matchingClasses.addAll(_unusedClasses);
       } else {
         assert(type is VoidType);
       }
     }
-    if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
+    if (matchingClasses.isNotEmpty && _registeredClasses.isEmpty) {
       matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
     }
     _registerTypeUses(impactBuilder, matchingClasses, cause);
@@ -508,7 +494,7 @@
 
   Iterable<ClassElement> _findUnusedClassesMatching(
       bool predicate(classElement)) {
-    return unusedClasses.where(predicate);
+    return _unusedClasses.where(predicate);
   }
 
   Iterable<ClassElement> _onFirstNativeClass(WorldImpactBuilder impactBuilder) {
@@ -564,8 +550,8 @@
   }
 
   void logSummary(log(message)) {
-    log('Resolved ${registeredClasses.length} native elements used, '
-        '${unusedClasses.length} native elements dead.');
+    log('Resolved ${_registeredClasses.length} native elements used, '
+        '${_unusedClasses.length} native elements dead.');
   }
 
   /**
@@ -620,19 +606,19 @@
   NativeCodegenEnqueuer(Compiler compiler, this.emitter)
       : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
 
-  void processNativeClasses(
+  void _processNativeClasses(
       WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
-    super.processNativeClasses(impactBuilder, libraries);
+    super._processNativeClasses(impactBuilder, libraries);
 
     // HACK HACK - add all the resolved classes.
     NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
     Set<ClassElement> matchingClasses = new Set<ClassElement>();
-    for (final classElement in enqueuer.registeredClasses) {
-      if (unusedClasses.contains(classElement)) {
+    for (final classElement in enqueuer._registeredClasses) {
+      if (_unusedClasses.contains(classElement)) {
         matchingClasses.add(classElement);
       }
     }
-    if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
+    if (matchingClasses.isNotEmpty && _registeredClasses.isEmpty) {
       matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
     }
     _registerTypeUses(impactBuilder, matchingClasses, 'was resolved');
@@ -679,7 +665,7 @@
   }
 
   void logSummary(log(message)) {
-    log('Compiled ${registeredClasses.length} native classes, '
-        '${unusedClasses.length} native classes omitted.');
+    log('Compiled ${_registeredClasses.length} native classes, '
+        '${_unusedClasses.length} native classes omitted.');
   }
 }
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 51d7e81..ce40fd0 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -7,7 +7,6 @@
 import '../common.dart';
 import '../common/backend_api.dart'
     show Backend, ForeignResolver, NativeRegistry;
-import '../common/registry.dart' show Registry;
 import '../common/resolution.dart' show ResolutionImpact, Target;
 import '../constants/expressions.dart';
 import '../dart_types.dart';
@@ -154,7 +153,7 @@
 /// related information in a [TreeElements] mapping and registers calls with
 /// [Backend], [World] and [Enqueuer].
 // TODO(johnniwinther): Split this into an interface and implementation class.
-class ResolutionRegistry extends Registry {
+class ResolutionRegistry {
   final Target target;
   final TreeElementMapping mapping;
   final ResolutionWorldImpactBuilder impactBuilder;
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index abf9afa..8bb5e0b 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -36,7 +36,7 @@
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
-import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
+import '../universe/use.dart' show DynamicUse, StaticUse;
 import '../util/util.dart';
 import '../world.dart' show ClosedWorld;
 
@@ -47,6 +47,7 @@
 import 'nodes.dart';
 import 'optimize.dart';
 import 'ssa_branch_builder.dart';
+import 'type_builder.dart';
 import 'types.dart';
 
 class SsaBuilderTask extends CompilerTask {
@@ -188,6 +189,9 @@
   /// Handles the building of loops.
   LoopHandler<ast.Node> loopHandler;
 
+  /// Handles type check building.
+  TypeBuilder typeBuilder;
+
   // TODO(sigmund): make most args optional
   SsaBuilder(
       this.target,
@@ -213,6 +217,7 @@
         sourceInformationBuilder.buildVariableDeclaration();
     localsHandler = new LocalsHandler(this, target, null, compiler);
     loopHandler = new SsaLoopHandler(this);
+    typeBuilder = new TypeBuilder(this);
   }
 
   BackendHelpers get helpers => backend.helpers;
@@ -223,6 +228,8 @@
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
+  Element get targetElement => target;
+
   /// Reference to resolved elements in [target]'s AST.
   TreeElements get elements => resolvedAst.elements;
 
@@ -244,6 +251,7 @@
   /// The returned element is a declaration element.
   // TODO(johnniwinther): Check that all usages of sourceElement agree on
   // implementation/declaration distinction.
+  @override
   Element get sourceElement => sourceElementStack.last;
 
   /// Helper to retrieve global inference results for [element] with special
@@ -257,10 +265,6 @@
       inferenceResults.resultOf(
           element is ConstructorBodyElementX ? element.constructor : element);
 
-  bool get _checkOrTrustTypes =>
-      compiler.options.enableTypeAssertions ||
-      compiler.options.trustTypeAnnotations;
-
   /// Build the graph for [target].
   HGraph build() {
     assert(invariant(target, target.isImplementation));
@@ -294,6 +298,13 @@
     add(attachPosition(instruction, node));
   }
 
+  HTypeConversion buildFunctionTypeConversion(
+      HInstruction original, DartType type, int kind) {
+    HInstruction reifiedType = buildFunctionType(type);
+    return new HTypeConversion.viaMethodOnType(
+        type, kind, original.instructionType, reifiedType, original);
+  }
+
   /**
    * Returns a complete argument list for a call of [function].
    */
@@ -309,8 +320,7 @@
     // For static calls, [providedArguments] is complete, default arguments
     // have been included if necessary, see [makeStaticArgumentList].
     if (!isInstanceMember ||
-        currentNode == null // In erroneous code, currentNode can be null.
-        ||
+        currentNode == null || // In erroneous code, currentNode can be null.
         providedArgumentsKnownToBeComplete(currentNode) ||
         function.isGenerativeConstructorBody ||
         selector.isGetter) {
@@ -751,7 +761,8 @@
     // If the method is intercepted, we want the actual receiver
     // to be the first parameter.
     graph.entry.addBefore(graph.entry.last, parameter);
-    HInstruction value = potentiallyCheckOrTrustType(parameter, field.type);
+    HInstruction value =
+        typeBuilder.potentiallyCheckOrTrustType(parameter, field.type);
     add(new HFieldSet(field, thisInstruction, value));
     return closeFunction();
   }
@@ -767,7 +778,7 @@
     openFunction(variable, node);
     visit(initializer);
     HInstruction value = pop();
-    value = potentiallyCheckOrTrustType(value, variable.type);
+    value = typeBuilder.potentiallyCheckOrTrustType(value, variable.type);
     // In the case of multiple declarations (and some definitions) on the same
     // line, the source pointer needs to point to the right initialized
     // variable. So find the specific initialized variable we are referring to.
@@ -899,7 +910,8 @@
    * Run this builder on the body of the [function] to be inlined.
    */
   void visitInlinedFunction(ResolvedAst resolvedAst) {
-    potentiallyCheckInlinedParameterTypes(resolvedAst.element.implementation);
+    typeBuilder.potentiallyCheckInlinedParameterTypes(
+        resolvedAst.element.implementation);
 
     if (resolvedAst.element.isGenerativeConstructor) {
       buildFactory(resolvedAst);
@@ -932,20 +944,6 @@
   }
 
   /**
-   * In checked mode, generate type tests for the parameters of the inlined
-   * function.
-   */
-  void potentiallyCheckInlinedParameterTypes(FunctionElement function) {
-    if (!_checkOrTrustTypes) return;
-
-    FunctionSignature signature = function.functionSignature;
-    signature.orderedForEachParameter((ParameterElement parameter) {
-      HInstruction argument = localsHandler.readLocal(parameter);
-      potentiallyCheckOrTrustType(argument, parameter.type);
-    });
-  }
-
-  /**
    * Documentation wanted -- johnniwinther
    *
    * Invariant: [constructors] must contain only implementation elements.
@@ -980,7 +978,7 @@
             TypeVariableType typeVariable = variables.current;
             localsHandler.updateLocal(
                 localsHandler.getTypeVariableAsLocal(typeVariable),
-                analyzeTypeArgument(argument));
+                typeBuilder.analyzeTypeArgument(argument, sourceElement));
           });
         } else {
           // If the supertype is a raw type, we need to set to null the
@@ -1282,7 +1280,8 @@
       } else {
         fields.add(member);
         DartType type = localsHandler.substInContext(member.type);
-        constructorArguments.add(potentiallyCheckOrTrustType(value, type));
+        constructorArguments
+            .add(typeBuilder.potentiallyCheckOrTrustType(value, type));
       }
     }, includeSuperAndInjectedMembers: true);
 
@@ -1480,8 +1479,8 @@
           //       new A("foo");  // invalid in checked mode.
           //
           // Only the final target is allowed to check for the argument types.
-          newParameter =
-              potentiallyCheckOrTrustType(newParameter, parameterElement.type);
+          newParameter = typeBuilder.potentiallyCheckOrTrustType(
+              newParameter, parameterElement.type);
         }
         localsHandler.directLocals[parameterElement] = newParameter;
       });
@@ -1519,112 +1518,12 @@
     }
   }
 
-  /// Check that [type] is valid in the context of `localsHandler.contextClass`.
-  /// This should only be called in assertions.
-  bool assertTypeInContext(DartType type, [Spannable spannable]) {
-    return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable,
-        () {
-      ClassElement contextClass = Types.getClassContext(type);
-      return contextClass == null || contextClass == localsHandler.contextClass;
-    },
-        message: "Type '$type' is not valid context of "
-            "${localsHandler.contextClass}.");
-  }
-
-  /// Build a [HTypeConversion] for converting [original] to type [type].
-  ///
-  /// Invariant: [type] must be valid in the context.
-  /// See [LocalsHandler.substInContext].
-  HInstruction buildTypeConversion(
-      HInstruction original, DartType type, int kind) {
-    if (type == null) return original;
-    // GENERIC_METHODS: The following statement was added for parsing and
-    // ignoring method type variables; must be generalized for full support of
-    // generic methods.
-    type = type.dynamifyMethodTypeVariableType;
-    type = type.unaliased;
-    assert(assertTypeInContext(type, original));
-    if (type.isInterfaceType && !type.treatAsRaw) {
-      TypeMask subtype =
-          new TypeMask.subtype(type.element, compiler.closedWorld);
-      HInstruction representations = buildTypeArgumentRepresentations(type);
-      add(representations);
-      return new HTypeConversion.withTypeRepresentation(
-          type, kind, subtype, original, representations);
-    } else if (type.isTypeVariable) {
-      TypeMask subtype = original.instructionType;
-      HInstruction typeVariable = addTypeVariableReference(type);
-      return new HTypeConversion.withTypeRepresentation(
-          type, kind, subtype, original, typeVariable);
-    } else if (type.isFunctionType) {
-      String name =
-          kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck';
-
-      List<HInstruction> arguments = <HInstruction>[
-        buildFunctionType(type),
-        original
-      ];
-      pushInvokeDynamic(
-          null,
-          new Selector.call(
-              new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG),
-          null,
-          arguments);
-
-      return new HTypeConversion(type, kind, original.instructionType, pop());
-    } else {
-      return original.convertType(compiler, type, kind);
-    }
-  }
-
-  HInstruction _trustType(HInstruction original, DartType type) {
-    assert(compiler.options.trustTypeAnnotations);
-    assert(type != null);
-    type = localsHandler.substInContext(type);
-    type = type.unaliased;
-    if (type.isDynamic) return original;
-    if (!type.isInterfaceType) return original;
-    if (type.isObject) return original;
-    // The type element is either a class or the void element.
-    Element element = type.element;
-    TypeMask mask = new TypeMask.subtype(element, compiler.closedWorld);
-    return new HTypeKnown.pinned(mask, original);
-  }
-
-  HInstruction _checkType(HInstruction original, DartType type, int kind) {
-    assert(compiler.options.enableTypeAssertions);
-    assert(type != null);
-    type = localsHandler.substInContext(type);
-    HInstruction other = buildTypeConversion(original, type, kind);
-    // TODO(johnniwinther): This operation on `registry` may be inconsistent.
-    // If it is needed then it seems likely that similar invocations of
-    // `buildTypeConversion` in `SsaBuilder.visitAs` should also be followed by
-    // a similar operation on `registry`; otherwise, this one might not be
-    // needed.
-    registry?.registerTypeUse(new TypeUse.isCheck(type));
-    return other;
-  }
-
-  HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type,
-      {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
-    if (type == null) return original;
-    HInstruction checkedOrTrusted = original;
-    if (compiler.options.trustTypeAnnotations) {
-      checkedOrTrusted = _trustType(original, type);
-    } else if (compiler.options.enableTypeAssertions) {
-      checkedOrTrusted = _checkType(original, type, kind);
-    }
-    if (checkedOrTrusted == original) return original;
-    add(checkedOrTrusted);
-    return checkedOrTrusted;
-  }
-
   void assertIsSubtype(
       ast.Node node, DartType subtype, DartType supertype, String message) {
-    HInstruction subtypeInstruction =
-        analyzeTypeArgument(localsHandler.substInContext(subtype));
-    HInstruction supertypeInstruction =
-        analyzeTypeArgument(localsHandler.substInContext(supertype));
+    HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument(
+        localsHandler.substInContext(subtype), sourceElement);
+    HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument(
+        localsHandler.substInContext(supertype), sourceElement);
     HInstruction messageInstruction =
         graph.addConstantString(new ast.DartString.literal(message), compiler);
     MethodElement element = helpers.assertIsSubtype;
@@ -1650,11 +1549,15 @@
     push(attachPosition(instruction, node));
   }
 
+  /// Pops the most recent instruction from the stack and 'boolifies' it.
+  ///
+  /// Boolification is checking if the value is '=== true'.
   @override
   HInstruction popBoolified() {
     HInstruction value = pop();
-    if (_checkOrTrustTypes) {
-      return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType,
+    if (typeBuilder.checkOrTrustTypes) {
+      return typeBuilder.potentiallyCheckOrTrustType(
+          value, compiler.coreTypes.boolType,
           kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
     }
     HInstruction result = new HBoolify(value, backend.boolType);
@@ -2445,7 +2348,7 @@
         pop();
       } else {
         FieldElement field = element;
-        value = potentiallyCheckOrTrustType(value, field.type);
+        value = typeBuilder.potentiallyCheckOrTrustType(value, field.type);
         addWithPosition(new HStaticStore(field, value), location);
       }
       stack.add(value);
@@ -2462,7 +2365,7 @@
         value.sourceElement = local;
       }
       HInstruction checkedOrTrusted =
-          potentiallyCheckOrTrustType(value, local.type);
+          typeBuilder.potentiallyCheckOrTrustType(value, local.type);
       if (!identical(checkedOrTrusted, value)) {
         pop();
         stack.add(checkedOrTrusted);
@@ -2484,24 +2387,6 @@
     return new HLiteralList(inputs, backend.extendableArrayType);
   }
 
-  HInstruction buildTypeArgumentRepresentations(DartType type) {
-    assert(!type.isTypeVariable);
-    // Compute the representation of the type arguments, including access
-    // to the runtime type information for type variables as instructions.
-    assert(type.element.isClass);
-    InterfaceType interface = type;
-    List<HInstruction> inputs = <HInstruction>[];
-    for (DartType argument in interface.typeArguments) {
-      inputs.add(analyzeTypeArgument(argument));
-    }
-    HInstruction representation = new HTypeInfoExpression(
-        TypeInfoExpressionKind.INSTANCE,
-        interface.element.thisType,
-        inputs,
-        backend.dynamicType);
-    return representation;
-  }
-
   @override
   void visitAs(ast.Send node, ast.Node expression, DartType type, _) {
     HInstruction expressionInstruction = visitAndPop(expression);
@@ -2514,8 +2399,10 @@
         stack.add(expressionInstruction);
       }
     } else {
-      HInstruction converted = buildTypeConversion(expressionInstruction,
-          localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK);
+      HInstruction converted = typeBuilder.buildTypeConversion(
+          expressionInstruction,
+          localsHandler.substInContext(type),
+          HTypeConversion.CAST_TYPE_CHECK);
       if (converted != expressionInstruction) add(converted);
       stack.add(converted);
     }
@@ -2561,7 +2448,8 @@
           arguments);
       return new HIs.compound(type, expression, pop(), backend.boolType);
     } else if (type.isTypeVariable) {
-      HInstruction runtimeType = addTypeVariableReference(type);
+      HInstruction runtimeType =
+          typeBuilder.addTypeVariableReference(type, sourceElement);
       Element helper = helpers.checkSubtypeOfRuntimeType;
       List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
       pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType);
@@ -2570,7 +2458,8 @@
     } else if (RuntimeTypes.hasTypeArguments(type)) {
       ClassElement element = type.element;
       Element helper = helpers.checkSubtype;
-      HInstruction representations = buildTypeArgumentRepresentations(type);
+      HInstruction representations =
+          typeBuilder.buildTypeArgumentRepresentations(type, sourceElement);
       add(representations);
       js.Name operator = backend.namer.operatorIs(element);
       HInstruction isFieldName = addConstantStringFromName(operator);
@@ -2598,11 +2487,6 @@
     }
   }
 
-  HInstruction buildFunctionType(FunctionType type) {
-    type.accept(new TypeBuilder(compiler.closedWorld), this);
-    return pop();
-  }
-
   void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) {
     CallStructure callStructure = elements.getSelector(node).callStructure;
     if (callStructure.namedArgumentCount == 0) {
@@ -3389,113 +3273,6 @@
     });
   }
 
-  /**
-   * Generate code to extract the type argument from the object.
-   */
-  HInstruction readTypeVariable(TypeVariableType variable,
-      {SourceInformation sourceInformation}) {
-    assert(sourceElement.isInstanceMember);
-    assert(variable is! MethodTypeVariableType);
-    HInstruction target = localsHandler.readThis();
-    push(new HTypeInfoReadVariable(variable, target, backend.dynamicType)
-      ..sourceInformation = sourceInformation);
-    return pop();
-  }
-
-  // TODO(karlklose): this is needed to avoid a bug where the resolved type is
-  // not stored on a type annotation in the closure translator. Remove when
-  // fixed.
-  bool hasDirectLocal(Local local) {
-    return !localsHandler.isAccessedDirectly(local) ||
-        localsHandler.directLocals[local] != null;
-  }
-
-  /**
-   * Helper to create an instruction that gets the value of a type variable.
-   */
-  HInstruction addTypeVariableReference(TypeVariableType type,
-      {SourceInformation sourceInformation}) {
-    assert(assertTypeInContext(type));
-    if (type is MethodTypeVariableType) {
-      return graph.addConstantNull(compiler);
-    }
-    Element member = sourceElement;
-    bool isClosure = member.enclosingElement.isClosure;
-    if (isClosure) {
-      ClosureClassElement closureClass = member.enclosingElement;
-      member = closureClass.methodElement;
-      member = member.outermostEnclosingMemberOrTopLevel;
-    }
-    bool isInConstructorContext =
-        member.isConstructor || member.isGenerativeConstructorBody;
-    Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type);
-    if (isClosure) {
-      if (member.isFactoryConstructor ||
-          (isInConstructorContext && hasDirectLocal(typeVariableLocal))) {
-        // The type variable is used from a closure in a factory constructor.
-        // The value of the type argument is stored as a local on the closure
-        // itself.
-        return localsHandler.readLocal(typeVariableLocal,
-            sourceInformation: sourceInformation);
-      } else if (member.isFunction ||
-          member.isGetter ||
-          member.isSetter ||
-          isInConstructorContext) {
-        // The type variable is stored on the "enclosing object" and needs to be
-        // accessed using the this-reference in the closure.
-        return readTypeVariable(type, sourceInformation: sourceInformation);
-      } else {
-        assert(member.isField);
-        // The type variable is stored in a parameter of the method.
-        return localsHandler.readLocal(typeVariableLocal);
-      }
-    } else if (isInConstructorContext ||
-        // When [member] is a field, we can be either
-        // generating a checked setter or inlining its
-        // initializer in a constructor. An initializer is
-        // never built standalone, so in that case [target] is not
-        // the [member] itself.
-        (member.isField && member != target)) {
-      // The type variable is stored in a parameter of the method.
-      return localsHandler.readLocal(typeVariableLocal,
-          sourceInformation: sourceInformation);
-    } else if (member.isInstanceMember) {
-      // The type variable is stored on the object.
-      return readTypeVariable(type, sourceInformation: sourceInformation);
-    } else {
-      reporter.internalError(
-          type.element, 'Unexpected type variable in static context.');
-      return null;
-    }
-  }
-
-  HInstruction analyzeTypeArgument(DartType argument,
-      {SourceInformation sourceInformation}) {
-    assert(assertTypeInContext(argument));
-    argument = argument.unaliased;
-    if (argument.treatAsDynamic) {
-      // Represent [dynamic] as [null].
-      return graph.addConstantNull(compiler);
-    }
-
-    if (argument.isTypeVariable) {
-      return addTypeVariableReference(argument,
-          sourceInformation: sourceInformation);
-    }
-
-    List<HInstruction> inputs = <HInstruction>[];
-    argument.forEachTypeVariable((variable) {
-      if (variable is! MethodTypeVariableType) {
-        inputs.add(analyzeTypeArgument(variable));
-      }
-    });
-    HInstruction result = new HTypeInfoExpression(
-        TypeInfoExpressionKind.COMPLETE, argument, inputs, backend.dynamicType)
-      ..sourceInformation = sourceInformation;
-    add(result);
-    return result;
-  }
-
   HInstruction handleListConstructor(
       InterfaceType type, ast.Node currentNode, HInstruction newObject) {
     if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
@@ -3504,27 +3281,11 @@
     List<HInstruction> inputs = <HInstruction>[];
     type = localsHandler.substInContext(type);
     type.typeArguments.forEach((DartType argument) {
-      inputs.add(analyzeTypeArgument(argument));
+      inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
     });
     // TODO(15489): Register at codegen.
     registry?.registerInstantiation(type);
-    return callSetRuntimeTypeInfoWithTypeArguments(
-        type.element, inputs, newObject);
-  }
-
-  HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element,
-      List<HInstruction> rtiInputs, HInstruction newObject) {
-    if (!backend.classNeedsRti(element)) {
-      return newObject;
-    }
-
-    HInstruction typeInfo = new HTypeInfoExpression(
-        TypeInfoExpressionKind.INSTANCE,
-        element.thisType,
-        rtiInputs,
-        backend.dynamicType);
-    add(typeInfo);
-    return callSetRuntimeTypeInfo(typeInfo, newObject);
+    return callSetRuntimeTypeInfoWithTypeArguments(type, inputs, newObject);
   }
 
   HInstruction callSetRuntimeTypeInfo(
@@ -3681,12 +3442,8 @@
     TypeMask elementType = computeType(constructor);
     if (isFixedListConstructorCall) {
       if (!inputs[0].isNumber(compiler)) {
-        HTypeConversion conversion = new HTypeConversion(
-            null,
-            HTypeConversion.ARGUMENT_TYPE_CHECK,
-            backend.numType,
-            inputs[0],
-            null);
+        HTypeConversion conversion = new HTypeConversion(null,
+            HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, inputs[0]);
         add(conversion);
         inputs[0] = conversion;
       }
@@ -3752,7 +3509,8 @@
 
     // Finally, if we called a redirecting factory constructor, check the type.
     if (isRedirected) {
-      HInstruction checked = potentiallyCheckOrTrustType(newInstance, type);
+      HInstruction checked =
+          typeBuilder.potentiallyCheckOrTrustType(newInstance, type);
       if (checked != newInstance) {
         pop();
         stack.add(checked);
@@ -3766,8 +3524,8 @@
     if (!backend.classNeedsRti(cls)) return;
     assert(cls.typeVariables.length == expectedType.typeArguments.length);
     expectedType.typeArguments.forEach((DartType argument) {
-      inputs.add(
-          analyzeTypeArgument(argument, sourceInformation: sourceInformation));
+      inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement,
+          sourceInformation: sourceInformation));
     });
   }
 
@@ -4039,7 +3797,7 @@
       generateTypeError(node, "Method type variables are not reified");
     } else {
       DartType type = localsHandler.substInContext(typeVariable);
-      HInstruction value = analyzeTypeArgument(type,
+      HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement,
           sourceInformation: sourceInformationBuilder.buildGet(node));
       pushInvokeStatic(node, helpers.runtimeTypeToString, [value],
           typeMask: backend.stringType);
@@ -5365,7 +5123,7 @@
           redirectingConstructor.computeEffectiveTargetType(cls.thisType);
       targetType = localsHandler.substInContext(targetType);
       targetType.typeArguments.forEach((DartType argument) {
-        inputs.add(analyzeTypeArgument(argument));
+        inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
       });
     }
     pushInvokeStatic(node, targetConstructor.declaration, inputs);
@@ -5415,7 +5173,7 @@
           return;
         }
       } else {
-        value = potentiallyCheckOrTrustType(value, returnType);
+        value = typeBuilder.potentiallyCheckOrTrustType(value, returnType);
       }
     }
 
@@ -5477,12 +5235,11 @@
     }
     List<HInstruction> arguments = <HInstruction>[];
     for (DartType argument in type.typeArguments) {
-      arguments.add(analyzeTypeArgument(argument));
+      arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
     }
     // TODO(15489): Register at codegen.
     registry?.registerInstantiation(type);
-    return callSetRuntimeTypeInfoWithTypeArguments(
-        type.element, arguments, object);
+    return callSetRuntimeTypeInfoWithTypeArguments(type, arguments, object);
   }
 
   visitLiteralList(ast.LiteralList node) {
@@ -5925,7 +5682,8 @@
     if (backend.classNeedsRti(cls)) {
       List<HInstruction> typeInputs = <HInstruction>[];
       expectedType.typeArguments.forEach((DartType argument) {
-        typeInputs.add(analyzeTypeArgument(argument));
+        typeInputs
+            .add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
       });
 
       // We lift this common call pattern into a helper function to save space
@@ -7002,94 +6760,3 @@
       this.oldElementInferenceResults)
       : super(function);
 }
-
-class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
-  final ClosedWorld closedWorld;
-
-  TypeBuilder(this.closedWorld);
-
-  void visit(DartType type, SsaBuilder builder) => type.accept(this, builder);
-
-  void visitVoidType(VoidType type, SsaBuilder builder) {
-    ClassElement cls = builder.backend.helpers.VoidRuntimeType;
-    builder.push(new HVoidType(type, new TypeMask.exact(cls, closedWorld)));
-  }
-
-  void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) {
-    ClassElement cls = builder.backend.helpers.RuntimeType;
-    TypeMask instructionType = new TypeMask.subclass(cls, closedWorld);
-    if (!builder.sourceElement.enclosingElement.isClosure &&
-        builder.sourceElement.isInstanceMember) {
-      HInstruction receiver = builder.localsHandler.readThis();
-      builder.push(new HReadTypeVariable(type, receiver, instructionType));
-    } else {
-      builder.push(new HReadTypeVariable.noReceiver(
-          type, builder.addTypeVariableReference(type), instructionType));
-    }
-  }
-
-  void visitFunctionType(FunctionType type, SsaBuilder builder) {
-    type.returnType.accept(this, builder);
-    HInstruction returnType = builder.pop();
-    List<HInstruction> inputs = <HInstruction>[returnType];
-
-    for (DartType parameter in type.parameterTypes) {
-      parameter.accept(this, builder);
-      inputs.add(builder.pop());
-    }
-
-    for (DartType parameter in type.optionalParameterTypes) {
-      parameter.accept(this, builder);
-      inputs.add(builder.pop());
-    }
-
-    List<DartType> namedParameterTypes = type.namedParameterTypes;
-    List<String> names = type.namedParameters;
-    for (int index = 0; index < names.length; index++) {
-      ast.DartString dartString = new ast.DartString.literal(names[index]);
-      inputs.add(builder.graph.addConstantString(dartString, builder.compiler));
-      namedParameterTypes[index].accept(this, builder);
-      inputs.add(builder.pop());
-    }
-
-    ClassElement cls = builder.backend.helpers.RuntimeFunctionType;
-    builder.push(
-        new HFunctionType(inputs, type, new TypeMask.exact(cls, closedWorld)));
-  }
-
-  void visitMalformedType(MalformedType type, SsaBuilder builder) {
-    visitDynamicType(const DynamicType(), builder);
-  }
-
-  void visitStatementType(StatementType type, SsaBuilder builder) {
-    throw 'not implemented visitStatementType($type)';
-  }
-
-  void visitInterfaceType(InterfaceType type, SsaBuilder builder) {
-    List<HInstruction> inputs = <HInstruction>[];
-    for (DartType typeArgument in type.typeArguments) {
-      typeArgument.accept(this, builder);
-      inputs.add(builder.pop());
-    }
-    ClassElement cls;
-    if (type.typeArguments.isEmpty) {
-      cls = builder.backend.helpers.RuntimeTypePlain;
-    } else {
-      cls = builder.backend.helpers.RuntimeTypeGeneric;
-    }
-    builder.push(
-        new HInterfaceType(inputs, type, new TypeMask.exact(cls, closedWorld)));
-  }
-
-  void visitTypedefType(TypedefType type, SsaBuilder builder) {
-    DartType unaliased = type.unaliased;
-    if (unaliased is TypedefType) throw 'unable to unalias $type';
-    unaliased.accept(this, builder);
-  }
-
-  void visitDynamicType(DynamicType type, SsaBuilder builder) {
-    JavaScriptBackend backend = builder.compiler.backend;
-    ClassElement cls = backend.helpers.DynamicRuntimeType;
-    builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld)));
-  }
-}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 6183f3f..3f407ca 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -16,8 +16,11 @@
 import '../kernel/kernel.dart';
 import '../resolution/tree_elements.dart';
 import '../tree/dartstring.dart';
+import '../tree/nodes.dart' show FunctionExpression, Node;
 import '../types/masks.dart';
+import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart';
+import '../universe/use.dart' show TypeUse;
 import 'graph_builder.dart';
 import 'kernel_ast_adapter.dart';
 import 'kernel_string_builder.dart';
@@ -25,6 +28,7 @@
 import 'loop_handler.dart';
 import 'nodes.dart';
 import 'ssa_branch_builder.dart';
+import 'type_builder.dart';
 
 class SsaKernelBuilderTask extends CompilerTask {
   final JavaScriptBackend backend;
@@ -62,6 +66,7 @@
   SourceInformationBuilder sourceInformationBuilder;
   KernelAstAdapter astAdapter;
   LoopHandler<ir.Node> loopHandler;
+  TypeBuilder typeBuilder;
 
   KernelSsaBuilder(
       this.targetElement,
@@ -72,6 +77,7 @@
       Kernel kernel) {
     this.compiler = compiler;
     this.loopHandler = new KernelLoopHandler(this);
+    typeBuilder = new TypeBuilder(this);
     graph.element = targetElement;
     // TODO(het): Should sourceInformationBuilder be in GraphBuilder?
     this.sourceInformationBuilder =
@@ -118,23 +124,193 @@
     closeFunction();
   }
 
+  /// Pops the most recent instruction from the stack and 'boolifies' it.
+  ///
+  /// Boolification is checking if the value is '=== true'.
   @override
   HInstruction popBoolified() {
     HInstruction value = pop();
-    // TODO(het): add boolean conversion type check
+    if (typeBuilder.checkOrTrustTypes) {
+      return typeBuilder.potentiallyCheckOrTrustType(
+          value, compiler.coreTypes.boolType,
+          kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
+    }
     HInstruction result = new HBoolify(value, backend.boolType);
     add(result);
     return result;
   }
 
+  /// Builds generative constructors.
+  ///
+  /// Generative constructors are built in two stages.
+  ///
+  /// First, the field values for every instance field for every class in the
+  /// class hierarchy are collected. Then, create a function body that sets
+  /// all of the instance fields to the collected values and call the
+  /// constructor bodies for all constructors in the hierarchy.
   void buildConstructor(ir.Constructor constructor) {
-    // TODO(het): Actually handle this correctly
-    HBasicBlock block = graph.addNewBlock();
-    open(graph.entry);
-    close(new HGoto()).addSuccessor(block);
-    open(block);
-    closeAndGotoExit(new HGoto());
-    graph.finalize();
+    openFunction();
+
+    // Collect field values for the current class.
+    // TODO(het): Does kernel always put field initializers in the constructor
+    //            initializer list? If so then this is unnecessary...
+    Map<ir.Field, HInstruction> fieldValues =
+        _collectFieldValues(constructor.enclosingClass);
+
+    _buildInitializers(constructor, fieldValues);
+
+    final constructorArguments = <HInstruction>[];
+    astAdapter.getClass(constructor.enclosingClass).forEachInstanceField(
+        (ClassElement enclosingClass, FieldElement member) {
+      var value = fieldValues[astAdapter.getFieldFromElement(member)];
+      constructorArguments.add(value);
+    }, includeSuperAndInjectedMembers: true);
+
+    // TODO(het): If the class needs runtime type information, add it as a
+    // constructor argument.
+    HInstruction create = new HCreate(
+        astAdapter.getClass(constructor.enclosingClass),
+        constructorArguments,
+        new TypeMask.nonNullExact(
+            astAdapter.getClass(constructor.enclosingClass),
+            compiler.closedWorld),
+        instantiatedTypes: <DartType>[
+          astAdapter.getClass(constructor.enclosingClass).thisType
+        ],
+        hasRtiInput: false);
+
+    add(create);
+
+    // Generate calls to the constructor bodies.
+
+    closeAndGotoExit(new HReturn(create, null));
+    closeFunction();
+  }
+
+  /// Maps the fields of a class to their SSA values.
+  Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) {
+    final fieldValues = <ir.Field, HInstruction>{};
+
+    for (var field in clazz.fields) {
+      if (field.initializer == null) {
+        fieldValues[field] = graph.addConstantNull(compiler);
+      } else {
+        field.initializer.accept(this);
+        fieldValues[field] = pop();
+      }
+    }
+
+    return fieldValues;
+  }
+
+  /// Collects field initializers all the way up the inheritance chain.
+  void _buildInitializers(
+      ir.Constructor constructor, Map<ir.Field, HInstruction> fieldValues) {
+    var foundSuperCall = false;
+    for (var initializer in constructor.initializers) {
+      if (initializer is ir.SuperInitializer) {
+        foundSuperCall = true;
+        var superConstructor = initializer.target;
+        var arguments = _normalizeAndBuildArguments(
+            superConstructor.function, initializer.arguments);
+        _buildInlinedSuperInitializers(
+            superConstructor, arguments, fieldValues);
+      } else if (initializer is ir.FieldInitializer) {
+        initializer.value.accept(this);
+        fieldValues[initializer.field] = pop();
+      }
+    }
+
+    // TODO(het): does kernel always set the super initializer at the end?
+    // If there was no super-call initializer, then call the default constructor
+    // in the superclass.
+    if (!foundSuperCall) {
+      if (constructor.enclosingClass != astAdapter.objectClass) {
+        var superclass = constructor.enclosingClass.superclass;
+        var defaultConstructor = superclass.constructors
+            .firstWhere((c) => c.name == '', orElse: () => null);
+        if (defaultConstructor == null) {
+          compiler.reporter.internalError(
+              NO_LOCATION_SPANNABLE, 'Could not find default constructor.');
+        }
+        _buildInlinedSuperInitializers(
+            defaultConstructor, <HInstruction>[], fieldValues);
+      }
+    }
+  }
+
+  List<HInstruction> _normalizeAndBuildArguments(
+      ir.FunctionNode function, ir.Arguments arguments) {
+    var signature = astAdapter.getFunctionSignature(function);
+    var builtArguments = <HInstruction>[];
+    var positionalIndex = 0;
+    signature.forEachRequiredParameter((_) {
+      arguments.positional[positionalIndex++].accept(this);
+      builtArguments.add(pop());
+    });
+    if (!signature.optionalParametersAreNamed) {
+      signature.forEachOptionalParameter((ParameterElement element) {
+        if (positionalIndex < arguments.positional.length) {
+          arguments.positional[positionalIndex++].accept(this);
+          builtArguments.add(pop());
+        } else {
+          var constantValue =
+              backend.constants.getConstantValue(element.constant);
+          assert(invariant(element, constantValue != null,
+              message: 'No constant computed for $element'));
+          builtArguments.add(graph.addConstant(constantValue, compiler));
+        }
+      });
+    } else {
+      signature.orderedOptionalParameters.forEach((ParameterElement element) {
+        var correspondingNamed = arguments.named.firstWhere(
+            (named) => named.name == element.name,
+            orElse: () => null);
+        if (correspondingNamed != null) {
+          correspondingNamed.value.accept(this);
+          builtArguments.add(pop());
+        } else {
+          var constantValue =
+              backend.constants.getConstantValue(element.constant);
+          assert(invariant(element, constantValue != null,
+              message: 'No constant computed for $element'));
+          builtArguments.add(graph.addConstant(constantValue, compiler));
+        }
+      });
+    }
+
+    return builtArguments;
+  }
+
+  /// Inlines the given super [constructor]'s initializers by collecting it's
+  /// field values and building its constructor initializers. We visit super
+  /// constructors all the way up to the [Object] constructor.
+  void _buildInlinedSuperInitializers(ir.Constructor constructor,
+      List<HInstruction> arguments, Map<ir.Field, HInstruction> fieldValues) {
+    // TODO(het): Handle RTI if class needs it
+    fieldValues.addAll(_collectFieldValues(constructor.enclosingClass));
+
+    var signature = astAdapter.getFunctionSignature(constructor.function);
+    var index = 0;
+    signature.orderedForEachParameter((ParameterElement parameter) {
+      HInstruction argument = arguments[index++];
+      // Because we are inlining the initializer, we must update
+      // what was given as parameter. This will be used in case
+      // there is a parameter check expression in the initializer.
+      parameters[parameter] = argument;
+      localsHandler.updateLocal(parameter, argument);
+    });
+
+    // TODO(het): set the locals handler state as if we were inlining the
+    // constructor.
+    _buildInitializers(constructor, fieldValues);
+  }
+
+  HTypeConversion buildFunctionTypeConversion(
+      HInstruction original, DartType type, int kind) {
+    HInstruction reifiedType = buildFunctionType(type);
+    return new HTypeConversion.viaMethodOnType(
+        type, kind, original.instructionType, reifiedType, original);
   }
 
   /// Builds a SSA graph for [procedure].
@@ -147,7 +323,12 @@
   void openFunction() {
     HBasicBlock block = graph.addNewBlock();
     open(graph.entry);
-    localsHandler.startFunction(targetElement, resolvedAst.node);
+
+    Node function;
+    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+      function = resolvedAst.node;
+    }
+    localsHandler.startFunction(targetElement, function);
     close(new HGoto()).addSuccessor(block);
 
     open(block);
@@ -158,12 +339,25 @@
     graph.finalize();
   }
 
+  /// Pushes a boolean checking [expression] against null.
+  pushCheckNull(HInstruction expression) {
+    push(new HIdentity(
+        expression, graph.addConstantNull(compiler), null, backend.boolType));
+  }
+
   @override
   void defaultExpression(ir.Expression expression) {
     // TODO(het): This is only to get tests working
     stack.add(graph.addConstantNull(compiler));
   }
 
+  /// Returns the current source element.
+  ///
+  /// The returned element is a declaration element.
+  // TODO(efortuna): Update this when we implement inlining.
+  @override
+  Element get sourceElement => astAdapter.getElement(target);
+
   @override
   void visitBlock(ir.Block block) {
     assert(!isAborted());
@@ -197,9 +391,10 @@
     if (returnStatement.expression == null) {
       value = graph.addConstantNull(compiler);
     } else {
+      assert(target is ir.Procedure);
       returnStatement.expression.accept(this);
-      value = pop();
-      // TODO(het): Check or trust the type of value
+      value = typeBuilder.potentiallyCheckOrTrustType(pop(),
+          astAdapter.getFunctionReturnType((target as ir.Procedure).function));
     }
     // TODO(het): Add source information
     // TODO(het): Set a return value instead of closing the function when we
@@ -401,6 +596,26 @@
         forInStatement, buildInitializer, buildCondition, () {}, buildBody);
   }
 
+  HInstruction callSetRuntimeTypeInfo(
+      HInstruction typeInfo, HInstruction newObject) {
+    // Set the runtime type information on the object.
+    ir.Procedure typeInfoSetterFn = astAdapter.setRuntimeTypeInfo;
+    // TODO(efortuna): Insert source information in this static invocation.
+    _pushStaticInvocation(typeInfoSetterFn, <HInstruction>[newObject, typeInfo],
+        backend.dynamicType);
+
+    // 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(invariant(CURRENT_ELEMENT_SPANNABLE,
+        stack.last is HInvokeStatic || stack.last == newObject,
+        message: "Unexpected `stack.last`: Found ${stack.last}, "
+            "expected ${newObject} or an HInvokeStatic. "
+            "State: typeInfo=$typeInfo, stack=$stack."));
+    stack.last.instructionType = newObject.instructionType;
+    return pop();
+  }
+
   @override
   void visitWhileStatement(ir.WhileStatement whileStatement) {
     assert(isReachable);
@@ -500,6 +715,21 @@
     stack.add(graph.addConstantNull(compiler));
   }
 
+  HInstruction setRtiIfNeeded(HInstruction object, ir.ListLiteral listLiteral) {
+    InterfaceType type = localsHandler
+        .substInContext(elements.getType(astAdapter.getNode(listLiteral)));
+    if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
+      return object;
+    }
+    List<HInstruction> arguments = <HInstruction>[];
+    for (DartType argument in type.typeArguments) {
+      arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
+    }
+    // TODO(15489): Register at codegen.
+    registry?.registerInstantiation(type);
+    return callSetRuntimeTypeInfoWithTypeArguments(type, arguments, object);
+  }
+
   @override
   void visitListLiteral(ir.ListLiteral listLiteral) {
     HInstruction listInstruction;
@@ -514,7 +744,7 @@
       }
       listInstruction = new HLiteralList(elements, backend.extendableArrayType);
       add(listInstruction);
-      // TODO(het): set runtime type info
+      listInstruction = setRtiIfNeeded(listInstruction, listLiteral);
     }
 
     TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral);
@@ -591,8 +821,10 @@
           astAdapter.returnTypeOf(staticTarget));
       pop();
     } else {
-      // TODO(het): check or trust type
-      add(new HStaticStore(astAdapter.getMember(staticTarget), value));
+      add(new HStaticStore(
+          astAdapter.getMember(staticTarget),
+          typeBuilder.potentiallyCheckOrTrustType(
+              value, astAdapter.getDartType(staticTarget.setterType))));
     }
     stack.add(value);
   }
@@ -647,8 +879,10 @@
     }
 
     stack.add(value);
-    // TODO(het): check or trust type
-    localsHandler.updateLocal(local, value);
+    localsHandler.updateLocal(
+        local,
+        typeBuilder.potentiallyCheckOrTrustType(
+            value, astAdapter.getDartType(variable.type)));
   }
 
   // TODO(het): Also extract type arguments
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 5248f91..c882259 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2825,8 +2825,22 @@
 
     if (helper == null) {
       assert(type.isFunctionType);
-      use(node.inputs[0]);
+      assert(node.usesMethodOnType);
+
+      String name = node.isCastTypeCheck ? '_asCheck' : '_assertCheck';
+      HInstruction reifiedType = node.inputs[0];
+      HInstruction checkedInput = node.inputs[1];
+      use(reifiedType);
+      js.Expression receiver = pop();
+      use(checkedInput);
+      Selector selector = new Selector.call(
+          new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG);
+      registry.registerDynamicUse(
+          new DynamicUse(selector, reifiedType.instructionType));
+      js.Name methodLiteral = backend.namer.invocationName(selector);
+      push(js.js('#.#(#)', [receiver, methodLiteral, pop()]));
     } else {
+      assert(!node.usesMethodOnType);
       push(helper.generateCall(this, node));
     }
   }
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index c3e2bb6..34d156b 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -440,11 +440,18 @@
 
   void visitIs(HIs instruction) {
     // In the general case the input might be used multple multiple times, so it
-    // must not be set generate at use site.  If the code will generate
-    // 'instanceof' then we can generate at use site.
+    // must not be set generate at use site.
+
+    // If the code will generate 'instanceof' then we can generate at use site.
     if (instruction.useInstanceOf) {
       analyzeInputs(instruction, 0);
     }
+
+    // Compound and variable checks use a separate instruction to compute the
+    // result.
+    if (instruction.isCompoundCheck || instruction.isVariableCheck) {
+      analyzeInputs(instruction, 0);
+    }
   }
 
   // A bounds check method must not have its first input generated at use site,
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 22e6c30..e5dce33 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -2,17 +2,25 @@
 // 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 '../closure.dart';
+import '../common.dart';
+import '../common/codegen.dart' show CodegenRegistry;
 import '../compiler.dart';
+import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../io/source_information.dart';
 import '../js_backend/js_backend.dart';
 import '../resolution/tree_elements.dart';
 import '../tree/tree.dart' as ast;
 import '../types/types.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show TypeUse;
+import '../world.dart' show ClosedWorld;
 import 'jump_handler.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
 import 'ssa_branch_builder.dart';
+import 'type_builder.dart';
 
 /// Base class for objects that build up an SSA graph.
 ///
@@ -32,6 +40,8 @@
   /// The tree elements for the element being built into an SSA graph.
   TreeElements get elements;
 
+  CodegenRegistry get registry;
+
   /// Used to track the locals while building the graph.
   LocalsHandler localsHandler;
 
@@ -182,4 +192,143 @@
     if (expression == null) return null;
     return new HSubExpressionBlockInformation(expression);
   }
+
+  HInstruction buildFunctionType(FunctionType type) {
+    type.accept(
+        new ReifiedTypeRepresentationBuilder(compiler.closedWorld), this);
+    return pop();
+  }
+
+  HInstruction buildFunctionTypeConversion(
+      HInstruction original, DartType type, int kind);
+
+  /// Returns the current source element.
+  ///
+  /// The returned element is a declaration element.
+  Element get sourceElement;
+
+  // TODO(karlklose): this is needed to avoid a bug where the resolved type is
+  // not stored on a type annotation in the closure translator. Remove when
+  // fixed.
+  bool hasDirectLocal(Local local) {
+    return !localsHandler.isAccessedDirectly(local) ||
+        localsHandler.directLocals[local] != null;
+  }
+
+  HInstruction callSetRuntimeTypeInfoWithTypeArguments(
+      DartType type, List<HInstruction> rtiInputs, HInstruction newObject) {
+    if (!backend.classNeedsRti(type.element)) {
+      return newObject;
+    }
+
+    HInstruction typeInfo = new HTypeInfoExpression(
+        TypeInfoExpressionKind.INSTANCE,
+        (type.element as ClassElement).thisType,
+        rtiInputs,
+        backend.dynamicType);
+    add(typeInfo);
+    return callSetRuntimeTypeInfo(typeInfo, newObject);
+  }
+
+  HInstruction callSetRuntimeTypeInfo(
+      HInstruction typeInfo, HInstruction newObject);
+
+  /// The element for which this SSA builder is being used.
+  Element get targetElement;
+  TypeBuilder get typeBuilder;
+}
+
+class ReifiedTypeRepresentationBuilder
+    implements DartTypeVisitor<dynamic, GraphBuilder> {
+  final ClosedWorld closedWorld;
+
+  ReifiedTypeRepresentationBuilder(this.closedWorld);
+
+  void visit(DartType type, GraphBuilder builder) => type.accept(this, builder);
+
+  void visitVoidType(VoidType type, GraphBuilder builder) {
+    ClassElement cls = builder.backend.helpers.VoidRuntimeType;
+    builder.push(new HVoidType(type, new TypeMask.exact(cls, closedWorld)));
+  }
+
+  void visitTypeVariableType(TypeVariableType type, GraphBuilder builder) {
+    ClassElement cls = builder.backend.helpers.RuntimeType;
+    TypeMask instructionType = new TypeMask.subclass(cls, closedWorld);
+    if (!builder.sourceElement.enclosingElement.isClosure &&
+        builder.sourceElement.isInstanceMember) {
+      HInstruction receiver = builder.localsHandler.readThis();
+      builder.push(new HReadTypeVariable(type, receiver, instructionType));
+    } else {
+      builder.push(new HReadTypeVariable.noReceiver(
+          type,
+          builder.typeBuilder
+              .addTypeVariableReference(type, builder.sourceElement),
+          instructionType));
+    }
+  }
+
+  void visitFunctionType(FunctionType type, GraphBuilder builder) {
+    type.returnType.accept(this, builder);
+    HInstruction returnType = builder.pop();
+    List<HInstruction> inputs = <HInstruction>[returnType];
+
+    for (DartType parameter in type.parameterTypes) {
+      parameter.accept(this, builder);
+      inputs.add(builder.pop());
+    }
+
+    for (DartType parameter in type.optionalParameterTypes) {
+      parameter.accept(this, builder);
+      inputs.add(builder.pop());
+    }
+
+    List<DartType> namedParameterTypes = type.namedParameterTypes;
+    List<String> names = type.namedParameters;
+    for (int index = 0; index < names.length; index++) {
+      ast.DartString dartString = new ast.DartString.literal(names[index]);
+      inputs.add(builder.graph.addConstantString(dartString, builder.compiler));
+      namedParameterTypes[index].accept(this, builder);
+      inputs.add(builder.pop());
+    }
+
+    ClassElement cls = builder.backend.helpers.RuntimeFunctionType;
+    builder.push(
+        new HFunctionType(inputs, type, new TypeMask.exact(cls, closedWorld)));
+  }
+
+  void visitMalformedType(MalformedType type, GraphBuilder builder) {
+    visitDynamicType(const DynamicType(), builder);
+  }
+
+  void visitStatementType(StatementType type, GraphBuilder builder) {
+    throw 'not implemented visitStatementType($type)';
+  }
+
+  void visitInterfaceType(InterfaceType type, GraphBuilder builder) {
+    List<HInstruction> inputs = <HInstruction>[];
+    for (DartType typeArgument in type.typeArguments) {
+      typeArgument.accept(this, builder);
+      inputs.add(builder.pop());
+    }
+    ClassElement cls;
+    if (type.typeArguments.isEmpty) {
+      cls = builder.backend.helpers.RuntimeTypePlain;
+    } else {
+      cls = builder.backend.helpers.RuntimeTypeGeneric;
+    }
+    builder.push(
+        new HInterfaceType(inputs, type, new TypeMask.exact(cls, closedWorld)));
+  }
+
+  void visitTypedefType(TypedefType type, GraphBuilder builder) {
+    DartType unaliased = type.unaliased;
+    if (unaliased is TypedefType) throw 'unable to unalias $type';
+    unaliased.accept(this, builder);
+  }
+
+  void visitDynamicType(DynamicType type, GraphBuilder builder) {
+    JavaScriptBackend backend = builder.compiler.backend;
+    ClassElement cls = backend.helpers.DynamicRuntimeType;
+    builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld)));
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index 1ba818c..4db25e9 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -127,11 +127,19 @@
     return new CallStructure(argumentCount, namedArguments);
   }
 
+  FunctionSignature getFunctionSignature(ir.FunctionNode function) {
+    return getElement(function).asFunctionElement().functionSignature;
+  }
+
   Name getName(ir.Name name) {
     return new Name(
         name.name, name.isPrivate ? getElement(name.library) : null);
   }
 
+  ir.Field getFieldFromElement(FieldElement field) {
+    return kernel.fields[field];
+  }
+
   Selector getSelector(ir.Expression node) {
     if (node is ir.PropertyGet) return getGetterSelector(node);
     if (node is ir.InvocationExpression) return getInvocationSelector(node);
@@ -250,6 +258,8 @@
     return _backend.isInterceptedSelector(selector);
   }
 
+  LibraryElement get jsHelperLibrary => _backend.helpers.jsHelperLibrary;
+
   JumpTarget getTargetDefinition(ir.Node node) =>
       elements.getTargetDefinition(getNode(node));
 
@@ -282,9 +292,14 @@
   ir.Procedure get assertThrow =>
       kernel.functions[_backend.helpers.assertThrow];
 
+  ir.Procedure get setRuntimeTypeInfo =>
+      kernel.functions[_backend.helpers.setRuntimeTypeInfo];
+
   TypeMask get assertThrowReturnType => TypeMaskFactory
       .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler);
 
+  ir.Class get objectClass => kernel.classes[_compiler.coreClasses.objectClass];
+
   DartType getDartType(ir.DartType type) {
     return type.accept(_typeConverter);
   }
@@ -293,9 +308,13 @@
     return types.map(getDartType).toList();
   }
 
+  DartType getFunctionReturnType(ir.FunctionNode node) {
+    return getDartType(node.returnType);
+  }
+
   /// Computes the function type corresponding the signature of [node].
   FunctionType getFunctionType(ir.FunctionNode node) {
-    DartType returnType = getDartType(node.returnType);
+    DartType returnType = getFunctionReturnType(node);
     List<DartType> parameterTypes = <DartType>[];
     List<DartType> optionalParameterTypes = <DartType>[];
     for (ir.VariableDeclaration variable in node.positionalParameters) {
@@ -332,7 +351,6 @@
   }
 
   /// Compute the kind of foreign helper function called by [node], if any.
-  @override
   ForeignKind getForeignKind(ir.StaticInvocation node) {
     if (isForeignLibrary(node.target.enclosingLibrary)) {
       switch (node.target.name.name) {
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index f2d1af7..712ff29 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -2801,23 +2801,29 @@
 }
 
 class HTypeConversion extends HCheck {
-  final DartType typeExpression;
-  final int kind;
-  final Selector receiverTypeCheckSelector;
-  final bool contextIsTypeArguments;
-  TypeMask checkedType; // Not final because we refine it.
-
+  // Values for [kind].
   static const int CHECKED_MODE_CHECK = 0;
   static const int ARGUMENT_TYPE_CHECK = 1;
   static const int CAST_TYPE_CHECK = 2;
   static const int BOOLEAN_CONVERSION_CHECK = 3;
   static const int RECEIVER_TYPE_CHECK = 4;
 
+  final DartType typeExpression;
+  final int kind;
+  // [receiverTypeCheckSelector] is the selector used for a receiver type check
+  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
+  // compiled to the following, for which we need the selector `$add`.
+  //
+  //     if (typeof x != "number") x.$add();
+  //
+  final Selector receiverTypeCheckSelector;
+
+  TypeMask checkedType; // Not final because we refine it.
+
   HTypeConversion(
       this.typeExpression, this.kind, TypeMask type, HInstruction input,
-      [this.receiverTypeCheckSelector])
-      : contextIsTypeArguments = false,
-        checkedType = type,
+      {this.receiverTypeCheckSelector})
+      : checkedType = type,
         super(<HInstruction>[input], type) {
     assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
     assert(typeExpression == null || typeExpression.kind != TypeKind.TYPEDEF);
@@ -2826,21 +2832,21 @@
 
   HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
       TypeMask type, HInstruction input, HInstruction typeRepresentation)
-      : contextIsTypeArguments = false,
-        checkedType = type,
+      : checkedType = type,
         super(<HInstruction>[input, typeRepresentation], type),
         receiverTypeCheckSelector = null {
     assert(typeExpression.kind != TypeKind.TYPEDEF);
     sourceElement = input.sourceElement;
   }
 
-  HTypeConversion.withContext(this.typeExpression, this.kind, TypeMask type,
-      HInstruction input, HInstruction context,
-      {bool this.contextIsTypeArguments})
-      : super(<HInstruction>[input, context], type),
-        checkedType = type,
+  HTypeConversion.viaMethodOnType(this.typeExpression, this.kind, TypeMask type,
+      HInstruction reifiedType, HInstruction input)
+      : checkedType = type,
+        super(<HInstruction>[reifiedType, input], type),
         receiverTypeCheckSelector = null {
-    assert(typeExpression.kind != TypeKind.TYPEDEF);
+    // This form is currently used only for function types.
+    assert(typeExpression.isFunctionType);
+    assert(kind == CHECKED_MODE_CHECK || kind == CAST_TYPE_CHECK);
     sourceElement = input.sourceElement;
   }
 
@@ -2850,11 +2856,11 @@
 
   HInstruction get typeRepresentation => inputs[1];
 
-  bool get hasContext {
-    return typeExpression.isFunctionType && inputs.length > 1;
-  }
+  bool get usesMethodOnType =>
+      typeExpression != null && typeExpression.isFunctionType;
 
-  HInstruction get context => inputs[1];
+  HInstruction get checkedInput =>
+      usesMethodOnType ? inputs[1] : super.checkedInput;
 
   HInstruction convertType(Compiler compiler, DartType type, int kind) {
     if (typeExpression == type) {
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 507c459..5f11f1d 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -800,11 +800,25 @@
         // throw a type error at runtime.
         return node;
       }
-      if (!type.treatAsRaw || type.isTypeVariable) {
+      if (type.isTypeVariable) {
+        return node;
+      }
+      if (!type.treatAsRaw) {
+        HInstruction input = node.checkedInput;
+        // `null` always passes type conversion.
+        if (input.isNull()) return input;
+        // TODO(sra): We can statically check [input] if it is a constructor.
+        // TODO(sra): We can statically check [input] if it is load from a field
+        // of the same ground type, or load from a field of a parameterized type
+        // with the same receiver.
         return node;
       }
       if (type.isFunctionType) {
+        HInstruction input = node.checkedInput; 
+        // `null` always passes type conversion.
+        if (input.isNull()) return input;
         // TODO(johnniwinther): Optimize function type conversions.
+        // TODO(sra): We can statically check [input] if it is a closure getter.
         return node;
       }
     }
@@ -944,15 +958,18 @@
     FieldElement field =
         findConcreteFieldForDynamicAccess(receiver, node.selector);
     if (field == null || !field.isAssignable) return node;
-    // Use [:node.inputs.last:] in case the call follows the
-    // interceptor calling convention, but is not a call on an
-    // interceptor.
+    // Use `node.inputs.last` in case the call follows the interceptor calling
+    // convention, but is not a call on an interceptor.
     HInstruction value = node.inputs.last;
     if (compiler.options.enableTypeAssertions) {
       DartType type = field.type;
-      if (!type.treatAsRaw || type.isTypeVariable) {
+      if (!type.treatAsRaw ||
+          type.isTypeVariable ||
+          type.unaliased.isFunctionType) {
         // We cannot generate the correct type representation here, so don't
         // inline this access.
+        // TODO(sra): If the input is such that we don't need a type check, we
+        // can skip the test an generate the HFieldSet.
         return node;
       }
       HInstruction other =
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 1768db1..6c1d543 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -334,9 +334,11 @@
     return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs);
   }
 
-  String visitForeignCode(HForeignCode foreign) {
-    return handleGenericInvoke(
-        "ForeignCode", "${foreign.codeTemplate.ast}", foreign.inputs);
+  String visitForeignCode(HForeignCode node) {
+    var template = node.codeTemplate;
+    String code = '${template.ast}';
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "ForeignCode: $code ($inputs)";
   }
 
   String visitLess(HLess node) => handleInvokeBinary(node, 'Less');
@@ -482,11 +484,19 @@
   }
 
   String visitTypeConversion(HTypeConversion node) {
-    assert(node.inputs.length <= 2);
-    String otherInput =
-        (node.inputs.length == 2) ? temporaryId(node.inputs[1]) : '';
-    return "TypeConversion: ${temporaryId(node.checkedInput)} to "
-        "${node.instructionType} $otherInput";
+    String checkedInput = temporaryId(node.checkedInput);
+    String rest;
+    if (node.usesMethodOnType) {
+      assert(node.inputs.length == 2);
+      assert(identical(node.checkedInput, node.inputs.last));
+      rest = " ${temporaryId(node.inputs.first)}";
+    } else if (node.inputs.length == 2) {
+      rest = " ${temporaryId(node.inputs.last)}";
+    } else {
+      assert(node.inputs.length == 1);
+      rest = "";
+    }
+    return "TypeConversion: $checkedInput to ${node.instructionType}$rest";
   }
 
   String visitTypeKnown(HTypeKnown node) {
@@ -504,23 +514,29 @@
   }
 
   String visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
-    return "TypeInfoReadRaw";
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "TypeInfoReadRaw: $inputs";
   }
 
   String visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
-    return "TypeInfoReadVariable ${node.variable}";
+    return "TypeInfoReadVariable: "
+        "${temporaryId(node.inputs.single)}.${node.variable}";
   }
 
   String visitTypeInfoExpression(HTypeInfoExpression node) {
-    return "TypeInfoExpression ${node.kindAsString} ${node.dartType}";
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "TypeInfoExpression: ${node.kindAsString} ${node.dartType}"
+        " ($inputs)";
   }
 
   String visitReadTypeVariable(HReadTypeVariable node) {
-    return "ReadTypeVariable: ${node.dartType} ${node.hasReceiver}";
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "ReadTypeVariable: ${node.dartType} ${node.hasReceiver} $inputs";
   }
 
   String visitFunctionType(HFunctionType node) {
-    return "FunctionType: ${node.dartType}";
+    var inputs = node.inputs.map(temporaryId).join(', ');
+    return "FunctionType: ${node.dartType} $inputs";
   }
 
   String visitVoidType(HVoidType node) {
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
new file mode 100644
index 0000000..605678b
--- /dev/null
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -0,0 +1,252 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'graph_builder.dart';
+import 'nodes.dart';
+import '../closure.dart';
+import '../common.dart';
+import '../dart_types.dart';
+import '../types/types.dart';
+import '../elements/elements.dart';
+import '../io/source_information.dart';
+import '../universe/selector.dart' show Selector;
+import '../universe/use.dart' show TypeUse;
+
+/// Functions to insert type checking, coercion, and instruction insertion
+/// depending on the environment for dart code.
+class TypeBuilder {
+  final GraphBuilder builder;
+  TypeBuilder(this.builder);
+
+  /// Create an instruction to simply trust the provided type.
+  HInstruction _trustType(HInstruction original, DartType type) {
+    assert(builder.compiler.options.trustTypeAnnotations);
+    assert(type != null);
+    type = builder.localsHandler.substInContext(type);
+    type = type.unaliased;
+    if (type.isDynamic) return original;
+    if (!type.isInterfaceType) return original;
+    if (type.isObject) return original;
+    // The type element is either a class or the void element.
+    Element element = type.element;
+    TypeMask mask = new TypeMask.subtype(element, builder.compiler.closedWorld);
+    return new HTypeKnown.pinned(mask, original);
+  }
+
+  /// Produces code that checks the runtime type is actually the type specified
+  /// by attempting a type conversion.
+  HInstruction _checkType(HInstruction original, DartType type, int kind) {
+    assert(builder.compiler.options.enableTypeAssertions);
+    assert(type != null);
+    type = builder.localsHandler.substInContext(type);
+    HInstruction other = buildTypeConversion(original, type, kind);
+    // TODO(johnniwinther): This operation on `registry` may be inconsistent.
+    // If it is needed then it seems likely that similar invocations of
+    // `buildTypeConversion` in `SsaBuilder.visitAs` should also be followed by
+    // a similar operation on `registry`; otherwise, this one might not be
+    // needed.
+    builder.registry?.registerTypeUse(new TypeUse.isCheck(type));
+    return other;
+  }
+
+  /// Depending on the context and the mode, wrap the given type in an
+  /// instruction that checks the type is what we expect or automatically
+  /// trusts the written type.
+  HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type,
+      {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
+    if (type == null) return original;
+    HInstruction checkedOrTrusted = original;
+    if (builder.compiler.options.trustTypeAnnotations) {
+      checkedOrTrusted = _trustType(original, type);
+    } else if (builder.compiler.options.enableTypeAssertions) {
+      checkedOrTrusted = _checkType(original, type, kind);
+    }
+    if (checkedOrTrusted == original) return original;
+    builder.add(checkedOrTrusted);
+    return checkedOrTrusted;
+  }
+
+  /// Helper to create an instruction that gets the value of a type variable.
+  HInstruction addTypeVariableReference(TypeVariableType type, Element member,
+      {SourceInformation sourceInformation}) {
+    assert(assertTypeInContext(type));
+    if (type is MethodTypeVariableType) {
+      return builder.graph.addConstantNull(builder.compiler);
+    }
+    bool isClosure = member.enclosingElement.isClosure;
+    if (isClosure) {
+      ClosureClassElement closureClass = member.enclosingElement;
+      member = closureClass.methodElement;
+      member = member.outermostEnclosingMemberOrTopLevel;
+    }
+    bool isInConstructorContext =
+        member.isConstructor || member.isGenerativeConstructorBody;
+    Local typeVariableLocal =
+        builder.localsHandler.getTypeVariableAsLocal(type);
+    if (isClosure) {
+      if (member.isFactoryConstructor ||
+          (isInConstructorContext &&
+              builder.hasDirectLocal(typeVariableLocal))) {
+        // The type variable is used from a closure in a factory constructor.
+        // The value of the type argument is stored as a local on the closure
+        // itself.
+        return builder.localsHandler
+            .readLocal(typeVariableLocal, sourceInformation: sourceInformation);
+      } else if (member.isFunction ||
+          member.isGetter ||
+          member.isSetter ||
+          isInConstructorContext) {
+        // The type variable is stored on the "enclosing object" and needs to be
+        // accessed using the this-reference in the closure.
+        return readTypeVariable(type, member,
+            sourceInformation: sourceInformation);
+      } else {
+        assert(member.isField);
+        // The type variable is stored in a parameter of the method.
+        return builder.localsHandler.readLocal(typeVariableLocal);
+      }
+    } else if (isInConstructorContext ||
+        // When [member] is a field, we can be either
+        // generating a checked setter or inlining its
+        // initializer in a constructor. An initializer is
+        // never built standalone, so in that case [target] is not
+        // the [member] itself.
+        (member.isField && member != builder.targetElement)) {
+      // The type variable is stored in a parameter of the method.
+      return builder.localsHandler
+          .readLocal(typeVariableLocal, sourceInformation: sourceInformation);
+    } else if (member.isInstanceMember) {
+      // The type variable is stored on the object.
+      return readTypeVariable(type, member,
+          sourceInformation: sourceInformation);
+    } else {
+      builder.compiler.reporter.internalError(
+          type.element, 'Unexpected type variable in static context.');
+      return null;
+    }
+  }
+
+  /// Generate code to extract the type argument from the object.
+  HInstruction readTypeVariable(TypeVariableType variable, Element member,
+      {SourceInformation sourceInformation}) {
+    assert(member.isInstanceMember);
+    assert(variable is! MethodTypeVariableType);
+    HInstruction target = builder.localsHandler.readThis();
+    builder.push(
+        new HTypeInfoReadVariable(variable, target, builder.backend.dynamicType)
+          ..sourceInformation = sourceInformation);
+    return builder.pop();
+  }
+
+  HInstruction buildTypeArgumentRepresentations(
+      DartType type, Element sourceElement) {
+    assert(!type.isTypeVariable);
+    // Compute the representation of the type arguments, including access
+    // to the runtime type information for type variables as instructions.
+    assert(type.element.isClass);
+    InterfaceType interface = type;
+    List<HInstruction> inputs = <HInstruction>[];
+    for (DartType argument in interface.typeArguments) {
+      inputs.add(analyzeTypeArgument(argument, sourceElement));
+    }
+    HInstruction representation = new HTypeInfoExpression(
+        TypeInfoExpressionKind.INSTANCE,
+        interface.element.thisType,
+        inputs,
+        builder.backend.dynamicType);
+    return representation;
+  }
+
+  /// Check that [type] is valid in the context of `localsHandler.contextClass`.
+  /// This should only be called in assertions.
+  bool assertTypeInContext(DartType type, [Spannable spannable]) {
+    return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable,
+        () {
+      ClassElement contextClass = Types.getClassContext(type);
+      return contextClass == null ||
+          contextClass == builder.localsHandler.contextClass;
+    },
+        message: "Type '$type' is not valid context of "
+            "${builder.localsHandler.contextClass}.");
+  }
+
+  HInstruction analyzeTypeArgument(DartType argument, Element sourceElement,
+      {SourceInformation sourceInformation}) {
+    assert(assertTypeInContext(argument));
+    argument = argument.unaliased;
+    if (argument.treatAsDynamic) {
+      // Represent [dynamic] as [null].
+      return builder.graph.addConstantNull(builder.compiler);
+    }
+
+    if (argument.isTypeVariable) {
+      return addTypeVariableReference(argument, sourceElement,
+          sourceInformation: sourceInformation);
+    }
+
+    List<HInstruction> inputs = <HInstruction>[];
+    argument.forEachTypeVariable((variable) {
+      if (variable is! MethodTypeVariableType) {
+        inputs.add(analyzeTypeArgument(variable, sourceElement));
+      }
+    });
+    HInstruction result = new HTypeInfoExpression(
+        TypeInfoExpressionKind.COMPLETE,
+        argument,
+        inputs,
+        builder.backend.dynamicType)..sourceInformation = sourceInformation;
+    builder.add(result);
+    return result;
+  }
+
+  /// In checked mode, generate type tests for the parameters of the inlined
+  /// function.
+  void potentiallyCheckInlinedParameterTypes(FunctionElement function) {
+    if (!checkOrTrustTypes) return;
+
+    FunctionSignature signature = function.functionSignature;
+    signature.orderedForEachParameter((ParameterElement parameter) {
+      HInstruction argument = builder.localsHandler.readLocal(parameter);
+      potentiallyCheckOrTrustType(argument, parameter.type);
+    });
+  }
+
+  bool get checkOrTrustTypes =>
+      builder.compiler.options.enableTypeAssertions ||
+      builder.compiler.options.trustTypeAnnotations;
+
+  /// Build a [HTypeConversion] for converting [original] to type [type].
+  ///
+  /// Invariant: [type] must be valid in the context.
+  /// See [LocalsHandler.substInContext].
+  HInstruction buildTypeConversion(
+      HInstruction original, DartType type, int kind) {
+    if (type == null) return original;
+    // GENERIC_METHODS: The following statement was added for parsing and
+    // ignoring method type variables; must be generalized for full support of
+    // generic methods.
+    type = type.dynamifyMethodTypeVariableType;
+    type = type.unaliased;
+    assert(assertTypeInContext(type, original));
+    if (type.isInterfaceType && !type.treatAsRaw) {
+      TypeMask subtype =
+          new TypeMask.subtype(type.element, builder.compiler.closedWorld);
+      HInstruction representations =
+          buildTypeArgumentRepresentations(type, builder.sourceElement);
+      builder.add(representations);
+      return new HTypeConversion.withTypeRepresentation(
+          type, kind, subtype, original, representations);
+    } else if (type.isTypeVariable) {
+      TypeMask subtype = original.instructionType;
+      HInstruction typeVariable =
+          addTypeVariableReference(type, builder.sourceElement);
+      return new HTypeConversion.withTypeRepresentation(
+          type, kind, subtype, original, typeVariable);
+    } else if (type.isFunctionType) {
+      return builder.buildFunctionTypeConversion(original, type, kind);
+    } else {
+      return original.convertType(builder.compiler, type, kind);
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 5a94e8d..63da628 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -233,9 +233,9 @@
     Selector selector = (kind == HTypeConversion.RECEIVER_TYPE_CHECK)
         ? instruction.selector
         : null;
-    HTypeConversion converted =
-        new HTypeConversion(null, kind, type, input, selector)
-          ..sourceInformation = instruction.sourceInformation;
+    HTypeConversion converted = new HTypeConversion(null, kind, type, input,
+        receiverTypeCheckSelector: selector)
+      ..sourceInformation = instruction.sourceInformation;
     instruction.block.addBefore(instruction, converted);
     input.replaceAllUsersDominatedBy(instruction, converted);
   }
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index 1885e0d..ff36cfe 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -594,7 +594,7 @@
   final Node selector;
   final NodeList argumentsNode;
 
-  /// Whether this is a conditinal send of the form `a?.b`.
+  /// Whether this is a conditional send of the form `a?.b`.
   final bool isConditional;
 
   Link<Node> get arguments => argumentsNode.nodes;
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index c078298..d2831c0 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -251,8 +251,8 @@
       typesInferrerInternal ??= new TypeGraphInferrer(compiler, masks);
       typesInferrerInternal.analyzeMain(mainElement);
       typesInferrerInternal.clear();
-      results = new GlobalTypeInferenceResults(
-          typesInferrerInternal, compiler, masks, typesInferrerInternal.inferrer.types);
+      results = new GlobalTypeInferenceResults(typesInferrerInternal, compiler,
+          masks, typesInferrerInternal.inferrer.types);
     });
   }
 }
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 39937fb..bc959c1 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -218,12 +218,12 @@
   }
 
   bool appliesUnnamed(Element element) {
-    assert(sameNameHack(element));
+    assert(name == element.name);
     return appliesUntyped(element);
   }
 
   bool appliesUntyped(Element element) {
-    assert(sameNameHack(element));
+    assert(name == element.name);
     if (Elements.isUnresolved(element)) return false;
     if (memberName.isPrivate && memberName.library != element.library) {
       // TODO(johnniwinther): Maybe this should be
@@ -247,13 +247,8 @@
     return callStructure.signatureApplies(function.functionSignature);
   }
 
-  bool sameNameHack(Element element) {
-    // TODO(ngeoffray): Remove workaround checks.
-    return element.isConstructor || name == element.name;
-  }
-
   bool applies(Element element) {
-    if (!sameNameHack(element)) return false;
+    if (name != element.name) return false;
     return appliesUnnamed(element);
   }
 
diff --git a/pkg/dev_compiler/USAGE.md b/pkg/dev_compiler/USAGE.md
index 77c2a69..9a3de65 100644
--- a/pkg/dev_compiler/USAGE.md
+++ b/pkg/dev_compiler/USAGE.md
@@ -73,7 +73,7 @@
 
 ## Feedback
 
-Please file issues in our [GitHub issue tracker](https://github.com/dart-lang/dev_compiler/issues).
+Please file issues in our [GitHub issue tracker](https://github.com/dart-lang/sdk/issues).
 
 You can also view or join our [mailing list](https://groups.google.com/a/dartlang.org/forum/#!forum/dev-compiler).
 
diff --git a/pkg/dev_compiler/codereview.settings b/pkg/dev_compiler/codereview.settings
index 1c7f5d4..491e3d8 100644
--- a/pkg/dev_compiler/codereview.settings
+++ b/pkg/dev_compiler/codereview.settings
@@ -1,3 +1,3 @@
 CODE_REVIEW_SERVER: https://codereview.chromium.org
-VIEW_VC: https://github.com/dart-lang/dev_compiler/commit/
+VIEW_VC: https://github.com/dart-lang/sdk/commit/
 CC_LIST: dev-compiler+reviews@dartlang.org
diff --git a/pkg/dev_compiler/lib/js/amd/dart_sdk.js b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
index 8d7c71e..c2cb697 100644
--- a/pkg/dev_compiler/lib/js/amd/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
@@ -36890,7 +36890,7 @@
       let args = Array.prototype.map.call(arguments, js._convertToDart);
       return js._convertToJS(f(...args));
     };
-    dart.dsetindex(js._dartProxies, wrapper, f);
+    js._dartProxies.set(wrapper, f);
     return wrapper;
   };
   dart.fn(js._wrapDartFunction, dynamicTodynamic$());
@@ -83133,15 +83133,6 @@
       sanitizeNode: dart.definiteFunctionType(dart.void, [html$.Node, html$.Node])
     })
   });
-  html$.Point$ = math.Point$;
-  html$.Point = math.Point;
-  html$.Rectangle$ = math.Rectangle$;
-  html$.Rectangle = math.Rectangle;
-  html_common.SupportedBrowser = _metadata.SupportedBrowser;
-  html_common.Unstable = _metadata.Unstable;
-  html_common.DocsEditable = _metadata.DocsEditable;
-  html_common.Experimental = _metadata.Experimental;
-  html_common.DomName = _metadata.DomName;
   html_common.convertDartToNative_SerializedScriptValue = function(value) {
     return html_common.convertDartToNative_PrepareForStructuredClone(value);
   };
diff --git a/pkg/dev_compiler/lib/js/common/dart_sdk.js b/pkg/dev_compiler/lib/js/common/dart_sdk.js
index f5370bd..78f09d2 100644
--- a/pkg/dev_compiler/lib/js/common/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/common/dart_sdk.js
@@ -36890,7 +36890,7 @@
       let args = Array.prototype.map.call(arguments, js._convertToDart);
       return js._convertToJS(f(...args));
     };
-    dart.dsetindex(js._dartProxies, wrapper, f);
+    js._dartProxies.set(wrapper, f);
     return wrapper;
   };
   dart.fn(js._wrapDartFunction, dynamicTodynamic$());
@@ -83133,15 +83133,6 @@
       sanitizeNode: dart.definiteFunctionType(dart.void, [html$.Node, html$.Node])
     })
   });
-  html$.Point$ = math.Point$;
-  html$.Point = math.Point;
-  html$.Rectangle$ = math.Rectangle$;
-  html$.Rectangle = math.Rectangle;
-  html_common.SupportedBrowser = _metadata.SupportedBrowser;
-  html_common.Unstable = _metadata.Unstable;
-  html_common.DocsEditable = _metadata.DocsEditable;
-  html_common.Experimental = _metadata.Experimental;
-  html_common.DomName = _metadata.DomName;
   html_common.convertDartToNative_SerializedScriptValue = function(value) {
     return html_common.convertDartToNative_PrepareForStructuredClone(value);
   };
diff --git a/pkg/dev_compiler/lib/js/es6/dart_sdk.js b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
index 44083b7..c16638f 100644
--- a/pkg/dev_compiler/lib/js/es6/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
@@ -36888,7 +36888,7 @@
     let args = Array.prototype.map.call(arguments, js._convertToDart);
     return js._convertToJS(f(...args));
   };
-  dart.dsetindex(js._dartProxies, wrapper, f);
+  js._dartProxies.set(wrapper, f);
   return wrapper;
 };
 dart.fn(js._wrapDartFunction, dynamicTodynamic());
@@ -83131,15 +83131,6 @@
     sanitizeNode: dart.definiteFunctionType(dart.void, [html.Node, html.Node])
   })
 });
-html.Point$ = math.Point$;
-html.Point = math.Point;
-html.Rectangle$ = math.Rectangle$;
-html.Rectangle = math.Rectangle;
-html_common.SupportedBrowser = _metadata.SupportedBrowser;
-html_common.Unstable = _metadata.Unstable;
-html_common.DocsEditable = _metadata.DocsEditable;
-html_common.Experimental = _metadata.Experimental;
-html_common.DomName = _metadata.DomName;
 html_common.convertDartToNative_SerializedScriptValue = function(value) {
   return html_common.convertDartToNative_PrepareForStructuredClone(value);
 };
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
index 4f8489f..2312c34 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
@@ -36891,7 +36891,7 @@
       let args = Array.prototype.map.call(arguments, js._convertToDart);
       return js._convertToJS(f(...args));
     };
-    dart.dsetindex(js._dartProxies, wrapper, f);
+    js._dartProxies.set(wrapper, f);
     return wrapper;
   };
   dart.fn(js._wrapDartFunction, dynamicTodynamic$());
@@ -83134,15 +83134,6 @@
       sanitizeNode: dart.definiteFunctionType(dart.void, [html$.Node, html$.Node])
     })
   });
-  html$.Point$ = math.Point$;
-  html$.Point = math.Point;
-  html$.Rectangle$ = math.Rectangle$;
-  html$.Rectangle = math.Rectangle;
-  html_common.SupportedBrowser = _metadata.SupportedBrowser;
-  html_common.Unstable = _metadata.Unstable;
-  html_common.DocsEditable = _metadata.DocsEditable;
-  html_common.Experimental = _metadata.Experimental;
-  html_common.DomName = _metadata.DomName;
   html_common.convertDartToNative_SerializedScriptValue = function(value) {
     return html_common.convertDartToNative_PrepareForStructuredClone(value);
   };
diff --git a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
index 80408b8..79fff65 100644
--- a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
+++ b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
Binary files differ
diff --git a/pkg/dev_compiler/lib/src/analyzer/context.dart b/pkg/dev_compiler/lib/src/analyzer/context.dart
index 209c2fe..5617f7f 100644
--- a/pkg/dev_compiler/lib/src/analyzer/context.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/context.dart
@@ -46,16 +46,21 @@
   /// of the unsummarized one.
   final String dartSdkSummaryPath;
 
+  /// Defined variables used by `bool.fromEnvironment` etc.
+  final Map<String, String> declaredVariables;
+
   AnalyzerOptions(
       {this.summaryPaths: const [],
       String dartSdkPath,
       this.dartSdkSummaryPath,
       this.customUrlMappings: const {},
       this.packageRoot: null,
-      this.packagePaths: const []})
+      this.packagePaths: const [],
+      this.declaredVariables: const {}})
       : dartSdkPath = dartSdkPath ?? getSdkDir().path;
 
-  factory AnalyzerOptions.fromArguments(ArgResults args) {
+  factory AnalyzerOptions.fromArguments(
+      ArgResults args, Map<String, String> declaredVariables) {
     var sdkPath = args['dart-sdk'] ?? getSdkDir().path;
     var sdkSummaryPath = args['dart-sdk-summary'];
 
@@ -72,7 +77,8 @@
         dartSdkSummaryPath: sdkSummaryPath,
         customUrlMappings: _parseUrlMappings(args['url-mapping']),
         packageRoot: args['package-root'],
-        packagePaths: (args['package-paths'] as String)?.split(',') ?? []);
+        packagePaths: (args['package-paths'] as String)?.split(',') ?? [],
+        declaredVariables: declaredVariables);
   }
 
   /// Whether to resolve 'package:' uris using the multi-package resolver.
@@ -186,3 +192,25 @@
       : _createFolderBasedDartSdk(sdkPath);
   return new DartUriResolver(sdk);
 }
+
+List<String> parseDeclaredVariables(
+    List<String> args, Map<String, String> declaredVars) {
+  var count = args.length;
+  var remainingArgs = <String>[];
+  for (int i = 0; i < count; i++) {
+    var arg = args[i];
+    if (arg == '--') {
+      while (i < count) {
+        remainingArgs.add(args[i++]);
+      }
+    } else if (arg.startsWith("-D")) {
+      // The format for defined variables is:
+      //     -D<name>=<value>
+      var parts = arg.substring(2).split('=');
+      declaredVars[parts[0]] = parts.length > 1 ? parts[1] : '';
+    } else {
+      remainingArgs.add(arg);
+    }
+  }
+  return remainingArgs;
+}
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
index 98afa9f..231fcb9 100644
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
@@ -125,7 +125,7 @@
   final ClassElement objectClass;
   final ClassElement stringClass;
 
-  ConstFieldVisitor _constField;
+  ConstFieldVisitor _constants;
 
   /// The current function body being compiled.
   FunctionBody _currentFunction;
@@ -276,7 +276,7 @@
     }
     _loader = new ElementLoader(nodes);
     if (compilationUnits.isNotEmpty) {
-      _constField = new ConstFieldVisitor(types,
+      _constants = new ConstFieldVisitor(context,
           dummySource: compilationUnits.first.element.source);
     }
 
@@ -517,35 +517,32 @@
         // modules we import, so we will never go down this code path for them.
         _moduleItems
             .add(js.statement('#.# = #;', [libraryName, name.selector, name]));
-      } else {
-        // top-level fields, getters, setters need to copy the property
-        // descriptor.
-        _moduleItems.add(_callHelperStatement(
-            'export(#, #, #);', [libraryName, name.receiver, name.selector]));
       }
     }
 
-    for (var export in exportedNames.definedNames.values) {
-      if (export is PropertyAccessorElement) {
-        export = (export as PropertyAccessorElement).variable;
-      }
+    // We only need to export main as it is the only method party of the
+    // publicly exposed JS API for a library.
+    // TODO(jacobr): add a library level annotation indicating that all
+    // contents of a library need to be exposed to JS.
+    // https://github.com/dart-lang/sdk/issues/26368
 
-      // Don't allow redefining names from this library.
-      if (currentNames.containsKey(export.name)) continue;
+    var export = exportedNames.get('main');
 
-      if (export.isSynthetic && export is PropertyInducingElement) {
-        _emitDeclaration(export.getter);
-        _emitDeclaration(export.setter);
-      } else {
-        _emitDeclaration(export);
-      }
-      if (export is ClassElement && export.typeParameters.isNotEmpty) {
-        // Export the generic name as well.
-        // TODO(jmesserly): revisit generic classes
-        emitExport(export, suffix: r'$');
-      }
-      emitExport(export);
+    if (export == null) return;
+    if (export is PropertyAccessorElement) {
+      export = (export as PropertyAccessorElement).variable;
     }
+
+    // Don't allow redefining names from this library.
+    if (currentNames.containsKey(export.name)) return;
+
+    if (export.isSynthetic && export is PropertyInducingElement) {
+      _emitDeclaration(export.getter);
+      _emitDeclaration(export.setter);
+    } else {
+      _emitDeclaration(export);
+    }
+    emitExport(export);
   }
 
   @override
@@ -2120,7 +2117,7 @@
     for (var declaration in fieldDecls) {
       for (var fieldNode in declaration.fields.variables) {
         var element = fieldNode.element;
-        if (_constField.isFieldInitConstant(fieldNode)) {
+        if (_constants.isFieldInitConstant(fieldNode)) {
           unsetFields[element as FieldElement] = fieldNode;
         } else {
           fields[element as FieldElement] = _visitInitializer(fieldNode);
@@ -3767,7 +3764,7 @@
     bool isLoaded = _loader.finishCheckingReferences();
 
     bool eagerInit =
-        isLoaded && (field.isConst || _constField.isFieldInitConstant(field));
+        isLoaded && (field.isConst || _constants.isFieldInitConstant(field));
 
     var fieldName = field.name.name;
     if (eagerInit &&
@@ -3796,7 +3793,7 @@
 
     bool eagerInit;
     JS.Expression jsInit;
-    if (field.isConst || _constField.isFieldInitConstant(field)) {
+    if (field.isConst || _constants.isFieldInitConstant(field)) {
       // If the field is constant, try and generate it at the top level.
       _loader.startTopLevel(element);
       jsInit = _visitInitializer(field);
@@ -3961,6 +3958,41 @@
     var constructor = node.constructorName;
     var name = constructor.name;
     var type = constructor.type.type;
+    if (node.isConst &&
+        element?.name == 'fromEnvironment' &&
+        element.library.isDartCore) {
+      var value = node.accept(_constants.constantVisitor);
+
+      if (value == null || value.isNull) {
+        return new JS.LiteralNull();
+      }
+      // Handle unknown value: when the declared variable wasn't found, and no
+      // explicit default value was passed either.
+      // TODO(jmesserly): ideally Analyzer would simply resolve this to the
+      // default value that is specified in the SDK. Instead we implement that
+      // here. `bool.fromEnvironment` defaults to `false`, the others to `null`:
+      // https://api.dartlang.org/stable/1.20.1/dart-core/bool/bool.fromEnvironment.html
+      if (value.isUnknown) {
+        return type == types.boolType
+            ? js.boolean(false)
+            : new JS.LiteralNull();
+      }
+      if (value.type == types.boolType) {
+        var boolValue = value.toBoolValue();
+        return boolValue != null ? js.boolean(boolValue) : new JS.LiteralNull();
+      }
+      if (value.type == types.intType) {
+        var intValue = value.toIntValue();
+        return intValue != null ? js.number(intValue) : new JS.LiteralNull();
+      }
+      if (value.type == types.stringType) {
+        var stringValue = value.toStringValue();
+        return stringValue != null
+            ? js.escapedString(stringValue)
+            : new JS.LiteralNull();
+      }
+      throw new StateError('failed to evaluate $node');
+    }
     return _emitInstanceCreationExpression(
         element, type, name, node.argumentList, node.isConst);
   }
diff --git a/pkg/dev_compiler/lib/src/compiler/command.dart b/pkg/dev_compiler/lib/src/compiler/command.dart
index 7d5e212..221e7d4 100644
--- a/pkg/dev_compiler/lib/src/compiler/command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/command.dart
@@ -10,7 +10,7 @@
 import 'package:args/command_runner.dart' show UsageException;
 import 'package:path/path.dart' as path;
 
-import '../analyzer/context.dart' show AnalyzerOptions;
+import '../analyzer/context.dart' show AnalyzerOptions, parseDeclaredVariables;
 import 'compiler.dart' show BuildUnit, CompilerOptions, ModuleCompiler;
 import 'module_builder.dart';
 
@@ -41,14 +41,15 @@
 int compile(List<String> args, {void printFn(Object obj)}) {
   printFn ??= print;
   ArgResults argResults;
+  var declaredVars = <String, String>{};
   try {
-    argResults = _argParser.parse(args);
+    argResults = _argParser.parse(parseDeclaredVariables(args, declaredVars));
   } on FormatException catch (error) {
     printFn('$error\n\n$_usageMessage');
     return 64;
   }
   try {
-    _compile(argResults, printFn);
+    _compile(argResults, declaredVars, printFn);
     return 0;
   } on UsageException catch (error) {
     // Incorrect usage, input file not found, etc.
@@ -90,13 +91,14 @@
   return false;
 }
 
-void _compile(ArgResults argResults, void printFn(Object obj)) {
+void _compile(ArgResults argResults, Map<String, String> declaredVars,
+    void printFn(Object obj)) {
   if (argResults['help']) {
     printFn(_usageMessage);
     return;
   }
-  var compiler =
-      new ModuleCompiler(new AnalyzerOptions.fromArguments(argResults));
+  var compiler = new ModuleCompiler(
+      new AnalyzerOptions.fromArguments(argResults, declaredVars));
   var compilerOpts = new CompilerOptions.fromArguments(argResults);
   var outPaths = argResults['out'] as List<String>;
   var moduleFormats = parseModuleFormatOption(argResults);
diff --git a/pkg/dev_compiler/lib/src/compiler/compiler.dart b/pkg/dev_compiler/lib/src/compiler/compiler.dart
index 92cfc59..ea67648 100644
--- a/pkg/dev_compiler/lib/src/compiler/compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/compiler.dart
@@ -94,6 +94,8 @@
     context.typeProvider = sdkResolver.dartSdk.context.typeProvider;
     context.resultProvider =
         new InputPackagesResultProvider(context, summaryData);
+    options.declaredVariables.forEach(context.declaredVariables.define);
+    context.declaredVariables.define('dart.isVM', 'false');
 
     return new ModuleCompiler.withContext(context, summaryData);
   }
diff --git a/pkg/dev_compiler/lib/src/compiler/side_effect_analysis.dart b/pkg/dev_compiler/lib/src/compiler/side_effect_analysis.dart
index 5da18ea..499cb86 100644
--- a/pkg/dev_compiler/lib/src/compiler/side_effect_analysis.dart
+++ b/pkg/dev_compiler/lib/src/compiler/side_effect_analysis.dart
@@ -8,7 +8,7 @@
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/error/listener.dart'
     show AnalysisErrorListener, ErrorReporter;
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/dart/ast/ast.dart';
 
@@ -105,12 +105,12 @@
 }
 
 class ConstFieldVisitor {
-  final ConstantVisitor _constantVisitor;
+  final ConstantVisitor constantVisitor;
 
-  ConstFieldVisitor(TypeProvider types, {Source dummySource})
-      // TODO(jmesserly): support -D variables on the command line
-      : _constantVisitor = new ConstantVisitor(
-            new ConstantEvaluationEngine(types, new DeclaredVariables()),
+  ConstFieldVisitor(AnalysisContext context, {Source dummySource})
+      : constantVisitor = new ConstantVisitor(
+            new ConstantEvaluationEngine(
+                context.typeProvider, context.declaredVariables),
             new ErrorReporter(
                 AnalysisErrorListener.NULL_LISTENER, dummySource));
 
@@ -134,6 +134,6 @@
 
     var initializer = field.initializer;
     if (initializer == null) return null;
-    return initializer.accept(_constantVisitor);
+    return initializer.accept(constantVisitor);
   }
 }
diff --git a/pkg/dev_compiler/test/browser/language_tests.js b/pkg/dev_compiler/test/browser/language_tests.js
index 948d48a..af33d47 100644
--- a/pkg/dev_compiler/test/browser/language_tests.js
+++ b/pkg/dev_compiler/test/browser/language_tests.js
@@ -290,7 +290,6 @@
       'throwing_lazy_variable_test': skip_fail,
       'top_level_non_prefixed_library_test': skip_fail,
       'truncdiv_test': fail,  // did not throw
-      'type_literal_test': firefox_fail,
       'type_variable_nested_test': skip_fail,  // unsound is-check
       'type_variable_typedef_test': skip_fail,  // unsound is-check
 
@@ -401,7 +400,6 @@
     'corelib/regexp': {
       'default_arguments_test': fail,
       'UC16_test': firefox_fail,
-      'unicodeCaseInsensitive_test': firefox_fail
     },
 
     'lib/convert': {
@@ -494,6 +492,7 @@
       'native_gc_test': async_unittest,
       'notification_test': 'fail', // was sdk#27578, needs triage
       'postmessage_structured_test': async_unittest,
+      'queryall_test': ['slow'], // see sdk #27794
       'request_animation_frame_test': async_unittest,
       'resource_http_test': async_unittest,
       'rtc_test': is.chrome('<=55') ? fail : pass, // was sdk#27578, needs triage
@@ -679,7 +678,6 @@
       'typedef_metadata_test': fail,
       'typedef_test': fail,
       'typevariable_mirror_metadata_test': fail,
-      'unmangled_type_test': firefox_fail,
       'unnamed_library_test': fail,
       'variable_is_const_test_none_multi': fail,
     },
diff --git a/pkg/dev_compiler/test/codegen_test.dart b/pkg/dev_compiler/test/codegen_test.dart
index 5c215e0..80a1a8a 100644
--- a/pkg/dev_compiler/test/codegen_test.dart
+++ b/pkg/dev_compiler/test/codegen_test.dart
@@ -22,7 +22,8 @@
         parseDirectives;
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:args/args.dart' show ArgParser, ArgResults;
-import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions;
+import 'package:dev_compiler/src/analyzer/context.dart'
+    show AnalyzerOptions, parseDeclaredVariables;
 import 'package:dev_compiler/src/compiler/compiler.dart'
     show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler;
 import 'package:dev_compiler/src/compiler/module_builder.dart'
@@ -76,9 +77,8 @@
       .where((p) => p.endsWith('.sum'))
       .toList();
 
-  var analyzerOptions = new AnalyzerOptions(
-      dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths);
-  var compiler = new ModuleCompiler(analyzerOptions);
+  var sharedCompiler = new ModuleCompiler(new AnalyzerOptions(
+      dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths));
 
   var testDirs = [
     'language',
@@ -100,9 +100,20 @@
 
   // Our default compiler options. Individual tests can override these.
   var defaultOptions = ['--no-source-map', '--no-summarize'];
-  var compilerArgParser = new ArgParser();
-  CompilerOptions.addArguments(compilerArgParser);
-  addModuleFormatOptions(compilerArgParser);
+  var compileArgParser = new ArgParser();
+  CompilerOptions.addArguments(compileArgParser);
+  addModuleFormatOptions(compileArgParser);
+
+  var testFileOptionsMatcher =
+      new RegExp(r'// (compile options: |SharedOptions=)(.*)', multiLine: true);
+
+  // Ignore dart2js options that we don't support in DDC.
+  var ignoreOptions = [
+    '--enable-enum',
+    '--experimental-trust-js-interop-type-annotations',
+    '--trust-type-annotations',
+    '--supermixin'
+  ];
 
   // Compile each test file to JS and put the result in gen/codegen_output.
   for (var testFile in testFiles) {
@@ -116,15 +127,17 @@
     test('dartdevc $name', () {
       // Check if we need to use special compile options.
       var contents = new File(testFile).readAsStringSync();
-      var match =
-          new RegExp(r'// compile options: (.*)').matchAsPrefix(contents);
+      var match = testFileOptionsMatcher.firstMatch(contents);
 
       var args = defaultOptions.toList();
       if (match != null) {
-        args.addAll(match.group(1).split(' '));
+        var matchedArgs = match.group(2).split(' ');
+        args.addAll(matchedArgs.where((s) => !ignoreOptions.contains(s)));
       }
 
-      var argResults = compilerArgParser.parse(args);
+      var declaredVars = <String, String>{};
+      var argResults =
+          compileArgParser.parse(parseDeclaredVariables(args, declaredVars));
       var options = new CompilerOptions.fromArguments(argResults);
       var moduleFormat = parseModuleFormatOption(argResults).first;
 
@@ -133,6 +146,14 @@
       _collectTransitiveImports(contents, files, from: testFile);
       var unit = new BuildUnit(
           name, path.dirname(testFile), files.toList(), _moduleForLibrary);
+
+      var compiler = sharedCompiler;
+      if (declaredVars.isNotEmpty) {
+        compiler = new ModuleCompiler(new AnalyzerOptions(
+            dartSdkSummaryPath: sdkSummaryFile,
+            summaryPaths: summaryPaths,
+            declaredVariables: declaredVars));
+      }
       var module = compiler.compile(unit, options);
 
       bool notStrong = notYetStrongTests.contains(name);
@@ -155,7 +176,7 @@
 
   if (filePattern.hasMatch('sunflower')) {
     test('sunflower', () {
-      _buildSunflower(compiler, codegenOutputDir, codegenExpectDir);
+      _buildSunflower(sharedCompiler, codegenOutputDir, codegenExpectDir);
     });
   }
 
diff --git a/pkg/dev_compiler/test/not_yet_strong_tests.dart b/pkg/dev_compiler/test/not_yet_strong_tests.dart
index 2b458dd..d6d3976 100644
--- a/pkg/dev_compiler/test/not_yet_strong_tests.dart
+++ b/pkg/dev_compiler/test/not_yet_strong_tests.dart
@@ -2397,27 +2397,12 @@
   'language/unresolved_in_factory_negative_test',
   'language/unresolved_top_level_method_negative_test',
   'language/unresolved_top_level_var_negative_test',
-  'corelib/bool_from_environment_test',
   'corelib/file_resource_test',
-  'corelib/from_environment_const_type_test_none_multi',
-  'corelib/from_environment_const_type_test_01_multi',
-  'corelib/from_environment_const_type_test_05_multi',
-  'corelib/from_environment_const_type_test_10_multi',
-  'corelib/from_environment_const_type_test_15_multi',
-  'corelib/from_environment_const_type_undefined_test_none_multi',
-  'corelib/from_environment_const_type_undefined_test_01_multi',
-  'corelib/from_environment_const_type_undefined_test_05_multi',
-  'corelib/from_environment_const_type_undefined_test_10_multi',
-  'corelib/from_environment_const_type_undefined_test_15_multi',
-  'corelib/int_from_environment2_test',
-  'corelib/int_from_environment_test',
   'corelib/queue_test',
   'corelib/regexp/global_test',
   'corelib/regexp/regexp_test',
   'corelib/regexp/regress-regexp-codeflush_test',
   'corelib/regexp/standalones_test',
-  'corelib/string_from_environment2_test',
-  'corelib/string_from_environment_test',
   'corelib/string_from_list_test',
   'lib/convert/chunked_conversion_json_encode1_test',
   'lib/convert/chunked_conversion_utf84_test',
diff --git a/pkg/dev_compiler/tool/build_pkgs.dart b/pkg/dev_compiler/tool/build_pkgs.dart
new file mode 100755
index 0000000..a6e2b6b
--- /dev/null
+++ b/pkg/dev_compiler/tool/build_pkgs.dart
@@ -0,0 +1,104 @@
+#!/usr/bin/env dart
+import 'dart:io';
+
+import 'package:dev_compiler/src/compiler/command.dart';
+
+/// Compiles the packages that the DDC tests use to JS into:
+///
+/// gen/codegen_output/pkg/...
+///
+/// Assumes the working directory is pkg/dev_compiler.
+///
+/// If no arguments are passed, builds the all of the modules tested on Travis.
+/// If "test" is passed, only builds the modules needed by the tests.
+void main(List<String> arguments) {
+  var test = arguments.length == 1 && arguments[0] == 'test';
+
+  new Directory("gen/codegen_output/pkg").createSync(recursive: true);
+
+  // Build leaf packages. These have no other package dependencies.
+
+  // Under pkg.
+  compileModule('async_helper');
+  compileModule('expect', libs: ['minitest']);
+  compileModule('js', libs: ['js_util']);
+  if (!test) {
+    compileModule('lookup_map');
+    compileModule('meta');
+    compileModule('microlytics', libs: ['html_channels']);
+    compileModule('typed_mock');
+  }
+
+  // Under third_party/pkg.
+  compileModule('collection');
+  compileModule('matcher');
+  compileModule('path');
+  if (!test) {
+    compileModule('args', libs: ['command_runner']);
+    compileModule('charcode');
+    compileModule('fixnum');
+    compileModule('logging');
+    compileModule('markdown');
+    compileModule('mime');
+    compileModule('plugin', libs: ['manager']);
+    compileModule('typed_data');
+    compileModule('usage');
+    compileModule('utf');
+    compileModule('when');
+  }
+
+  // Composite packages with dependencies.
+  compileModule('stack_trace', deps: ['path']);
+  if (!test) {
+    compileModule('async', deps: ['collection']);
+  }
+
+  if (test) {
+    compileModule('unittest',
+        deps: ['matcher', 'path', 'stack_trace'],
+        libs: ['html_config', 'html_individual_config', 'html_enhanced_config'],
+        unsafeForceCompile: true);
+  }
+}
+
+/// Compiles a [module] with a single matching ".dart" library and additional
+/// [libs] and [deps] on other modules.
+void compileModule(String module,
+    {List<String> libs, List<String> deps, bool unsafeForceCompile: false}) {
+  var args = [
+    '--dart-sdk-summary=lib/sdk/ddc_sdk.sum',
+    '-ogen/codegen_output/pkg/$module.js'
+  ];
+
+  // There is always a library that matches the module.
+  args.add('package:$module/$module.dart');
+
+  // Add any additional libraries.
+  if (libs != null) {
+    for (var lib in libs) {
+      args.add('package:$module/$lib.dart');
+    }
+  }
+
+  // Add summaries for any modules this depends on.
+  if (deps != null) {
+    for (var dep in deps) {
+      args.add('-sgen/codegen_output/pkg/$dep.sum');
+    }
+  }
+
+  if (unsafeForceCompile) {
+    args.add('--unsafe-force-compile');
+  }
+
+  // TODO(rnystrom): Hack. DDC has its own forked copy of async_helper that
+  // has a couple of differences from pkg/async_helper. We should unfork them,
+  // but I'm not sure how they'll affect the other non-DDC tests. For now, just
+  // use ours.
+  if (module == 'async_helper') {
+    args.add('--url-mapping=package:async_helper/async_helper.dart,'
+        'test/codegen/async_helper.dart');
+  }
+
+  compile(args);
+}
diff --git a/pkg/dev_compiler/tool/build_pkgs.sh b/pkg/dev_compiler/tool/build_pkgs.sh
index a26c7ea..87ec3c0 100755
--- a/pkg/dev_compiler/tool/build_pkgs.sh
+++ b/pkg/dev_compiler/tool/build_pkgs.sh
@@ -1,92 +1,5 @@
 #!/bin/bash
-set -e # bail on error
 
-cd $( dirname "${BASH_SOURCE[0]}" )/..
-
-mkdir -p gen/codegen_output/pkg/
-
-SDK=--dart-sdk-summary=lib/sdk/ddc_sdk.sum
-
-# Build leaf packages.  These have no other package dependencies.
-
-# Under pkg
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/async_helper.js \
-    package:async_helper/async_helper.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/expect.js \
-    package:expect/expect.dart \
-    package:expect/minitest.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/js.js \
-    package:js/js.dart \
-    package:js/js_util.dart \
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/lookup_map.js \
-    package:lookup_map/lookup_map.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/meta.js \
-    package:meta/meta.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/microlytics.js \
-    package:microlytics/microlytics.dart \
-    package:microlytics/html_channels.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/typed_mock.js \
-    package:typed_mock/typed_mock.dart
-
-# Under third_party/pkg
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/args.js \
-    package:args/args.dart \
-    package:args/command_runner.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/charcode.js \
-    package:charcode/charcode.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/collection.js \
-    package:collection/collection.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/fixnum.js \
-    package:fixnum/fixnum.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/logging.js \
-    package:logging/logging.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/markdown.js \
-    package:markdown/markdown.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/matcher.js \
-    package:matcher/matcher.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/mime.js \
-    package:mime/mime.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/path.js \
-    package:path/path.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/plugin.js \
-    package:plugin/plugin.dart \
-    package:plugin/manager.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/typed_data.js \
-    package:typed_data/typed_data.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/usage.js \
-    package:usage/usage.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/utf.js \
-    package:utf/utf.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/when.js \
-    package:when/when.dart
-
-# Composite packages with dependencies
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/async.js \
-   -s gen/codegen_output/pkg/collection.sum \
-   package:async/async.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/stack_trace.js \
-    -s gen/codegen_output/pkg/path.sum \
-    package:stack_trace/stack_trace.dart
+# TODO: This script is deprecated in favor of the Dart version. For now, forward
+# to it so existing scripts don't break. Eventually, delete this one.
+./tool/build_pkgs.dart
diff --git a/pkg/dev_compiler/tool/build_test_pkgs.sh b/pkg/dev_compiler/tool/build_test_pkgs.sh
index bb63177..1aa3ddf 100755
--- a/pkg/dev_compiler/tool/build_test_pkgs.sh
+++ b/pkg/dev_compiler/tool/build_test_pkgs.sh
@@ -1,42 +1,5 @@
 #!/bin/bash
-set -e # bail on error
 
-cd $( dirname "${BASH_SOURCE[0]}" )/..
-
-mkdir -p gen/codegen_output/pkg/
-
-SDK=--dart-sdk-summary=lib/sdk/ddc_sdk.sum
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/expect.js \
-    package:expect/expect.dart \
-    package:expect/minitest.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/async_helper.js \
-    --url-mapping=package:async_helper/async_helper.dart,test/codegen/async_helper.dart \
-    package:async_helper/async_helper.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/collection.js \
-    package:collection/collection.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/js.js \
-    package:js/js.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/matcher.js \
-    package:matcher/matcher.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/path.js \
-    package:path/path.dart
-
-./bin/dartdevc.dart $SDK -o gen/codegen_output/pkg/stack_trace.js \
-    -s gen/codegen_output/pkg/path.sum \
-    package:stack_trace/stack_trace.dart
-
-./bin/dartdevc.dart $SDK --unsafe-force-compile \
-    -o gen/codegen_output/pkg/unittest.js \
-    -s gen/codegen_output/pkg/matcher.sum \
-    -s gen/codegen_output/pkg/path.sum \
-    -s gen/codegen_output/pkg/stack_trace.sum \
-    package:unittest/unittest.dart \
-    package:unittest/html_config.dart \
-    package:unittest/html_individual_config.dart \
-    package:unittest/html_enhanced_config.dart
+# TODO: This script is deprecated in favor of the Dart version. For now, forward
+# to it so existing scripts don't break. Eventually, delete this one.
+./tool/build_pkgs.dart test
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
index 4e2d6fd..1582f0d 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
+++ b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
@@ -470,7 +470,8 @@
       '  let args = Array.prototype.map.call(arguments, #);'
       '  return #(#(...args));'
       '}', _convertToDart, _convertToJS, f);
-  _dartProxies[wrapper] = f;
+  JS('', '#.set(#, #)', _dartProxies, wrapper, f);
+
   return wrapper;
 }
 
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index 3c7e543..00ec5db 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -14,8 +14,8 @@
 import 'package:path/path.dart' as path;
 
 void main(List<String> argv) {
+  var self = path.relative(path.fromUri(Platform.script));
   if (argv.length < 2) {
-    var self = path.relative(path.fromUri(Platform.script));
     var toolDir = path.relative(path.dirname(path.fromUri(Platform.script)));
 
     var inputExample = path.join(toolDir, 'input_sdk');
@@ -28,6 +28,8 @@
     exit(1);
   }
 
+  var selfModifyTime = new File(self).lastModifiedSync().millisecondsSinceEpoch;
+
   var input = argv[0];
   var sdkLibIn = path.join(input, 'lib');
   var patchIn = path.join(input, 'patch');
@@ -71,8 +73,8 @@
       var outPaths = <String>[libraryOut];
       var libraryContents = libraryFile.readAsStringSync();
 
-      int inputModifyTime =
-          libraryFile.lastModifiedSync().millisecondsSinceEpoch;
+      int inputModifyTime = math.max(selfModifyTime,
+          libraryFile.lastModifiedSync().millisecondsSinceEpoch);
       var partFiles = <File>[];
       for (var part in parseDirectives(libraryContents).directives) {
         if (part is PartDirective) {
@@ -263,6 +265,15 @@
     int start = patchMeta.endToken.next.offset;
     var code = patch.contents.substring(start, patchNode.end);
 
+    // Const factory constructors can't be legally parsed from the patch file,
+    // so we need to omit the "const" there, but still preserve it.
+    if (node is ConstructorDeclaration &&
+        node.constKeyword != null &&
+        patchNode is ConstructorDeclaration &&
+        patchNode.constKeyword == null) {
+      code = 'const $code';
+    }
+
     // For some node like static fields, the node's offset doesn't include
     // the external keyword. Also starting from the keyword lets us preserve
     // documentation comments.
diff --git a/pkg/dev_compiler/tool/run.js b/pkg/dev_compiler/tool/run.js
index b27a007..7306964 100644
--- a/pkg/dev_compiler/tool/run.js
+++ b/pkg/dev_compiler/tool/run.js
@@ -2,9 +2,23 @@
 // 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 is a utility to run and debug an individual DDC compiled test.
+/// Tests can be run with either node or devtool (a Chrome-based utility with
+/// DOM APIs and developer tools support).
+///
+/// Install devtool via:
+/// > npm install -g devtool
+///
+/// Run via:
+/// > devtool tool/run.js -- corelib/apply2_test
+/// or
+/// > node tool/run.js corelib/apply2_test
+///
+/// See TODO below on async / unittest support. 
+
 var args = process.argv.slice(2);
 if (args.length != 1) {
-  throw new Error("Usage: node test/run.js <test-module-name>");
+  throw new Error("Usage: devtool tool/run.js <test-module-name>");
 }
 var test = args[0];
 
@@ -27,7 +41,13 @@
 
 // TODO(vsm): Factor out test framework code in test/browser/language_tests.js
 // and use here.  Async tests and unittests won't work without it.
-
+var sdk = requirejs('dart_sdk');
 var module = requirejs(test);
-test = test.split('/').slice(-1)[0];
-module[test].main();
+var lib = test.split('/').slice(-1)[0];
+try {
+  module[lib].main();
+  console.log('Test ' + test + ' passed.');
+} catch (e) {
+  console.log('Test ' + test + ' failed:\n' + e.toString());
+  sdk.dart.stackPrint(e);
+}
diff --git a/pkg/dev_compiler/tool/sdk_expected_errors.txt b/pkg/dev_compiler/tool/sdk_expected_errors.txt
index 8e0b1c4..80eacbc 100644
--- a/pkg/dev_compiler/tool/sdk_expected_errors.txt
+++ b/pkg/dev_compiler/tool/sdk_expected_errors.txt
@@ -3,6 +3,12 @@
 [error] Invalid override. The type of 'ChunkedConverter.bind' ('(dynamic) → dynamic') isn't a subtype of 'Converter<S, T>.bind' ('(Stream<S>) → Stream<T>'). (dart:convert/chunked_conversion.dart, line 14, col 3)
 [error] Invalid override. The type of 'ChunkedConverter.bind' ('(dynamic) → dynamic') isn't a subtype of 'StreamTransformer<S, T>.bind' ('(Stream<S>) → Stream<T>'). (dart:convert/chunked_conversion.dart, line 14, col 3)
 [error] Invalid override. The type of 'ChunkedConverter.startChunkedConversion' ('(dynamic) → dynamic') isn't a subtype of 'Converter<S, T>.startChunkedConversion' ('(Sink<T>) → Sink<S>'). (dart:convert/chunked_conversion.dart, line 15, col 3)
+[error] Only redirecting factory constructors can be declared to be 'const'. (dart:core/bool.dart, line 41, col 9)
+[error] Const constructors can't throw exceptions. (dart:core/bool.dart, line 42, col 5)
+[error] Only redirecting factory constructors can be declared to be 'const'. (dart:core/int.dart, line 33, col 9)
+[error] Const constructors can't throw exceptions. (dart:core/int.dart, line 34, col 5)
+[error] Only redirecting factory constructors can be declared to be 'const'. (dart:core/string.dart, line 156, col 9)
+[error] Const constructors can't throw exceptions. (dart:core/string.dart, line 157, col 5)
 [error] Invalid override. The type of '_EventStreamSubscription.asFuture' ('([dynamic]) → Future<dynamic>') isn't a subtype of 'StreamSubscription<T>.asFuture' ('<E>([E]) → Future<E>'). (dart:html, line 40152, col 3)
 [error] Invalid override. The type of 'JsArray.[]=' ('(Object, E) → void') isn't a subtype of 'JsObject.[]=' ('(Object, dynamic) → dynamic'). (dart:js, line 363, col 3)
 [warning] Unsafe implicit cast from 'List<dynamic>' to 'List<String>'. This usually indicates that type information was lost and resulted in 'dynamic' and/or a place that will have a failure at runtime. (dart:_js_helper/regexp_helper.dart, line 140, col 43)
diff --git a/pkg/dev_compiler/tool/test.sh b/pkg/dev_compiler/tool/test.sh
index f32a6ad..f5593bc 100755
--- a/pkg/dev_compiler/tool/test.sh
+++ b/pkg/dev_compiler/tool/test.sh
@@ -27,7 +27,7 @@
   rm -r gen/codegen_output || fail
 fi
 
-./tool/build_test_pkgs.sh
+./tool/build_pkgs.dart test
 
 # Make sure we don't run tests in code coverage mode.
 # this will cause us to generate files that are not part of the baseline
diff --git a/pkg/front_end/.analysis_options b/pkg/front_end/.analysis_options
index a10d4c5..f0ac32f 100644
--- a/pkg/front_end/.analysis_options
+++ b/pkg/front_end/.analysis_options
@@ -1,2 +1,4 @@
 analyzer:
   strong-mode: true
+  language:
+    enableSuperMixins: true
diff --git a/pkg/front_end/lib/compilation_error.dart b/pkg/front_end/lib/compilation_error.dart
index a238575..5e30da1 100644
--- a/pkg/front_end/lib/compilation_error.dart
+++ b/pkg/front_end/lib/compilation_error.dart
@@ -18,8 +18,8 @@
   /// A text description of how the user can fix the error.  May be `null`.
   String get correction;
 
-  /// The source location where the error occurred.
-  SourceSpan get location;
+  /// The source span where the error occurred.
+  SourceSpan get span;
 
   /// A text description of the compile error.
   String get message;
diff --git a/pkg/front_end/lib/src/base/analysis_target.dart b/pkg/front_end/lib/src/base/analysis_target.dart
new file mode 100644
index 0000000..ab50efd
--- /dev/null
+++ b/pkg/front_end/lib/src/base/analysis_target.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/base/source.dart';
+
+/**
+ * An object with which an analysis result can be associated.
+ *
+ * Clients may implement this class when creating new kinds of targets.
+ * Instances of this type are used in hashed data structures, so subtypes are
+ * required to correctly implement [==] and [hashCode].
+ */
+abstract class AnalysisTarget {
+  /**
+   * If this target is associated with a library, return the source of the
+   * library's defining compilation unit; otherwise return `null`.
+   */
+  Source get librarySource;
+
+  /**
+   * Return the source associated with this target, or `null` if this target is
+   * not associated with a source.
+   */
+  Source get source;
+}
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/front_end/lib/src/base/errors.dart
new file mode 100644
index 0000000..d39953f
--- /dev/null
+++ b/pkg/front_end/lib/src/base/errors.dart
@@ -0,0 +1,282 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * An error code associated with an [AnalysisError].
+ *
+ * Generally, we want to provide messages that consist of three sentences. From
+ * the user's perspective these sentences should explain:
+ *
+ * 1. what is wrong,
+ * 2. why is it wrong, and
+ * 3. how do I fix it.
+ *
+ * However, we combine the first two in the [message] and the last in the
+ * [correction].
+ *
+ * When composing messages (including correction messages) keep the following
+ * guidelines in mind.
+ *
+ * 1. The message should be a complete sentence starting with an uppercase
+ * letter, and ending with a period.
+ *
+ * 2. Reserved words and embedded identifiers should be in single quotes, so
+ * prefer double quotes for the complete message. For example,
+ * ```
+ * "The class '{0}' can't use 'super'."
+ * ```
+ * Notice that the word 'class' in the preceding message is not quoted as it
+ * refers to the concept 'class', not the reserved word. On the other hand,
+ * 'super' refers to the reserved word. Do not quote 'null' and numeric literals.
+ *
+ * 3. Do not try to compose messages, as it can make translating them hard.
+ *
+ * 4. Try to keep the error messages short, but informative.
+ *
+ * 5. Use simple words and terminology, assume the reader of the message doesn't
+ * have an advanced degree in math, and that English is not the reader's native
+ * language. Do not assume any formal computer science training. For example, do
+ * not use Latin abbreviations (prefer "that is" over "i.e.", and "for example"
+ * over "e.g."). Also avoid phrases such as "if and only if" and "iff"; that
+ * level of precision is unnecessary.
+ *
+ * 6. Prefer contractions when they are in common use, for example, prefer
+ * "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
+ * off-putting to people new to programming.
+ *
+ * 7. Use common terminology, preferably from the Dart Language Specification.
+ * This increases the user's chance of finding a good explanation on the web.
+ *
+ * 8. Do not try to be cute or funny. It is extremely frustrating to work on a
+ * product that crashes with a "tongue-in-cheek" message, especially if you did
+ * not want to use this product to begin with.
+ *
+ * 9. Do not lie, that is, do not write error messages containing phrases like
+ * "can't happen".  If the user ever saw this message, it would be a lie. Prefer
+ * messages like: "Internal error: This function should not be called when 'x'
+ * is null.".
+ *
+ * 10. Prefer to not use the imperative tone. That is, the message should not
+ * sound accusing or like it is ordering the user around. The computer should
+ * describe the problem, not criticize the user for violating the specification.
+ */
+abstract class ErrorCode {
+  /**
+   * The name of the error code.
+   */
+  final String name;
+
+  /**
+   * The template used to create the message to be displayed for this error. The
+   * message should indicate what is wrong and why it is wrong.
+   */
+  final String message;
+
+  /**
+   * The template used to create the correction to be displayed for this error,
+   * or `null` if there is no correction information for this error. The
+   * correction should indicate how the user can fix the error.
+   */
+  final String correction;
+
+  /**
+   * Initialize a newly created error code to have the given [name]. The message
+   * associated with the error will be created from the given [message]
+   * template. The correction associated with the error will be created from the
+   * given [correction] template.
+   */
+  const ErrorCode(this.name, this.message, [this.correction]);
+
+  /**
+   * The severity of the error.
+   */
+  ErrorSeverity get errorSeverity;
+
+  /**
+   * The type of the error.
+   */
+  ErrorType get type;
+
+  /**
+   * The unique name of this error code.
+   */
+  String get uniqueName => "$runtimeType.$name";
+
+  @override
+  String toString() => uniqueName;
+}
+
+/**
+ * The severity of an [ErrorCode].
+ */
+class ErrorSeverity implements Comparable<ErrorSeverity> {
+  /**
+   * The severity representing a non-error. This is never used for any error
+   * code, but is useful for clients.
+   */
+  static const ErrorSeverity NONE = const ErrorSeverity('NONE', 0, " ", "none");
+
+  /**
+   * The severity representing an informational level analysis issue.
+   */
+  static const ErrorSeverity INFO = const ErrorSeverity('INFO', 1, "I", "info");
+
+  /**
+   * The severity representing a warning. Warnings can become errors if the `-Werror` command
+   * line flag is specified.
+   */
+  static const ErrorSeverity WARNING =
+      const ErrorSeverity('WARNING', 2, "W", "warning");
+
+  /**
+   * The severity representing an error.
+   */
+  static const ErrorSeverity ERROR =
+      const ErrorSeverity('ERROR', 3, "E", "error");
+
+  static const List<ErrorSeverity> values = const [NONE, INFO, WARNING, ERROR];
+
+  /**
+   * The name of this error code.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the error code.
+   */
+  final int ordinal;
+
+  /**
+   * The name of the severity used when producing machine output.
+   */
+  final String machineCode;
+
+  /**
+   * The name of the severity used when producing readable output.
+   */
+  final String displayName;
+
+  /**
+   * Initialize a newly created severity with the given names.
+   */
+  const ErrorSeverity(
+      this.name, this.ordinal, this.machineCode, this.displayName);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ErrorSeverity other) => ordinal - other.ordinal;
+
+  /**
+   * Return the severity constant that represents the greatest severity.
+   */
+  ErrorSeverity max(ErrorSeverity severity) =>
+      this.ordinal >= severity.ordinal ? this : severity;
+
+  @override
+  String toString() => name;
+}
+
+/**
+ * The type of an [ErrorCode].
+ */
+class ErrorType implements Comparable<ErrorType> {
+  /**
+   * Task (todo) comments in user code.
+   */
+  static const ErrorType TODO = const ErrorType('TODO', 0, ErrorSeverity.INFO);
+
+  /**
+   * Extra analysis run over the code to follow best practices, which are not in
+   * the Dart Language Specification.
+   */
+  static const ErrorType HINT = const ErrorType('HINT', 1, ErrorSeverity.INFO);
+
+  /**
+   * Compile-time errors are errors that preclude execution. A compile time
+   * error must be reported by a Dart compiler before the erroneous code is
+   * executed.
+   */
+  static const ErrorType COMPILE_TIME_ERROR =
+      const ErrorType('COMPILE_TIME_ERROR', 2, ErrorSeverity.ERROR);
+
+  /**
+   * Checked mode compile-time errors are errors that preclude execution in
+   * checked mode.
+   */
+  static const ErrorType CHECKED_MODE_COMPILE_TIME_ERROR = const ErrorType(
+      'CHECKED_MODE_COMPILE_TIME_ERROR', 3, ErrorSeverity.ERROR);
+
+  /**
+   * Static warnings are those warnings reported by the static checker. They
+   * have no effect on execution. Static warnings must be provided by Dart
+   * compilers used during development.
+   */
+  static const ErrorType STATIC_WARNING =
+      const ErrorType('STATIC_WARNING', 4, ErrorSeverity.WARNING);
+
+  /**
+   * Many, but not all, static warnings relate to types, in which case they are
+   * known as static type warnings.
+   */
+  static const ErrorType STATIC_TYPE_WARNING =
+      const ErrorType('STATIC_TYPE_WARNING', 5, ErrorSeverity.WARNING);
+
+  /**
+   * Syntactic errors are errors produced as a result of input that does not
+   * conform to the grammar.
+   */
+  static const ErrorType SYNTACTIC_ERROR =
+      const ErrorType('SYNTACTIC_ERROR', 6, ErrorSeverity.ERROR);
+
+  /**
+   * Lint warnings describe style and best practice recommendations that can be
+   * used to formalize a project's style guidelines.
+   */
+  static const ErrorType LINT = const ErrorType('LINT', 7, ErrorSeverity.INFO);
+
+  static const List<ErrorType> values = const [
+    TODO,
+    HINT,
+    COMPILE_TIME_ERROR,
+    CHECKED_MODE_COMPILE_TIME_ERROR,
+    STATIC_WARNING,
+    STATIC_TYPE_WARNING,
+    SYNTACTIC_ERROR,
+    LINT
+  ];
+
+  /**
+   * The name of this error type.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the error type.
+   */
+  final int ordinal;
+
+  /**
+   * The severity of this type of error.
+   */
+  final ErrorSeverity severity;
+
+  /**
+   * Initialize a newly created error type to have the given [name] and
+   * [severity].
+   */
+  const ErrorType(this.name, this.ordinal, this.severity);
+
+  String get displayName => name.toLowerCase().replaceAll('_', ' ');
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(ErrorType other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
+}
diff --git a/pkg/front_end/lib/src/base/jenkins_smi_hash.dart b/pkg/front_end/lib/src/base/jenkins_smi_hash.dart
new file mode 100644
index 0000000..8901ba4
--- /dev/null
+++ b/pkg/front_end/lib/src/base/jenkins_smi_hash.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Jenkins hash function, optimized for small integers.
+///
+/// Static methods borrowed from sdk/lib/math/jenkins_smi_hash.dart.  Non-static
+/// methods are an enhancement for the "front_end" package.
+///
+/// Where performance is critical, use [hash2], [hash3], or [hash4], or the
+/// pattern `finish(combine(combine(...combine(0, a), b)..., z))`, where a..z
+/// are hash codes to be combined.
+///
+/// For ease of use, you may also use this pattern:
+/// `(new JenkinsSmiHash()..add(a)..add(b)....add(z)).hashCode`, where a..z are
+/// the sub-objects whose hashes should be combined.  This pattern performs the
+/// same operations as the performance critical variant, but allocates an extra
+/// object.
+class JenkinsSmiHash {
+  /// Accumulates the hash code [value] into the running hash [hash].
+  static int combine(int hash, int value) {
+    hash = 0x1fffffff & (hash + value);
+    hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
+    return hash ^ (hash >> 6);
+  }
+
+  /// Finalizes a running hash produced by [combine].
+  static int finish(int hash) {
+    hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
+    hash = hash ^ (hash >> 11);
+    return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
+  }
+
+  /// Combines together two hash codes.
+  static int hash2(a, b) => finish(combine(combine(0, a), b));
+
+  /// Combines together three hash codes.
+  static int hash3(a, b, c) => finish(combine(combine(combine(0, a), b), c));
+
+  /// Combines together four hash codes.
+  static int hash4(a, b, c, d) =>
+      finish(combine(combine(combine(combine(0, a), b), c), d));
+
+  int _hash = 0;
+
+  /// Accumulates the object [o] into the hash.
+  void add(Object o) {
+    _hash = combine(_hash, o.hashCode);
+  }
+
+  /// Finalizes the hash and return the resulting hashcode.
+  int get hashCode => finish(_hash);
+}
diff --git a/pkg/front_end/lib/src/base/source.dart b/pkg/front_end/lib/src/base/source.dart
new file mode 100644
index 0000000..0ed4747
--- /dev/null
+++ b/pkg/front_end/lib/src/base/source.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/base/analysis_target.dart';
+import 'package:front_end/src/base/timestamped_data.dart';
+import 'package:front_end/src/base/uri_kind.dart';
+
+/**
+ * The interface `Source` defines the behavior of objects representing source code that can be
+ * analyzed by the analysis engine.
+ *
+ * Implementations of this interface need to be aware of some assumptions made by the analysis
+ * engine concerning sources:
+ * * Sources are not required to be unique. That is, there can be multiple instances representing
+ * the same source.
+ * * Sources are long lived. That is, the engine is allowed to hold on to a source for an extended
+ * period of time and that source must continue to report accurate and up-to-date information.
+ * Because of these assumptions, most implementations will not maintain any state but will delegate
+ * to an authoritative system of record in order to implement this API. For example, a source that
+ * represents files on disk would typically query the file system to determine the state of the
+ * file.
+ *
+ * If the instances that implement this API are the system of record, then they will typically be
+ * unique. In that case, sources that are created that represent non-existent files must also be
+ * retained so that if those files are created at a later date the long-lived sources representing
+ * those files will know that they now exist.
+ */
+abstract class Source implements AnalysisTarget {
+  /**
+   * An empty list of sources.
+   */
+  static const List<Source> EMPTY_LIST = const <Source>[];
+
+  /**
+   * Get the contents and timestamp of this source.
+   *
+   * Clients should consider using the method [AnalysisContext.getContents]
+   * because contexts can have local overrides of the content of a source that the source is not
+   * aware of.
+   *
+   * @return the contents and timestamp of the source
+   * @throws Exception if the contents of this source could not be accessed
+   */
+  TimestampedData<String> get contents;
+
+  /**
+   * Return an encoded representation of this source that can be used to create a source that is
+   * equal to this source.
+   *
+   * @return an encoded representation of this source
+   * See [SourceFactory.fromEncoding].
+   */
+  String get encoding;
+
+  /**
+   * Return the full (long) version of the name that can be displayed to the user to denote this
+   * source. For example, for a source representing a file this would typically be the absolute path
+   * of the file.
+   *
+   * @return a name that can be displayed to the user to denote this source
+   */
+  String get fullName;
+
+  /**
+   * Return a hash code for this source.
+   *
+   * @return a hash code for this source
+   * See [Object.hashCode].
+   */
+  @override
+  int get hashCode;
+
+  /**
+   * Return `true` if this source is in one of the system libraries.
+   *
+   * @return `true` if this is in a system library
+   */
+  bool get isInSystemLibrary;
+
+  @override
+  Source get librarySource => null;
+
+  /**
+   * Return the modification stamp for this source, or a negative value if the
+   * source does not exist. A modification stamp is a non-negative integer with
+   * the property that if the contents of the source have not been modified
+   * since the last time the modification stamp was accessed then the same value
+   * will be returned, but if the contents of the source have been modified one
+   * or more times (even if the net change is zero) the stamps will be different.
+   *
+   * Clients should consider using the method
+   * [AnalysisContext.getModificationStamp] because contexts can have local
+   * overrides of the content of a source that the source is not aware of.
+   */
+  int get modificationStamp;
+
+  /**
+   * Return a short version of the name that can be displayed to the user to denote this source. For
+   * example, for a source representing a file this would typically be the name of the file.
+   *
+   * @return a name that can be displayed to the user to denote this source
+   */
+  String get shortName;
+
+  @override
+  Source get source => this;
+
+  /**
+   * Return the URI from which this source was originally derived.
+   *
+   * @return the URI from which this source was originally derived
+   */
+  Uri get uri;
+
+  /**
+   * Return the kind of URI from which this source was originally derived. If this source was
+   * created from an absolute URI, then the returned kind will reflect the scheme of the absolute
+   * URI. If it was created from a relative URI, then the returned kind will be the same as the kind
+   * of the source against which the relative URI was resolved.
+   *
+   * @return the kind of URI from which this source was originally derived
+   */
+  UriKind get uriKind;
+
+  /**
+   * Return `true` if the given object is a source that represents the same source code as
+   * this source.
+   *
+   * @param object the object to be compared with this object
+   * @return `true` if the given object is a source that represents the same source code as
+   *         this source
+   * See [Object.==].
+   */
+  @override
+  bool operator ==(Object object);
+
+  /**
+   * Return `true` if this source exists.
+   *
+   * Clients should consider using the method [AnalysisContext.exists] because
+   * contexts can have local overrides of the content of a source that the source is not aware of
+   * and a source with local content is considered to exist even if there is no file on disk.
+   *
+   * @return `true` if this source exists
+   */
+  bool exists();
+}
diff --git a/pkg/front_end/lib/src/scanner/syntactic_entity.dart b/pkg/front_end/lib/src/base/syntactic_entity.dart
similarity index 100%
rename from pkg/front_end/lib/src/scanner/syntactic_entity.dart
rename to pkg/front_end/lib/src/base/syntactic_entity.dart
diff --git a/pkg/front_end/lib/src/base/timestamped_data.dart b/pkg/front_end/lib/src/base/timestamped_data.dart
new file mode 100644
index 0000000..4c76dc5
--- /dev/null
+++ b/pkg/front_end/lib/src/base/timestamped_data.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Analysis data for which we have a modification time.
+ */
+class TimestampedData<E> {
+  /**
+   * The modification time of the source from which the data was created.
+   */
+  final int modificationTime;
+
+  /**
+   * The data that was created from the source.
+   */
+  final E data;
+
+  /**
+   * Initialize a newly created holder to associate the given [data] with the
+   * given [modificationTime].
+   */
+  TimestampedData(this.modificationTime, this.data);
+}
diff --git a/pkg/front_end/lib/src/base/uri_kind.dart b/pkg/front_end/lib/src/base/uri_kind.dart
new file mode 100644
index 0000000..0e6d007
--- /dev/null
+++ b/pkg/front_end/lib/src/base/uri_kind.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * The enumeration `UriKind` defines the different kinds of URI's that are known to the
+ * analysis engine. These are used to keep track of the kind of URI associated with a given source.
+ */
+class UriKind implements Comparable<UriKind> {
+  /**
+   * A 'dart:' URI.
+   */
+  static const UriKind DART_URI = const UriKind('DART_URI', 0, 0x64);
+
+  /**
+   * A 'file:' URI.
+   */
+  static const UriKind FILE_URI = const UriKind('FILE_URI', 1, 0x66);
+
+  /**
+   * A 'package:' URI.
+   */
+  static const UriKind PACKAGE_URI = const UriKind('PACKAGE_URI', 2, 0x70);
+
+  static const List<UriKind> values = const [DART_URI, FILE_URI, PACKAGE_URI];
+
+  /**
+   * The name of this URI kind.
+   */
+  final String name;
+
+  /**
+   * The ordinal value of the URI kind.
+   */
+  final int ordinal;
+
+  /**
+   * The single character encoding used to identify this kind of URI.
+   */
+  final int encoding;
+
+  /**
+   * Initialize a newly created URI kind to have the given encoding.
+   */
+  const UriKind(this.name, this.ordinal, this.encoding);
+
+  @override
+  int get hashCode => ordinal;
+
+  @override
+  int compareTo(UriKind other) => ordinal - other.ordinal;
+
+  @override
+  String toString() => name;
+
+  /**
+   * Return the URI kind represented by the given [encoding], or `null` if there
+   * is no kind with the given encoding.
+   */
+  static UriKind fromEncoding(int encoding) {
+    while (true) {
+      if (encoding == 0x64) {
+        return DART_URI;
+      } else if (encoding == 0x66) {
+        return FILE_URI;
+      } else if (encoding == 0x70) {
+        return PACKAGE_URI;
+      }
+      break;
+    }
+    return null;
+  }
+
+  /**
+   * Return the URI kind corresponding to the given scheme string.
+   */
+  static UriKind fromScheme(String scheme) {
+    if (scheme == 'package') {
+      return UriKind.PACKAGE_URI;
+    } else if (scheme == 'dart') {
+      return UriKind.DART_URI;
+    } else if (scheme == 'file') {
+      return UriKind.FILE_URI;
+    }
+    return UriKind.FILE_URI;
+  }
+}
diff --git a/pkg/front_end/lib/src/scanner/errors.dart b/pkg/front_end/lib/src/scanner/errors.dart
index e5f66de..bcf0c56 100644
--- a/pkg/front_end/lib/src/scanner/errors.dart
+++ b/pkg/front_end/lib/src/scanner/errors.dart
@@ -2,284 +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.
 
-/**
- * An error code associated with an [AnalysisError].
- *
- * Generally, we want to provide messages that consist of three sentences. From
- * the user's perspective these sentences should explain:
- *
- * 1. what is wrong,
- * 2. why is it wrong, and
- * 3. how do I fix it.
- *
- * However, we combine the first two in the [message] and the last in the
- * [correction].
- *
- * When composing messages (including correction messages) keep the following
- * guidelines in mind.
- *
- * 1. The message should be a complete sentence starting with an uppercase
- * letter, and ending with a period.
- *
- * 2. Reserved words and embedded identifiers should be in single quotes, so
- * prefer double quotes for the complete message. For example,
- * ```
- * "The class '{0}' can't use 'super'."
- * ```
- * Notice that the word 'class' in the preceding message is not quoted as it
- * refers to the concept 'class', not the reserved word. On the other hand,
- * 'super' refers to the reserved word. Do not quote 'null' and numeric literals.
- *
- * 3. Do not try to compose messages, as it can make translating them hard.
- *
- * 4. Try to keep the error messages short, but informative.
- *
- * 5. Use simple words and terminology, assume the reader of the message doesn't
- * have an advanced degree in math, and that English is not the reader's native
- * language. Do not assume any formal computer science training. For example, do
- * not use Latin abbreviations (prefer "that is" over "i.e.", and "for example"
- * over "e.g."). Also avoid phrases such as "if and only if" and "iff"; that
- * level of precision is unnecessary.
- *
- * 6. Prefer contractions when they are in common use, for example, prefer
- * "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
- * off-putting to people new to programming.
- *
- * 7. Use common terminology, preferably from the Dart Language Specification.
- * This increases the user's chance of finding a good explanation on the web.
- *
- * 8. Do not try to be cute or funny. It is extremely frustrating to work on a
- * product that crashes with a "tongue-in-cheek" message, especially if you did
- * not want to use this product to begin with.
- *
- * 9. Do not lie, that is, do not write error messages containing phrases like
- * "can't happen".  If the user ever saw this message, it would be a lie. Prefer
- * messages like: "Internal error: This function should not be called when 'x'
- * is null.".
- *
- * 10. Prefer to not use the imperative tone. That is, the message should not
- * sound accusing or like it is ordering the user around. The computer should
- * describe the problem, not criticize the user for violating the specification.
- */
-abstract class ErrorCode {
-  /**
-   * The name of the error code.
-   */
-  final String name;
-
-  /**
-   * The template used to create the message to be displayed for this error. The
-   * message should indicate what is wrong and why it is wrong.
-   */
-  final String message;
-
-  /**
-   * The template used to create the correction to be displayed for this error,
-   * or `null` if there is no correction information for this error. The
-   * correction should indicate how the user can fix the error.
-   */
-  final String correction;
-
-  /**
-   * Initialize a newly created error code to have the given [name]. The message
-   * associated with the error will be created from the given [message]
-   * template. The correction associated with the error will be created from the
-   * given [correction] template.
-   */
-  const ErrorCode(this.name, this.message, [this.correction]);
-
-  /**
-   * The severity of the error.
-   */
-  ErrorSeverity get errorSeverity;
-
-  /**
-   * The type of the error.
-   */
-  ErrorType get type;
-
-  /**
-   * The unique name of this error code.
-   */
-  String get uniqueName => "$runtimeType.$name";
-
-  @override
-  String toString() => uniqueName;
-}
-
-/**
- * The severity of an [ErrorCode].
- */
-class ErrorSeverity implements Comparable<ErrorSeverity> {
-  /**
-   * The severity representing a non-error. This is never used for any error
-   * code, but is useful for clients.
-   */
-  static const ErrorSeverity NONE = const ErrorSeverity('NONE', 0, " ", "none");
-
-  /**
-   * The severity representing an informational level analysis issue.
-   */
-  static const ErrorSeverity INFO = const ErrorSeverity('INFO', 1, "I", "info");
-
-  /**
-   * The severity representing a warning. Warnings can become errors if the `-Werror` command
-   * line flag is specified.
-   */
-  static const ErrorSeverity WARNING =
-      const ErrorSeverity('WARNING', 2, "W", "warning");
-
-  /**
-   * The severity representing an error.
-   */
-  static const ErrorSeverity ERROR =
-      const ErrorSeverity('ERROR', 3, "E", "error");
-
-  static const List<ErrorSeverity> values = const [NONE, INFO, WARNING, ERROR];
-
-  /**
-   * The name of this error code.
-   */
-  final String name;
-
-  /**
-   * The ordinal value of the error code.
-   */
-  final int ordinal;
-
-  /**
-   * The name of the severity used when producing machine output.
-   */
-  final String machineCode;
-
-  /**
-   * The name of the severity used when producing readable output.
-   */
-  final String displayName;
-
-  /**
-   * Initialize a newly created severity with the given names.
-   */
-  const ErrorSeverity(
-      this.name, this.ordinal, this.machineCode, this.displayName);
-
-  @override
-  int get hashCode => ordinal;
-
-  @override
-  int compareTo(ErrorSeverity other) => ordinal - other.ordinal;
-
-  /**
-   * Return the severity constant that represents the greatest severity.
-   */
-  ErrorSeverity max(ErrorSeverity severity) =>
-      this.ordinal >= severity.ordinal ? this : severity;
-
-  @override
-  String toString() => name;
-}
-
-/**
- * The type of an [ErrorCode].
- */
-class ErrorType implements Comparable<ErrorType> {
-  /**
-   * Task (todo) comments in user code.
-   */
-  static const ErrorType TODO = const ErrorType('TODO', 0, ErrorSeverity.INFO);
-
-  /**
-   * Extra analysis run over the code to follow best practices, which are not in
-   * the Dart Language Specification.
-   */
-  static const ErrorType HINT = const ErrorType('HINT', 1, ErrorSeverity.INFO);
-
-  /**
-   * Compile-time errors are errors that preclude execution. A compile time
-   * error must be reported by a Dart compiler before the erroneous code is
-   * executed.
-   */
-  static const ErrorType COMPILE_TIME_ERROR =
-      const ErrorType('COMPILE_TIME_ERROR', 2, ErrorSeverity.ERROR);
-
-  /**
-   * Checked mode compile-time errors are errors that preclude execution in
-   * checked mode.
-   */
-  static const ErrorType CHECKED_MODE_COMPILE_TIME_ERROR = const ErrorType(
-      'CHECKED_MODE_COMPILE_TIME_ERROR', 3, ErrorSeverity.ERROR);
-
-  /**
-   * Static warnings are those warnings reported by the static checker. They
-   * have no effect on execution. Static warnings must be provided by Dart
-   * compilers used during development.
-   */
-  static const ErrorType STATIC_WARNING =
-      const ErrorType('STATIC_WARNING', 4, ErrorSeverity.WARNING);
-
-  /**
-   * Many, but not all, static warnings relate to types, in which case they are
-   * known as static type warnings.
-   */
-  static const ErrorType STATIC_TYPE_WARNING =
-      const ErrorType('STATIC_TYPE_WARNING', 5, ErrorSeverity.WARNING);
-
-  /**
-   * Syntactic errors are errors produced as a result of input that does not
-   * conform to the grammar.
-   */
-  static const ErrorType SYNTACTIC_ERROR =
-      const ErrorType('SYNTACTIC_ERROR', 6, ErrorSeverity.ERROR);
-
-  /**
-   * Lint warnings describe style and best practice recommendations that can be
-   * used to formalize a project's style guidelines.
-   */
-  static const ErrorType LINT = const ErrorType('LINT', 7, ErrorSeverity.INFO);
-
-  static const List<ErrorType> values = const [
-    TODO,
-    HINT,
-    COMPILE_TIME_ERROR,
-    CHECKED_MODE_COMPILE_TIME_ERROR,
-    STATIC_WARNING,
-    STATIC_TYPE_WARNING,
-    SYNTACTIC_ERROR,
-    LINT
-  ];
-
-  /**
-   * The name of this error type.
-   */
-  final String name;
-
-  /**
-   * The ordinal value of the error type.
-   */
-  final int ordinal;
-
-  /**
-   * The severity of this type of error.
-   */
-  final ErrorSeverity severity;
-
-  /**
-   * Initialize a newly created error type to have the given [name] and
-   * [severity].
-   */
-  const ErrorType(this.name, this.ordinal, this.severity);
-
-  String get displayName => name.toLowerCase().replaceAll('_', ' ');
-
-  @override
-  int get hashCode => ordinal;
-
-  @override
-  int compareTo(ErrorType other) => ordinal - other.ordinal;
-
-  @override
-  String toString() => name;
-}
+import 'package:front_end/src/base/errors.dart';
 
 /**
  * The error codes used for errors detected by the scanner.
diff --git a/pkg/front_end/lib/src/scanner/reader.dart b/pkg/front_end/lib/src/scanner/reader.dart
index ee9d6c0..b079139 100644
--- a/pkg/front_end/lib/src/scanner/reader.dart
+++ b/pkg/front_end/lib/src/scanner/reader.dart
@@ -42,3 +42,92 @@
    */
   int peek();
 }
+
+/**
+ * A [CharacterReader] that reads characters from a character sequence.
+ */
+class CharSequenceReader implements CharacterReader {
+  /**
+   * The sequence from which characters will be read.
+   */
+  final String _sequence;
+
+  /**
+   * The number of characters in the string.
+   */
+  int _stringLength;
+
+  /**
+   * The index, relative to the string, of the next character to be read.
+   */
+  int _charOffset;
+
+  /**
+   * Initialize a newly created reader to read the characters in the given
+   * [_sequence].
+   */
+  CharSequenceReader(this._sequence) {
+    this._stringLength = _sequence.length;
+    this._charOffset = 0;
+  }
+
+  @override
+  int get offset => _charOffset - 1;
+
+  @override
+  void set offset(int offset) {
+    _charOffset = offset + 1;
+  }
+
+  @override
+  int advance() {
+    if (_charOffset >= _stringLength) {
+      return -1;
+    }
+    return _sequence.codeUnitAt(_charOffset++);
+  }
+
+  @override
+  String getString(int start, int endDelta) =>
+      _sequence.substring(start, _charOffset + endDelta);
+
+  @override
+  int peek() {
+    if (_charOffset >= _stringLength) {
+      return -1;
+    }
+    return _sequence.codeUnitAt(_charOffset);
+  }
+}
+
+/**
+ * A [CharacterReader] that reads characters from a character sequence, but adds
+ * a delta when reporting the current character offset so that the character
+ * sequence can be a subsequence from a larger sequence.
+ */
+class SubSequenceReader extends CharSequenceReader {
+  /**
+   * The offset from the beginning of the file to the beginning of the source
+   * being scanned.
+   */
+  final int _offsetDelta;
+
+  /**
+   * Initialize a newly created reader to read the characters in the given
+   * [sequence]. The [_offsetDelta] is the offset from the beginning of the file
+   * to the beginning of the source being scanned
+   */
+  SubSequenceReader(String sequence, this._offsetDelta) : super(sequence);
+
+  @override
+  int get offset => _offsetDelta + super.offset;
+
+  @override
+  void set offset(int offset) {
+    super.offset = offset - _offsetDelta;
+  }
+
+  @override
+  String getString(int start, int endDelta) =>
+      super.getString(start - _offsetDelta, endDelta);
+}
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index 10d4924..95c1005 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -6,11 +6,10 @@
  * Defines the tokens that are produced by the scanner, used by the parser, and
  * referenced from the [AST structure](ast.dart).
  */
-
 import 'dart:collection';
 
+import 'package:front_end/src/base/syntactic_entity.dart';
 import 'package:front_end/src/scanner/string_utilities.dart';
-import 'package:front_end/src/scanner/syntactic_entity.dart';
 
 /**
  * The opening half of a grouping pair of tokens. This is used for curly
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
new file mode 100644
index 0000000..69e802d
--- /dev/null
+++ b/pkg/front_end/test/scanner_test.dart
@@ -0,0 +1,1298 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/base/errors.dart';
+import 'package:front_end/src/base/jenkins_smi_hash.dart';
+import 'package:front_end/src/scanner/errors.dart';
+import 'package:front_end/src/scanner/reader.dart';
+import 'package:front_end/src/scanner/scanner.dart';
+import 'package:front_end/src/scanner/token.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CharSequenceReaderTest);
+    defineReflectiveTests(KeywordStateTest);
+    defineReflectiveTests(ScannerTest);
+    defineReflectiveTests(TokenTypeTest);
+  });
+}
+
+@reflectiveTest
+class CharSequenceReaderTest {
+  void test_advance() {
+    CharSequenceReader reader = new CharSequenceReader("x");
+    expect(reader.advance(), 0x78);
+    expect(reader.advance(), -1);
+    expect(reader.advance(), -1);
+  }
+
+  void test_creation() {
+    expect(new CharSequenceReader("x"), isNotNull);
+  }
+
+  void test_getOffset() {
+    CharSequenceReader reader = new CharSequenceReader("x");
+    expect(reader.offset, -1);
+    reader.advance();
+    expect(reader.offset, 0);
+    reader.advance();
+    expect(reader.offset, 0);
+  }
+
+  void test_getString() {
+    CharSequenceReader reader = new CharSequenceReader("xyzzy");
+    reader.offset = 3;
+    expect(reader.getString(1, 0), "yzz");
+    expect(reader.getString(2, 1), "zzy");
+  }
+
+  void test_peek() {
+    CharSequenceReader reader = new CharSequenceReader("xy");
+    expect(reader.peek(), 0x78);
+    expect(reader.peek(), 0x78);
+    reader.advance();
+    expect(reader.peek(), 0x79);
+    expect(reader.peek(), 0x79);
+    reader.advance();
+    expect(reader.peek(), -1);
+    expect(reader.peek(), -1);
+  }
+
+  void test_setOffset() {
+    CharSequenceReader reader = new CharSequenceReader("xyz");
+    reader.offset = 2;
+    expect(reader.offset, 2);
+  }
+}
+
+@reflectiveTest
+class KeywordStateTest {
+  void test_KeywordState() {
+    //
+    // Generate the test data to be scanned.
+    //
+    List<Keyword> keywords = Keyword.values;
+    int keywordCount = keywords.length;
+    List<String> textToTest = new List<String>(keywordCount * 3);
+    for (int i = 0; i < keywordCount; i++) {
+      String syntax = keywords[i].syntax;
+      textToTest[i] = syntax;
+      textToTest[i + keywordCount] = "${syntax}x";
+      textToTest[i + keywordCount * 2] = syntax.substring(0, syntax.length - 1);
+    }
+    //
+    // Scan each of the identifiers.
+    //
+    KeywordState firstState = KeywordState.KEYWORD_STATE;
+    for (int i = 0; i < textToTest.length; i++) {
+      String text = textToTest[i];
+      int index = 0;
+      int length = text.length;
+      KeywordState state = firstState;
+      while (index < length && state != null) {
+        state = state.next(text.codeUnitAt(index));
+        index++;
+      }
+      if (i < keywordCount) {
+        // keyword
+        expect(state, isNotNull);
+        expect(state.keyword(), isNotNull);
+        expect(state.keyword(), keywords[i]);
+      } else if (i < keywordCount * 2) {
+        // keyword + "x"
+        expect(state, isNull);
+      } else {
+        // keyword.substring(0, keyword.length() - 1)
+        expect(state, isNotNull);
+      }
+    }
+  }
+}
+
+@reflectiveTest
+class ScannerTest {
+  void fail_incomplete_string_interpolation() {
+    // https://code.google.com/p/dart/issues/detail?id=18073
+    _assertErrorAndTokens(
+        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9, "\"foo \${bar", [
+      new StringToken(TokenType.STRING, "\"foo ", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 5),
+      new StringToken(TokenType.IDENTIFIER, "bar", 7)
+    ]);
+  }
+
+  void test_ampersand() {
+    _assertToken(TokenType.AMPERSAND, "&");
+  }
+
+  void test_ampersand_ampersand() {
+    _assertToken(TokenType.AMPERSAND_AMPERSAND, "&&");
+  }
+
+  void test_ampersand_ampersand_eq() {
+    _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=",
+        lazyAssignmentOperators: true);
+  }
+
+  void test_ampersand_eq() {
+    _assertToken(TokenType.AMPERSAND_EQ, "&=");
+  }
+
+  void test_at() {
+    _assertToken(TokenType.AT, "@");
+  }
+
+  void test_backping() {
+    _assertToken(TokenType.BACKPING, "`");
+  }
+
+  void test_backslash() {
+    _assertToken(TokenType.BACKSLASH, "\\");
+  }
+
+  void test_bang() {
+    _assertToken(TokenType.BANG, "!");
+  }
+
+  void test_bang_eq() {
+    _assertToken(TokenType.BANG_EQ, "!=");
+  }
+
+  void test_bar() {
+    _assertToken(TokenType.BAR, "|");
+  }
+
+  void test_bar_bar() {
+    _assertToken(TokenType.BAR_BAR, "||");
+  }
+
+  void test_bar_bar_eq() {
+    _assertToken(TokenType.BAR_BAR_EQ, "||=", lazyAssignmentOperators: true);
+  }
+
+  void test_bar_eq() {
+    _assertToken(TokenType.BAR_EQ, "|=");
+  }
+
+  void test_caret() {
+    _assertToken(TokenType.CARET, "^");
+  }
+
+  void test_caret_eq() {
+    _assertToken(TokenType.CARET_EQ, "^=");
+  }
+
+  void test_close_curly_bracket() {
+    _assertToken(TokenType.CLOSE_CURLY_BRACKET, "}");
+  }
+
+  void test_close_paren() {
+    _assertToken(TokenType.CLOSE_PAREN, ")");
+  }
+
+  void test_close_quare_bracket() {
+    _assertToken(TokenType.CLOSE_SQUARE_BRACKET, "]");
+  }
+
+  void test_colon() {
+    _assertToken(TokenType.COLON, ":");
+  }
+
+  void test_comma() {
+    _assertToken(TokenType.COMMA, ",");
+  }
+
+  void test_comment_disabled_multi() {
+    Scanner scanner =
+        new _TestScanner(new CharSequenceReader("/* comment */ "));
+    scanner.preserveComments = false;
+    Token token = scanner.tokenize();
+    expect(token, isNotNull);
+    expect(token.precedingComments, isNull);
+  }
+
+  void test_comment_generic_method_type_assign() {
+    _assertComment(TokenType.MULTI_LINE_COMMENT, "/*=comment*/");
+    _assertComment(TokenType.GENERIC_METHOD_TYPE_ASSIGN, "/*=comment*/",
+        genericMethodComments: true);
+  }
+
+  void test_comment_generic_method_type_list() {
+    _assertComment(TokenType.MULTI_LINE_COMMENT, "/*<comment>*/");
+    _assertComment(TokenType.GENERIC_METHOD_TYPE_LIST, "/*<comment>*/",
+        genericMethodComments: true);
+  }
+
+  void test_comment_multi() {
+    _assertComment(TokenType.MULTI_LINE_COMMENT, "/* comment */");
+  }
+
+  void test_comment_multi_lineEnds() {
+    String code = r'''
+/**
+ * aa
+ * bbb
+ * c
+ */''';
+    _ErrorListener listener = new _ErrorListener();
+    Scanner scanner = new _TestScanner(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");
+  }
+
+  void test_comment_nested() {
+    _assertComment(
+        TokenType.MULTI_LINE_COMMENT, "/* comment /* within a */ comment */");
+  }
+
+  void test_comment_single() {
+    _assertComment(TokenType.SINGLE_LINE_COMMENT, "// comment");
+  }
+
+  void test_double_both_E() {
+    _assertToken(TokenType.DOUBLE, "0.123E4");
+  }
+
+  void test_double_both_e() {
+    _assertToken(TokenType.DOUBLE, "0.123e4");
+  }
+
+  void test_double_fraction() {
+    _assertToken(TokenType.DOUBLE, ".123");
+  }
+
+  void test_double_fraction_E() {
+    _assertToken(TokenType.DOUBLE, ".123E4");
+  }
+
+  void test_double_fraction_e() {
+    _assertToken(TokenType.DOUBLE, ".123e4");
+  }
+
+  void test_double_missingDigitInExponent() {
+    _assertError(ScannerErrorCode.MISSING_DIGIT, 1, "1e");
+  }
+
+  void test_double_whole_E() {
+    _assertToken(TokenType.DOUBLE, "12E4");
+  }
+
+  void test_double_whole_e() {
+    _assertToken(TokenType.DOUBLE, "12e4");
+  }
+
+  void test_eq() {
+    _assertToken(TokenType.EQ, "=");
+  }
+
+  void test_eq_eq() {
+    _assertToken(TokenType.EQ_EQ, "==");
+  }
+
+  void test_gt() {
+    _assertToken(TokenType.GT, ">");
+  }
+
+  void test_gt_eq() {
+    _assertToken(TokenType.GT_EQ, ">=");
+  }
+
+  void test_gt_gt() {
+    _assertToken(TokenType.GT_GT, ">>");
+  }
+
+  void test_gt_gt_eq() {
+    _assertToken(TokenType.GT_GT_EQ, ">>=");
+  }
+
+  void test_hash() {
+    _assertToken(TokenType.HASH, "#");
+  }
+
+  void test_hexidecimal() {
+    _assertToken(TokenType.HEXADECIMAL, "0x1A2B3C");
+  }
+
+  void test_hexidecimal_missingDigit() {
+    _assertError(ScannerErrorCode.MISSING_HEX_DIGIT, 1, "0x");
+  }
+
+  void test_identifier() {
+    _assertToken(TokenType.IDENTIFIER, "result");
+  }
+
+  void test_illegalChar_cyrillicLetter_middle() {
+    _assertError(
+        ScannerErrorCode.ILLEGAL_CHARACTER, 5, "Shche\u0433lov", [0x433]);
+  }
+
+  void test_illegalChar_cyrillicLetter_start() {
+    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u0429", [0x429]);
+  }
+
+  void test_illegalChar_nbsp() {
+    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u00A0", [0xa0]);
+  }
+
+  void test_illegalChar_notLetter() {
+    _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u0312", [0x312]);
+  }
+
+  void test_index() {
+    _assertToken(TokenType.INDEX, "[]");
+  }
+
+  void test_index_eq() {
+    _assertToken(TokenType.INDEX_EQ, "[]=");
+  }
+
+  void test_int() {
+    _assertToken(TokenType.INT, "123");
+  }
+
+  void test_int_initialZero() {
+    _assertToken(TokenType.INT, "0123");
+  }
+
+  void test_keyword_abstract() {
+    _assertKeywordToken("abstract");
+  }
+
+  void test_keyword_as() {
+    _assertKeywordToken("as");
+  }
+
+  void test_keyword_assert() {
+    _assertKeywordToken("assert");
+  }
+
+  void test_keyword_break() {
+    _assertKeywordToken("break");
+  }
+
+  void test_keyword_case() {
+    _assertKeywordToken("case");
+  }
+
+  void test_keyword_catch() {
+    _assertKeywordToken("catch");
+  }
+
+  void test_keyword_class() {
+    _assertKeywordToken("class");
+  }
+
+  void test_keyword_const() {
+    _assertKeywordToken("const");
+  }
+
+  void test_keyword_continue() {
+    _assertKeywordToken("continue");
+  }
+
+  void test_keyword_default() {
+    _assertKeywordToken("default");
+  }
+
+  void test_keyword_deferred() {
+    _assertKeywordToken("deferred");
+  }
+
+  void test_keyword_do() {
+    _assertKeywordToken("do");
+  }
+
+  void test_keyword_dynamic() {
+    _assertKeywordToken("dynamic");
+  }
+
+  void test_keyword_else() {
+    _assertKeywordToken("else");
+  }
+
+  void test_keyword_enum() {
+    _assertKeywordToken("enum");
+  }
+
+  void test_keyword_export() {
+    _assertKeywordToken("export");
+  }
+
+  void test_keyword_extends() {
+    _assertKeywordToken("extends");
+  }
+
+  void test_keyword_factory() {
+    _assertKeywordToken("factory");
+  }
+
+  void test_keyword_false() {
+    _assertKeywordToken("false");
+  }
+
+  void test_keyword_final() {
+    _assertKeywordToken("final");
+  }
+
+  void test_keyword_finally() {
+    _assertKeywordToken("finally");
+  }
+
+  void test_keyword_for() {
+    _assertKeywordToken("for");
+  }
+
+  void test_keyword_get() {
+    _assertKeywordToken("get");
+  }
+
+  void test_keyword_if() {
+    _assertKeywordToken("if");
+  }
+
+  void test_keyword_implements() {
+    _assertKeywordToken("implements");
+  }
+
+  void test_keyword_import() {
+    _assertKeywordToken("import");
+  }
+
+  void test_keyword_in() {
+    _assertKeywordToken("in");
+  }
+
+  void test_keyword_is() {
+    _assertKeywordToken("is");
+  }
+
+  void test_keyword_library() {
+    _assertKeywordToken("library");
+  }
+
+  void test_keyword_new() {
+    _assertKeywordToken("new");
+  }
+
+  void test_keyword_null() {
+    _assertKeywordToken("null");
+  }
+
+  void test_keyword_operator() {
+    _assertKeywordToken("operator");
+  }
+
+  void test_keyword_part() {
+    _assertKeywordToken("part");
+  }
+
+  void test_keyword_rethrow() {
+    _assertKeywordToken("rethrow");
+  }
+
+  void test_keyword_return() {
+    _assertKeywordToken("return");
+  }
+
+  void test_keyword_set() {
+    _assertKeywordToken("set");
+  }
+
+  void test_keyword_static() {
+    _assertKeywordToken("static");
+  }
+
+  void test_keyword_super() {
+    _assertKeywordToken("super");
+  }
+
+  void test_keyword_switch() {
+    _assertKeywordToken("switch");
+  }
+
+  void test_keyword_this() {
+    _assertKeywordToken("this");
+  }
+
+  void test_keyword_throw() {
+    _assertKeywordToken("throw");
+  }
+
+  void test_keyword_true() {
+    _assertKeywordToken("true");
+  }
+
+  void test_keyword_try() {
+    _assertKeywordToken("try");
+  }
+
+  void test_keyword_typedef() {
+    _assertKeywordToken("typedef");
+  }
+
+  void test_keyword_var() {
+    _assertKeywordToken("var");
+  }
+
+  void test_keyword_void() {
+    _assertKeywordToken("void");
+  }
+
+  void test_keyword_while() {
+    _assertKeywordToken("while");
+  }
+
+  void test_keyword_with() {
+    _assertKeywordToken("with");
+  }
+
+  void test_lt() {
+    _assertToken(TokenType.LT, "<");
+  }
+
+  void test_lt_eq() {
+    _assertToken(TokenType.LT_EQ, "<=");
+  }
+
+  void test_lt_lt() {
+    _assertToken(TokenType.LT_LT, "<<");
+  }
+
+  void test_lt_lt_eq() {
+    _assertToken(TokenType.LT_LT_EQ, "<<=");
+  }
+
+  void test_minus() {
+    _assertToken(TokenType.MINUS, "-");
+  }
+
+  void test_minus_eq() {
+    _assertToken(TokenType.MINUS_EQ, "-=");
+  }
+
+  void test_minus_minus() {
+    _assertToken(TokenType.MINUS_MINUS, "--");
+  }
+
+  void test_open_curly_bracket() {
+    _assertToken(TokenType.OPEN_CURLY_BRACKET, "{");
+  }
+
+  void test_open_paren() {
+    _assertToken(TokenType.OPEN_PAREN, "(");
+  }
+
+  void test_open_square_bracket() {
+    _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
+  }
+
+  void test_openSquareBracket() {
+    _assertToken(TokenType.OPEN_SQUARE_BRACKET, "[");
+  }
+
+  void test_percent() {
+    _assertToken(TokenType.PERCENT, "%");
+  }
+
+  void test_percent_eq() {
+    _assertToken(TokenType.PERCENT_EQ, "%=");
+  }
+
+  void test_period() {
+    _assertToken(TokenType.PERIOD, ".");
+  }
+
+  void test_period_period() {
+    _assertToken(TokenType.PERIOD_PERIOD, "..");
+  }
+
+  void test_period_period_period() {
+    _assertToken(TokenType.PERIOD_PERIOD_PERIOD, "...");
+  }
+
+  void test_periodAfterNumberNotIncluded_identifier() {
+    _assertTokens("42.isEven()", [
+      new StringToken(TokenType.INT, "42", 0),
+      new Token(TokenType.PERIOD, 2),
+      new StringToken(TokenType.IDENTIFIER, "isEven", 3),
+      new Token(TokenType.OPEN_PAREN, 9),
+      new Token(TokenType.CLOSE_PAREN, 10)
+    ]);
+  }
+
+  void test_periodAfterNumberNotIncluded_period() {
+    _assertTokens("42..isEven()", [
+      new StringToken(TokenType.INT, "42", 0),
+      new Token(TokenType.PERIOD_PERIOD, 2),
+      new StringToken(TokenType.IDENTIFIER, "isEven", 4),
+      new Token(TokenType.OPEN_PAREN, 10),
+      new Token(TokenType.CLOSE_PAREN, 11)
+    ]);
+  }
+
+  void test_plus() {
+    _assertToken(TokenType.PLUS, "+");
+  }
+
+  void test_plus_eq() {
+    _assertToken(TokenType.PLUS_EQ, "+=");
+  }
+
+  void test_plus_plus() {
+    _assertToken(TokenType.PLUS_PLUS, "++");
+  }
+
+  void test_question() {
+    _assertToken(TokenType.QUESTION, "?");
+  }
+
+  void test_question_dot() {
+    _assertToken(TokenType.QUESTION_PERIOD, "?.");
+  }
+
+  void test_question_question() {
+    _assertToken(TokenType.QUESTION_QUESTION, "??");
+  }
+
+  void test_question_question_eq() {
+    _assertToken(TokenType.QUESTION_QUESTION_EQ, "??=");
+  }
+
+  void test_scriptTag_withArgs() {
+    _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart -debug");
+  }
+
+  void test_scriptTag_withoutSpace() {
+    _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart");
+  }
+
+  void test_scriptTag_withSpace() {
+    _assertToken(TokenType.SCRIPT_TAG, "#! /bin/dart");
+  }
+
+  void test_semicolon() {
+    _assertToken(TokenType.SEMICOLON, ";");
+  }
+
+  void test_setSourceStart() {
+    int offsetDelta = 42;
+    _ErrorListener listener = new _ErrorListener();
+    Scanner scanner =
+        new _TestScanner(new SubSequenceReader("a", offsetDelta), listener);
+    scanner.setSourceStart(3, 9);
+    scanner.tokenize();
+    List<int> lineStarts = scanner.lineStarts;
+    expect(lineStarts, isNotNull);
+    expect(lineStarts.length, 3);
+    expect(lineStarts[2], 33);
+  }
+
+  void test_slash() {
+    _assertToken(TokenType.SLASH, "/");
+  }
+
+  void test_slash_eq() {
+    _assertToken(TokenType.SLASH_EQ, "/=");
+  }
+
+  void test_star() {
+    _assertToken(TokenType.STAR, "*");
+  }
+
+  void test_star_eq() {
+    _assertToken(TokenType.STAR_EQ, "*=");
+  }
+
+  void test_startAndEnd() {
+    Token token = _scan("a");
+    Token previous = token.previous;
+    expect(previous.next, token);
+    expect(previous.previous, previous);
+    Token next = token.next;
+    expect(next.next, next);
+    expect(next.previous, token);
+  }
+
+  void test_string_multi_double() {
+    _assertToken(TokenType.STRING, "\"\"\"line1\nline2\"\"\"");
+  }
+
+  void test_string_multi_embeddedQuotes() {
+    _assertToken(TokenType.STRING, "\"\"\"line1\n\"\"\nline2\"\"\"");
+  }
+
+  void test_string_multi_embeddedQuotes_escapedChar() {
+    _assertToken(TokenType.STRING, "\"\"\"a\"\"\\tb\"\"\"");
+  }
+
+  void test_string_multi_interpolation_block() {
+    _assertTokens("\"Hello \${name}!\"", [
+      new StringToken(TokenType.STRING, "\"Hello ", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 7),
+      new StringToken(TokenType.IDENTIFIER, "name", 9),
+      new Token(TokenType.CLOSE_CURLY_BRACKET, 13),
+      new StringToken(TokenType.STRING, "!\"", 14)
+    ]);
+  }
+
+  void test_string_multi_interpolation_identifier() {
+    _assertTokens("\"Hello \$name!\"", [
+      new StringToken(TokenType.STRING, "\"Hello ", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 7),
+      new StringToken(TokenType.IDENTIFIER, "name", 8),
+      new StringToken(TokenType.STRING, "!\"", 12)
+    ]);
+  }
+
+  void test_string_multi_single() {
+    _assertToken(TokenType.STRING, "'''string'''");
+  }
+
+  void test_string_multi_slashEnter() {
+    _assertToken(TokenType.STRING, "'''\\\n'''");
+  }
+
+  void test_string_multi_unterminated() {
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8,
+        "'''string", [new StringToken(TokenType.STRING, "'''string", 0)]);
+  }
+
+  void test_string_multi_unterminated_interpolation_block() {
+    _assertErrorAndTokens(
+        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8, "'''\${name", [
+      new StringToken(TokenType.STRING, "'''", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 3),
+      new StringToken(TokenType.IDENTIFIER, "name", 5),
+      new StringToken(TokenType.STRING, "", 9)
+    ]);
+  }
+
+  void test_string_multi_unterminated_interpolation_identifier() {
+    _assertErrorAndTokens(
+        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7, "'''\$name", [
+      new StringToken(TokenType.STRING, "'''", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
+      new StringToken(TokenType.IDENTIFIER, "name", 4),
+      new StringToken(TokenType.STRING, "", 8)
+    ]);
+  }
+
+  void test_string_raw_multi_double() {
+    _assertToken(TokenType.STRING, "r\"\"\"line1\nline2\"\"\"");
+  }
+
+  void test_string_raw_multi_single() {
+    _assertToken(TokenType.STRING, "r'''string'''");
+  }
+
+  void test_string_raw_multi_unterminated() {
+    String source = "r'''string";
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9,
+        source, [new StringToken(TokenType.STRING, source, 0)]);
+  }
+
+  void test_string_raw_simple_double() {
+    _assertToken(TokenType.STRING, "r\"string\"");
+  }
+
+  void test_string_raw_simple_single() {
+    _assertToken(TokenType.STRING, "r'string'");
+  }
+
+  void test_string_raw_simple_unterminated_eof() {
+    String source = "r'string";
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7,
+        source, [new StringToken(TokenType.STRING, source, 0)]);
+  }
+
+  void test_string_raw_simple_unterminated_eol() {
+    String source = "r'string";
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8,
+        "$source\n", [new StringToken(TokenType.STRING, source, 0)]);
+  }
+
+  void test_string_simple_double() {
+    _assertToken(TokenType.STRING, "\"string\"");
+  }
+
+  void test_string_simple_escapedDollar() {
+    _assertToken(TokenType.STRING, "'a\\\$b'");
+  }
+
+  void test_string_simple_interpolation_adjacentIdentifiers() {
+    _assertTokens("'\$a\$b'", [
+      new StringToken(TokenType.STRING, "'", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
+      new StringToken(TokenType.IDENTIFIER, "a", 2),
+      new StringToken(TokenType.STRING, "", 3),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
+      new StringToken(TokenType.IDENTIFIER, "b", 4),
+      new StringToken(TokenType.STRING, "'", 5)
+    ]);
+  }
+
+  void test_string_simple_interpolation_block() {
+    _assertTokens("'Hello \${name}!'", [
+      new StringToken(TokenType.STRING, "'Hello ", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 7),
+      new StringToken(TokenType.IDENTIFIER, "name", 9),
+      new Token(TokenType.CLOSE_CURLY_BRACKET, 13),
+      new StringToken(TokenType.STRING, "!'", 14)
+    ]);
+  }
+
+  void test_string_simple_interpolation_blockWithNestedMap() {
+    _assertTokens("'a \${f({'b' : 'c'})} d'", [
+      new StringToken(TokenType.STRING, "'a ", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 3),
+      new StringToken(TokenType.IDENTIFIER, "f", 5),
+      new Token(TokenType.OPEN_PAREN, 6),
+      new Token(TokenType.OPEN_CURLY_BRACKET, 7),
+      new StringToken(TokenType.STRING, "'b'", 8),
+      new Token(TokenType.COLON, 12),
+      new StringToken(TokenType.STRING, "'c'", 14),
+      new Token(TokenType.CLOSE_CURLY_BRACKET, 17),
+      new Token(TokenType.CLOSE_PAREN, 18),
+      new Token(TokenType.CLOSE_CURLY_BRACKET, 19),
+      new StringToken(TokenType.STRING, " d'", 20)
+    ]);
+  }
+
+  void test_string_simple_interpolation_firstAndLast() {
+    _assertTokens("'\$greeting \$name'", [
+      new StringToken(TokenType.STRING, "'", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
+      new StringToken(TokenType.IDENTIFIER, "greeting", 2),
+      new StringToken(TokenType.STRING, " ", 10),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 11),
+      new StringToken(TokenType.IDENTIFIER, "name", 12),
+      new StringToken(TokenType.STRING, "'", 16)
+    ]);
+  }
+
+  void test_string_simple_interpolation_identifier() {
+    _assertTokens("'Hello \$name!'", [
+      new StringToken(TokenType.STRING, "'Hello ", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 7),
+      new StringToken(TokenType.IDENTIFIER, "name", 8),
+      new StringToken(TokenType.STRING, "!'", 12)
+    ]);
+  }
+
+  void test_string_simple_interpolation_missingIdentifier() {
+    _assertTokens("'\$x\$'", [
+      new StringToken(TokenType.STRING, "'", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
+      new StringToken(TokenType.IDENTIFIER, "x", 2),
+      new StringToken(TokenType.STRING, "", 3),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
+      new StringToken(TokenType.STRING, "'", 4)
+    ]);
+  }
+
+  void test_string_simple_interpolation_nonIdentifier() {
+    _assertTokens("'\$1'", [
+      new StringToken(TokenType.STRING, "'", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
+      new StringToken(TokenType.STRING, "1'", 2)
+    ]);
+  }
+
+  void test_string_simple_single() {
+    _assertToken(TokenType.STRING, "'string'");
+  }
+
+  void test_string_simple_unterminated_eof() {
+    String source = "'string";
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 6,
+        source, [new StringToken(TokenType.STRING, source, 0)]);
+  }
+
+  void test_string_simple_unterminated_eol() {
+    String source = "'string";
+    _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 7,
+        "$source\r", [new StringToken(TokenType.STRING, source, 0)]);
+  }
+
+  void test_string_simple_unterminated_interpolation_block() {
+    _assertErrorAndTokens(
+        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 6, "'\${name", [
+      new StringToken(TokenType.STRING, "'", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 1),
+      new StringToken(TokenType.IDENTIFIER, "name", 3),
+      new StringToken(TokenType.STRING, "", 7)
+    ]);
+  }
+
+  void test_string_simple_unterminated_interpolation_identifier() {
+    _assertErrorAndTokens(
+        ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 5, "'\$name", [
+      new StringToken(TokenType.STRING, "'", 0),
+      new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
+      new StringToken(TokenType.IDENTIFIER, "name", 2),
+      new StringToken(TokenType.STRING, "", 6)
+    ]);
+  }
+
+  void test_tilde() {
+    _assertToken(TokenType.TILDE, "~");
+  }
+
+  void test_tilde_slash() {
+    _assertToken(TokenType.TILDE_SLASH, "~/");
+  }
+
+  void test_tilde_slash_eq() {
+    _assertToken(TokenType.TILDE_SLASH_EQ, "~/=");
+  }
+
+  void test_unclosedPairInInterpolation() {
+    _ErrorListener listener = new _ErrorListener();
+    _scanWithListener("'\${(}'", listener);
+  }
+
+  void _assertComment(TokenType commentType, String source,
+      {bool genericMethodComments: false}) {
+    //
+    // Test without a trailing end-of-line marker
+    //
+    Token token = _scan(source, genericMethodComments: genericMethodComments);
+    expect(token, isNotNull);
+    expect(token.type, TokenType.EOF);
+    Token comment = token.precedingComments;
+    expect(comment, isNotNull);
+    expect(comment.type, commentType);
+    expect(comment.offset, 0);
+    expect(comment.length, source.length);
+    expect(comment.lexeme, source);
+    //
+    // Test with a trailing end-of-line marker
+    //
+    token = _scan("$source\n", genericMethodComments: genericMethodComments);
+    expect(token, isNotNull);
+    expect(token.type, TokenType.EOF);
+    comment = token.precedingComments;
+    expect(comment, isNotNull);
+    expect(comment.type, commentType);
+    expect(comment.offset, 0);
+    expect(comment.length, source.length);
+    expect(comment.lexeme, source);
+  }
+
+  /**
+   * Assert that scanning the given [source] produces an error with the given
+   * code.
+   *
+   * [expectedError] the error that should be produced
+   * [expectedOffset] the string offset that should be associated with the error
+   * [source] the source to be scanned to produce the error
+   */
+  void _assertError(
+      ScannerErrorCode expectedError, int expectedOffset, String source,
+      [List<Object> arguments]) {
+    _ErrorListener listener = new _ErrorListener();
+    _scanWithListener(source, listener);
+    listener.assertErrors(
+        [new _TestError(expectedOffset, 1, expectedError, arguments)]);
+  }
+
+  /**
+   * Assert that scanning the given [source] produces an error with the given
+   * code, and also produces the given tokens.
+   *
+   * [expectedError] the error that should be produced
+   * [expectedOffset] the string offset that should be associated with the error
+   * [source] the source to be scanned to produce the error
+   * [expectedTokens] the tokens that are expected to be in the source
+   */
+  void _assertErrorAndTokens(ScannerErrorCode expectedError, int expectedOffset,
+      String source, List<Token> expectedTokens) {
+    _ErrorListener listener = new _ErrorListener();
+    Token token = _scanWithListener(source, listener);
+    listener
+        .assertErrors([new _TestError(expectedOffset, 1, expectedError, null)]);
+    _checkTokens(token, expectedTokens);
+  }
+
+  /**
+   * Assert that when scanned the given [source] contains a single keyword token
+   * with the same lexeme as the original source.
+   */
+  void _assertKeywordToken(String source) {
+    Token token = _scan(source);
+    expect(token, isNotNull);
+    expect(token.type, TokenType.KEYWORD);
+    expect(token.offset, 0);
+    expect(token.length, source.length);
+    expect(token.lexeme, source);
+    Object value = token.value();
+    expect(value is Keyword, isTrue);
+    expect((value as Keyword).syntax, source);
+    token = _scan(" $source ");
+    expect(token, isNotNull);
+    expect(token.type, TokenType.KEYWORD);
+    expect(token.offset, 1);
+    expect(token.length, source.length);
+    expect(token.lexeme, source);
+    value = token.value();
+    expect(value is Keyword, isTrue);
+    expect((value as Keyword).syntax, source);
+    expect(token.next.type, TokenType.EOF);
+  }
+
+  /**
+   * Assert that the token scanned from the given [source] has the
+   * [expectedType].
+   */
+  Token _assertToken(TokenType expectedType, String source,
+      {bool lazyAssignmentOperators: false}) {
+    Token originalToken =
+        _scan(source, lazyAssignmentOperators: lazyAssignmentOperators);
+    expect(originalToken, isNotNull);
+    expect(originalToken.type, expectedType);
+    expect(originalToken.offset, 0);
+    expect(originalToken.length, source.length);
+    expect(originalToken.lexeme, source);
+    if (expectedType == TokenType.SCRIPT_TAG) {
+      // Adding space before the script tag is not allowed, and adding text at
+      // the end changes nothing.
+      return originalToken;
+    } else if (expectedType == TokenType.SINGLE_LINE_COMMENT) {
+      // Adding space to an end-of-line comment changes the comment.
+      Token tokenWithSpaces =
+          _scan(" $source", lazyAssignmentOperators: lazyAssignmentOperators);
+      expect(tokenWithSpaces, isNotNull);
+      expect(tokenWithSpaces.type, expectedType);
+      expect(tokenWithSpaces.offset, 1);
+      expect(tokenWithSpaces.length, source.length);
+      expect(tokenWithSpaces.lexeme, source);
+      return originalToken;
+    } else if (expectedType == TokenType.INT ||
+        expectedType == TokenType.DOUBLE) {
+      Token tokenWithLowerD =
+          _scan("${source}d", lazyAssignmentOperators: lazyAssignmentOperators);
+      expect(tokenWithLowerD, isNotNull);
+      expect(tokenWithLowerD.type, expectedType);
+      expect(tokenWithLowerD.offset, 0);
+      expect(tokenWithLowerD.length, source.length);
+      expect(tokenWithLowerD.lexeme, source);
+      Token tokenWithUpperD =
+          _scan("${source}D", lazyAssignmentOperators: lazyAssignmentOperators);
+      expect(tokenWithUpperD, isNotNull);
+      expect(tokenWithUpperD.type, expectedType);
+      expect(tokenWithUpperD.offset, 0);
+      expect(tokenWithUpperD.length, source.length);
+      expect(tokenWithUpperD.lexeme, source);
+    }
+    Token tokenWithSpaces =
+        _scan(" $source ", lazyAssignmentOperators: lazyAssignmentOperators);
+    expect(tokenWithSpaces, isNotNull);
+    expect(tokenWithSpaces.type, expectedType);
+    expect(tokenWithSpaces.offset, 1);
+    expect(tokenWithSpaces.length, source.length);
+    expect(tokenWithSpaces.lexeme, source);
+    expect(originalToken.next.type, TokenType.EOF);
+    return originalToken;
+  }
+
+  /**
+   * Assert that when scanned the given [source] contains a sequence of tokens
+   * identical to the given list of [expectedTokens].
+   */
+  void _assertTokens(String source, List<Token> expectedTokens) {
+    Token token = _scan(source);
+    _checkTokens(token, expectedTokens);
+  }
+
+  void _checkTokens(Token firstToken, List<Token> expectedTokens) {
+    expect(firstToken, isNotNull);
+    Token token = firstToken;
+    for (int i = 0; i < expectedTokens.length; i++) {
+      Token expectedToken = expectedTokens[i];
+      expect(token.type, expectedToken.type, reason: "Wrong type for token $i");
+      expect(token.offset, expectedToken.offset,
+          reason: "Wrong offset for token $i");
+      expect(token.length, expectedToken.length,
+          reason: "Wrong length for token $i");
+      expect(token.lexeme, expectedToken.lexeme,
+          reason: "Wrong lexeme for token $i");
+      token = token.next;
+      expect(token, isNotNull);
+    }
+    expect(token.type, TokenType.EOF);
+  }
+
+  Token _scan(String source,
+      {bool genericMethodComments: false,
+      bool lazyAssignmentOperators: false}) {
+    _ErrorListener listener = new _ErrorListener();
+    Token token = _scanWithListener(source, listener,
+        genericMethodComments: genericMethodComments,
+        lazyAssignmentOperators: lazyAssignmentOperators);
+    listener.assertNoErrors();
+    return token;
+  }
+
+  Token _scanWithListener(String source, _ErrorListener listener,
+      {bool genericMethodComments: false,
+      bool lazyAssignmentOperators: false}) {
+    Scanner scanner =
+        new _TestScanner(new CharSequenceReader(source), listener);
+    scanner.scanGenericMethodComments = genericMethodComments;
+    scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
+    return scanner.tokenize();
+  }
+}
+
+@reflectiveTest
+class TokenTypeTest {
+  void test_isOperator() {
+    expect(TokenType.AMPERSAND.isOperator, isTrue);
+    expect(TokenType.AMPERSAND_AMPERSAND.isOperator, isTrue);
+    expect(TokenType.AMPERSAND_EQ.isOperator, isTrue);
+    expect(TokenType.BANG.isOperator, isTrue);
+    expect(TokenType.BANG_EQ.isOperator, isTrue);
+    expect(TokenType.BAR.isOperator, isTrue);
+    expect(TokenType.BAR_BAR.isOperator, isTrue);
+    expect(TokenType.BAR_EQ.isOperator, isTrue);
+    expect(TokenType.CARET.isOperator, isTrue);
+    expect(TokenType.CARET_EQ.isOperator, isTrue);
+    expect(TokenType.EQ.isOperator, isTrue);
+    expect(TokenType.EQ_EQ.isOperator, isTrue);
+    expect(TokenType.GT.isOperator, isTrue);
+    expect(TokenType.GT_EQ.isOperator, isTrue);
+    expect(TokenType.GT_GT.isOperator, isTrue);
+    expect(TokenType.GT_GT_EQ.isOperator, isTrue);
+    expect(TokenType.INDEX.isOperator, isTrue);
+    expect(TokenType.INDEX_EQ.isOperator, isTrue);
+    expect(TokenType.IS.isOperator, isTrue);
+    expect(TokenType.LT.isOperator, isTrue);
+    expect(TokenType.LT_EQ.isOperator, isTrue);
+    expect(TokenType.LT_LT.isOperator, isTrue);
+    expect(TokenType.LT_LT_EQ.isOperator, isTrue);
+    expect(TokenType.MINUS.isOperator, isTrue);
+    expect(TokenType.MINUS_EQ.isOperator, isTrue);
+    expect(TokenType.MINUS_MINUS.isOperator, isTrue);
+    expect(TokenType.PERCENT.isOperator, isTrue);
+    expect(TokenType.PERCENT_EQ.isOperator, isTrue);
+    expect(TokenType.PERIOD_PERIOD.isOperator, isTrue);
+    expect(TokenType.PLUS.isOperator, isTrue);
+    expect(TokenType.PLUS_EQ.isOperator, isTrue);
+    expect(TokenType.PLUS_PLUS.isOperator, isTrue);
+    expect(TokenType.QUESTION.isOperator, isTrue);
+    expect(TokenType.SLASH.isOperator, isTrue);
+    expect(TokenType.SLASH_EQ.isOperator, isTrue);
+    expect(TokenType.STAR.isOperator, isTrue);
+    expect(TokenType.STAR_EQ.isOperator, isTrue);
+    expect(TokenType.TILDE.isOperator, isTrue);
+    expect(TokenType.TILDE_SLASH.isOperator, isTrue);
+    expect(TokenType.TILDE_SLASH_EQ.isOperator, isTrue);
+  }
+
+  void test_isUserDefinableOperator() {
+    expect(TokenType.AMPERSAND.isUserDefinableOperator, isTrue);
+    expect(TokenType.BAR.isUserDefinableOperator, isTrue);
+    expect(TokenType.CARET.isUserDefinableOperator, isTrue);
+    expect(TokenType.EQ_EQ.isUserDefinableOperator, isTrue);
+    expect(TokenType.GT.isUserDefinableOperator, isTrue);
+    expect(TokenType.GT_EQ.isUserDefinableOperator, isTrue);
+    expect(TokenType.GT_GT.isUserDefinableOperator, isTrue);
+    expect(TokenType.INDEX.isUserDefinableOperator, isTrue);
+    expect(TokenType.INDEX_EQ.isUserDefinableOperator, isTrue);
+    expect(TokenType.LT.isUserDefinableOperator, isTrue);
+    expect(TokenType.LT_EQ.isUserDefinableOperator, isTrue);
+    expect(TokenType.LT_LT.isUserDefinableOperator, isTrue);
+    expect(TokenType.MINUS.isUserDefinableOperator, isTrue);
+    expect(TokenType.PERCENT.isUserDefinableOperator, isTrue);
+    expect(TokenType.PLUS.isUserDefinableOperator, isTrue);
+    expect(TokenType.SLASH.isUserDefinableOperator, isTrue);
+    expect(TokenType.STAR.isUserDefinableOperator, isTrue);
+    expect(TokenType.TILDE.isUserDefinableOperator, isTrue);
+    expect(TokenType.TILDE_SLASH.isUserDefinableOperator, isTrue);
+  }
+}
+
+class _ErrorListener {
+  final errors = <_TestError>[];
+
+  void assertErrors(List<_TestError> expectedErrors) {
+    expect(errors, unorderedEquals(expectedErrors));
+  }
+
+  void assertNoErrors() {
+    assertErrors([]);
+  }
+}
+
+class _TestError {
+  final int offset;
+  final int length;
+  final ErrorCode errorCode;
+  final List<Object> arguments;
+
+  _TestError(this.offset, this.length, this.errorCode, this.arguments);
+
+  @override
+  get hashCode {
+    var h = new JenkinsSmiHash()..add(offset)..add(length)..add(errorCode);
+    if (arguments != null) {
+      for (Object argument in arguments) {
+        h.add(argument);
+      }
+    }
+    return h.hashCode;
+  }
+
+  @override
+  operator ==(Object other) {
+    if (other is _TestError &&
+        offset == other.offset &&
+        length == other.length &&
+        errorCode == other.errorCode) {
+      if (arguments == null) return other.arguments == null;
+      if (other.arguments == null) return false;
+      if (arguments.length != other.arguments.length) return false;
+      for (int i = 0; i < arguments.length; i++) {
+        if (arguments[i] != other.arguments[i]) return false;
+      }
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  toString() {
+    var end = offset + length;
+    var argString = arguments == null ? '' : '(${arguments.join(', ')})';
+    return 'Error($offset..$end, $errorCode$argString)';
+  }
+}
+
+class _TestScanner extends Scanner {
+  final _ErrorListener listener;
+
+  _TestScanner(CharacterReader reader, [this.listener]) : super(reader);
+
+  @override
+  void reportError(
+      ScannerErrorCode errorCode, int offset, List<Object> arguments) {
+    if (listener != null) {
+      listener.errors.add(new _TestError(offset, 1, errorCode, arguments));
+    }
+  }
+}
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index ec306ca..4d61e9b 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.dart
@@ -9,15 +9,12 @@
 import 'dart:io' show exit, stderr;
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart'
     show PhysicalResourceProvider;
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -26,6 +23,10 @@
 import 'package:kernel/kernel.dart';
 import 'package:package_config/discovery.dart';
 
+import 'package:front_end/src/scanner/reader.dart';
+import 'package:front_end/src/scanner/scanner.dart';
+import 'package:front_end/src/scanner/token.dart';
+
 /// Cumulative total number of chars scanned.
 int scanTotalChars = 0;
 
@@ -205,13 +206,23 @@
   scanTotalChars += contents.length;
   // TODO(sigmund): is there a way to scan from a random-access-file without
   // first converting to String?
-  var scanner = new Scanner(source, new CharSequenceReader(contents),
-      AnalysisErrorListener.NULL_LISTENER)..preserveComments = false;
+  var scanner = new _Scanner(contents);
   var token = scanner.tokenize();
   scanTimer.stop();
   return token;
 }
 
+class _Scanner extends Scanner {
+  _Scanner(String contents) : super(new CharSequenceReader(contents)) {
+    preserveComments = false;
+  }
+
+  @override
+  void reportError(errorCode, int offset, List<Object> arguments) {
+    // ignore errors.
+  }
+}
+
 /// Report that metric [name] took [time] micro-seconds to process
 /// [scanTotalChars] characters.
 void report(String name, int time) {
diff --git a/pkg/pkg.status b/pkg/pkg.status
index ee9fe4a..01ed03e 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -57,6 +57,9 @@
 front_end/test/memory_file_system_test: CompileTimeError # Issue 23773
 front_end/test/physical_file_system_test: SkipByDesign # Uses dart:io
 
+[ $compiler == dart2js && $fast_startup ]
+front_end/test/*: SkipByDesign # Tests written with dart:mirrors.
+
 [ $compiler == dart2js && $builder_tag != dart2js_analyzer ]
 analyzer/test/*: Skip # Issue 26813
 analyzer/tool/*: Skip # Issue 26813
@@ -68,6 +71,7 @@
 [ $runtime == jsshell ]
 async/test/stream_zip_test: RuntimeError, OK # Issue 26103. Timers are not supported.
 lookup_map/test/lookup_map_test: RuntimeError, OK # Issue 26103. Timers are not supported.
+front_end/test/*: RuntimeError, OK # Issue 26103. Timers are not supported.
 
 [ $compiler == dart2js && $runtime == drt ]
 async/test/stream_zip_test: RuntimeError, Pass # Issue 18548
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index b5116d5..8556ba2 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -247,17 +247,6 @@
   ]
 }
 
-libdart_library("libdart_nosnapshot_precompiled_runtime") {
-  extra_configs = [
-    ":dart_no_snapshot_config",
-    ":dart_precompiled_runtime_config",
-  ]
-  extra_deps = [
-    "vm:libdart_lib_nosnapshot_precompiled_runtime",
-    "vm:libdart_vm_nosnapshot_precompiled_runtime",
-  ]
-}
-
 libdart_library("libdart_nosnapshot_with_precompiler") {
   extra_configs = [
     ":dart_no_snapshot_config",
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 49ebb05..cbc2006 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -110,7 +110,17 @@
 
 
 void Builtin::SetNativeResolver(BuiltinLibraryId id) {
-  UNREACHABLE();
+  ASSERT(static_cast<int>(id) >= 0);
+  ASSERT(static_cast<int>(id) < num_libs_);
+
+  if (builtin_libraries_[id].has_natives_) {
+    Dart_Handle url = DartUtils::NewString(builtin_libraries_[id].url_);
+    Dart_Handle library = Dart_LookupLibrary(url);
+    ASSERT(!Dart_IsError(library));
+    // Setup the native resolver for built in library functions.
+    DART_CHECK_VALID(
+        Dart_SetNativeResolver(library, NativeLookup, NativeSymbol));
+  }
 }
 
 
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index db8e1fa..cd005db 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -72,8 +72,10 @@
     DartUtils::ReadFile(&buffer, kernel_length, script_file);
     DartUtils::CloseFile(script_file);
     if (*kernel_length > 0 && buffer != NULL) {
-      *kernel_file = buffer;
-      if (DartUtils::SniffForMagicNumber(&buffer, kernel_length) !=
+      // We need a temporary variable because SniffForMagicNumber modifies the
+      // buffer pointer to skip snapshot magic number.
+      const uint8_t* temp = buffer;
+      if (DartUtils::SniffForMagicNumber(&temp, kernel_length) !=
           DartUtils::kKernelMagicNumber) {
         free(const_cast<uint8_t*>(buffer));
         *kernel_file = NULL;
@@ -83,6 +85,7 @@
         // Caller is responsible for freeing the buffer when this function
         // returns true.
         is_kernel_file = true;
+        *kernel_file = buffer;
       }
     }
   }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 17acc09..53babb7 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -1266,8 +1266,16 @@
     // Now we create an isolate into which we load all the code that needs to
     // be in the snapshot.
     isolate_data = new IsolateData(NULL, NULL, NULL);
-    if (Dart_CreateIsolate(NULL, NULL, NULL, NULL, isolate_data, &error) ==
-        NULL) {
+    const uint8_t* kernel = NULL;
+    intptr_t kernel_length = 0;
+    const bool is_kernel_file =
+        TryReadKernel(app_script_name, &kernel, &kernel_length);
+    Dart_Isolate isolate =
+        is_kernel_file
+            ? Dart_CreateIsolateFromKernel(NULL, NULL, kernel, kernel_length,
+                                           NULL, isolate_data, &error)
+            : Dart_CreateIsolate(NULL, NULL, NULL, NULL, isolate_data, &error);
+    if (isolate == NULL) {
       fprintf(stderr, "%s", error);
       free(error);
       exit(255);
@@ -1284,14 +1292,9 @@
     Dart_QualifiedFunctionName* entry_points =
         ParseEntryPointsManifestIfPresent();
 
-    intptr_t payload_bytes = 0;
-    const uint8_t* payload = NULL;
-    const bool is_kernel_file =
-        TryReadKernel(app_script_name, &payload, &payload_bytes);
-
     if (is_kernel_file) {
-      Dart_Handle library = Dart_LoadKernel(payload, payload_bytes);
-      free(const_cast<uint8_t*>(payload));
+      Dart_Handle library = Dart_LoadKernel(kernel, kernel_length);
+      free(const_cast<uint8_t*>(kernel));
       if (Dart_IsError(library)) FATAL("Failed to load app from Kernel IR");
     } else {
       // Set up the library tag handler in such a manner that it will use the
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index b481a67..21fde13 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -799,10 +799,26 @@
     return NULL;
   }
 
+  // If the script is a Kernel binary, then we will try to bootstrap from the
+  // script.
+  const uint8_t* kernel_file = NULL;
+  intptr_t kernel_length = -1;
+  const bool is_kernel =
+      !run_app_snapshot &&
+      TryReadKernel(script_uri, &kernel_file, &kernel_length);
+
   IsolateData* isolate_data =
       new IsolateData(script_uri, package_root, packages_config);
-  Dart_Isolate isolate = Dart_CreateIsolate(
-      script_uri, main, isolate_snapshot_buffer, flags, isolate_data, error);
+  Dart_Isolate isolate =
+      is_kernel ? Dart_CreateIsolateFromKernel(script_uri, main, kernel_file,
+                                               kernel_length, flags,
+                                               isolate_data, error)
+                : Dart_CreateIsolate(script_uri, main, isolate_snapshot_buffer,
+                                     flags, isolate_data, error);
+  if (is_kernel) {
+    free(const_cast<uint8_t*>(kernel_file));
+  }
+
   if (isolate == NULL) {
     delete isolate_data;
     return NULL;
@@ -810,7 +826,20 @@
 
   Dart_EnterScope();
 
-  if (isolate_snapshot_buffer != NULL) {
+  // Set up the library tag handler for this isolate.
+  Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
+  CHECK_RESULT(result);
+
+  if (is_kernel) {
+    // TODO(27590): We should not read the kernel file again!
+    if (!TryReadKernel(script_uri, &kernel_file, &kernel_length)) {
+      FATAL("Failed to read kernel second time");
+    }
+    Dart_Handle result = Dart_LoadKernel(kernel_file, kernel_length);
+    free(const_cast<uint8_t*>(kernel_file));
+    CHECK_RESULT(result);
+  }
+  if (is_kernel || (isolate_snapshot_buffer != NULL)) {
     // Setup the native resolver as the snapshot does not carry it.
     Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
     Builtin::SetNativeResolver(Builtin::kIOLibrary);
@@ -820,10 +849,6 @@
     CHECK_RESULT(result);
   }
 
-  // Set up the library tag handler for this isolate.
-  Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
-  CHECK_RESULT(result);
-
   if (Dart_IsServiceIsolate(isolate)) {
     // If this is the service isolate, load embedder specific bits and return.
     bool skip_library_load = run_app_snapshot;
@@ -872,8 +897,10 @@
     Dart_Handle uri =
         DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
     CHECK_RESULT(uri);
-    result = Loader::LibraryTagHandler(Dart_kScriptTag, Dart_Null(), uri);
-    CHECK_RESULT(result);
+    if (!is_kernel) {
+      result = Loader::LibraryTagHandler(Dart_kScriptTag, Dart_Null(), uri);
+      CHECK_RESULT(result);
+    }
 
     Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
                        Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
@@ -1835,6 +1862,9 @@
 
   if (gen_snapshot_kind == kAppJIT) {
     vm_options.AddArgument("--fields_may_be_reset");
+#if !defined(PRODUCT)
+    vm_options.AddArgument("--collect_code=false");
+#endif
   }
   if ((gen_snapshot_kind == kAppAOT) || is_noopt) {
     vm_options.AddArgument("--precompilation");
diff --git a/runtime/bin/platform_patch.dart b/runtime/bin/platform_patch.dart
index 8110ea1..c4b3481 100644
--- a/runtime/bin/platform_patch.dart
+++ b/runtime/bin/platform_patch.dart
@@ -28,7 +28,7 @@
       => VMLibraryHooks.packageConfigString;
 
   // This script singleton is written to by the embedder if applicable.
-  @patch static void set _nativeScript(String path) {
+  static void set _nativeScript(String path) {
     if (path.startsWith('http:') ||
         path.startsWith('https:') ||
         path.startsWith('package:') ||
diff --git a/runtime/bin/stdio_patch.dart b/runtime/bin/stdio_patch.dart
index 392ae1c..9478180 100644
--- a/runtime/bin/stdio_patch.dart
+++ b/runtime/bin/stdio_patch.dart
@@ -34,7 +34,7 @@
     return null;
   }
 
-  @patch static int _nativeSocketType(_NativeSocket nativeSocket) {
+  static int _nativeSocketType(_NativeSocket nativeSocket) {
     var result = _getSocketType(nativeSocket);
     if (result is OSError) {
       throw new FileSystemException(
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index da2dd8d..acbcba9 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -155,7 +155,8 @@
 bool VmService::LoadForGenPrecompiled() {
   Dart_Handle result;
   Dart_SetLibraryTagHandler(LibraryTagHandler);
-  Dart_Handle library = LoadLibrary(kVMServiceIOLibraryScriptResourceName);
+  Dart_Handle library =
+      LookupOrLoadLibrary(kVMServiceIOLibraryScriptResourceName);
   ASSERT(library != Dart_Null());
   SHUTDOWN_ON_ERROR(library);
   result = Dart_SetNativeResolver(library, VmServiceIONativeResolver, NULL);
@@ -314,10 +315,14 @@
 }
 
 
-Dart_Handle VmService::LoadLibrary(const char* name) {
+Dart_Handle VmService::LookupOrLoadLibrary(const char* name) {
   Dart_Handle uri = Dart_NewStringFromCString(kVMServiceIOLibraryUri);
-  Dart_Handle source = GetSource(name);
-  return Dart_LoadLibrary(uri, Dart_Null(), source, 0, 0);
+  Dart_Handle library = Dart_LookupLibrary(uri);
+  if (!Dart_IsLibrary(library)) {
+    Dart_Handle source = GetSource(name);
+    library = Dart_LoadLibrary(uri, Dart_Null(), source, 0, 0);
+  }
+  return library;
 }
 
 
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 9f9ce6b..8bdc81e 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -34,7 +34,7 @@
   static void SetServerAddress(const char* server_uri_);
   static Dart_Handle GetSource(const char* name);
   static Dart_Handle LoadScript(const char* name);
-  static Dart_Handle LoadLibrary(const char* name);
+  static Dart_Handle LookupOrLoadLibrary(const char* name);
   static Dart_Handle LoadSource(Dart_Handle library, const char* name);
   static Dart_Handle LoadResources(Dart_Handle library);
   static Dart_Handle LoadResource(Dart_Handle library, const char* name);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 652c7913..1a09f7b 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -873,7 +873,7 @@
  * \param error DOCUMENT
  *
  * \return The new isolate is returned. May be NULL if an error
- *   occurs duing isolate initialization.
+ *   occurs during isolate initialization.
  */
 DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri,
                                             const char* main,
@@ -885,6 +885,34 @@
  * isolate. */
 
 /**
+ * Creates a new isolate from a Dart Kernel file. The new isolate
+ * becomes the current isolate.
+ *
+ * Requires there to be no current isolate.
+ *
+ * \param script_uri The name of the script this isolate will load.
+ *   Provided only for advisory purposes to improve debugging messages.
+ * \param main The name of the main entry point this isolate will run.
+ *   Provided only for advisory purposes to improve debugging messages.
+ * \param kernel A buffer containing the Dart Kernel binary.
+ * \param kernel_length The length of the Kernel buffer.
+ * \param flags Pointer to VM specific flags or NULL for default flags.
+ * \param callback_data Embedder data.  This data will be passed to
+ *   the Dart_IsolateCreateCallback when new isolates are spawned from
+ *   this parent isolate.
+ * \param error DOCUMENT
+ *
+ * \return The new isolate is returned. May be NULL if an error
+ *   occurs during isolate initialization.
+ */
+DART_EXPORT Dart_Isolate Dart_CreateIsolateFromKernel(const char* script_uri,
+                                                      const char* main,
+                                                      const uint8_t* kernel,
+                                                      intptr_t kernel_length,
+                                                      Dart_IsolateFlags* flags,
+                                                      void* callback_data,
+                                                      char** error);
+/**
  * Shuts down the current isolate. After this call, the current isolate
  * is NULL. Invokes the shutdown callback and any callbacks of remaining
  * weak persistent handles.
diff --git a/runtime/lib/class_id.cc b/runtime/lib/class_id.cc
index 2d9f67d..c950b0e 100644
--- a/runtime/lib/class_id.cc
+++ b/runtime/lib/class_id.cc
@@ -13,4 +13,24 @@
   return Smi::New(instance.GetClassId());
 }
 
+
+DEFINE_NATIVE_ENTRY(ClassID_byName, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
+
+#define CLASS_LIST_WITH_NULL(V)                                                \
+  V(Null)                                                                      \
+  CLASS_LIST_NO_OBJECT(V)
+
+#define COMPARE(clazz)                                                         \
+  if (name.Equals(#clazz)) return Smi::New(k##clazz##Cid);
+
+  CLASS_LIST_WITH_NULL(COMPARE)
+
+#undef COMPARE
+#undef CLASS_LIST_WITH_NULL
+
+  UNREACHABLE();
+  return Smi::New(-1);
+}
+
 }  // namespace dart
diff --git a/runtime/lib/class_id.dart b/runtime/lib/class_id.dart
index 045cfa1..8a8d670 100644
--- a/runtime/lib/class_id.dart
+++ b/runtime/lib/class_id.dart
@@ -4,4 +4,14 @@
 
 class ClassID {
   static int getID(Object value) native "ClassID_getID";
+
+  static int _lookup(String name) native "ClassID_byName";
+
+  static final int cidArray = _lookup('Array');
+  static final int cidExternalOneByteString = _lookup('ExternalOneByteString');
+  static final int cidGrowableObjectArray = _lookup('GrowableObjectArray');
+  static final int cidImmutableArray = _lookup('ImmutableArray');
+  static final int cidOneByteString = _lookup('OneByteString');
+  static final int cidTwoByteString = _lookup('TwoByteString');
+  static final int cidBigint = _lookup('Bigint');
 }
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index 390079f..27770a9 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -117,7 +117,8 @@
       AbstractType::CheckedHandle(arguments->NativeArgAt(2));
   const String& dst_name = String::CheckedHandle(arguments->NativeArgAt(3));
   const String& error_msg = String::CheckedHandle(arguments->NativeArgAt(4));
-  const AbstractType& src_type = AbstractType::Handle(src_value.GetType());
+  const AbstractType& src_type =
+      AbstractType::Handle(src_value.GetType(Heap::kNew));
   Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
                                       error_msg);
   UNREACHABLE();
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index bf04059..2635802 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -103,7 +103,7 @@
 
   static _throwNew(int case_clause_pos) native "FallThroughError_throwNew";
 
-  @patch String toString() {
+  String toString() {
     return "'$_url': Switch case fall-through at line $_line.";
   }
 
@@ -273,6 +273,7 @@
     }
 
     StringBuffer msg_buf = new StringBuffer("NoSuchMethodError: ");
+    bool is_type_call = false;
     switch (level) {
       case _InvocationMirror._DYNAMIC: {
         if (_receiver == null) {
@@ -286,6 +287,13 @@
           if (_receiver is Function) {
             msg_buf.writeln("Closure call with mismatched arguments: "
                 "function '$memberName'");
+          } else if (_receiver is _Type && memberName == "call") {
+            is_type_call = true;
+            String name = _receiver.toString();
+            msg_buf.writeln("Attempted to use type '$name' as a function. "
+                "Since types do not define a method 'call', this is not "
+                "possible. Did you intend to call the $name constructor and "
+                "forget the 'new' operator?");
           } else {
             msg_buf.writeln("Class '${_receiver.runtimeType}' has no instance "
                 "$type_str '$memberName'$args_message.");
@@ -324,7 +332,8 @@
     }
 
     if (type == _InvocationMirror._METHOD) {
-      msg_buf.write("Tried calling: $memberName($arguments)");
+      String m = is_type_call ? "$_receiver" : "$memberName";
+      msg_buf.write("Tried calling: $m($arguments)");
     } else if (argumentCount == 0) {
       msg_buf.write("Tried calling: $memberName");
     } else if (type == _InvocationMirror._SETTER) {
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 48e579b..7a2efe0 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -1370,7 +1370,7 @@
 
 DEFINE_NATIVE_ENTRY(InstanceMirror_computeType, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
-  const AbstractType& type = AbstractType::Handle(instance.GetType());
+  const AbstractType& type = AbstractType::Handle(instance.GetType(Heap::kNew));
   // The static type of null is specified to be the bottom type, however, the
   // runtime type of null is the Null type, which we correctly return here.
   return type.Canonicalize();
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 276d0d2..6a7db55 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -123,7 +123,7 @@
   } else if (instance.IsDouble()) {
     return Type::Double();
   }
-  return instance.GetType();
+  return instance.GetType(Heap::kNew);
 }
 
 
@@ -147,8 +147,10 @@
   const Class& cls = Class::Handle(left.clazz());
   if (cls.IsClosureClass()) {
     // TODO(vegorov): provide faster implementation for closure classes.
-    const AbstractType& left_type = AbstractType::Handle(left.GetType());
-    const AbstractType& right_type = AbstractType::Handle(right.GetType());
+    const AbstractType& left_type =
+        AbstractType::Handle(left.GetType(Heap::kNew));
+    const AbstractType& right_type =
+        AbstractType::Handle(right.GetType(Heap::kNew));
     return Bool::Get(left_type.raw() == right_type.raw()).raw();
   }
 
@@ -182,7 +184,7 @@
     const char* result_str = is_instance_of ? "true" : "false";
     OS::Print("Native Object.instanceOf: result %s\n", result_str);
     const AbstractType& instance_type =
-        AbstractType::Handle(zone, instance.GetType());
+        AbstractType::Handle(zone, instance.GetType(Heap::kNew));
     OS::Print("  instance type: %s\n",
               String::Handle(zone, instance_type.Name()).ToCString());
     OS::Print("  test type: %s\n",
@@ -318,7 +320,7 @@
     const char* result_str = is_instance_of ? "true" : "false";
     OS::Print("Object.as: result %s\n", result_str);
     const AbstractType& instance_type =
-        AbstractType::Handle(zone, instance.GetType());
+        AbstractType::Handle(zone, instance.GetType(Heap::kNew));
     OS::Print("  instance type: %s\n",
               String::Handle(zone, instance_type.Name()).ToCString());
     OS::Print("  cast type: %s\n",
@@ -333,7 +335,7 @@
     ASSERT(caller_frame != NULL);
     const TokenPosition location = caller_frame->GetTokenPos();
     const AbstractType& instance_type =
-        AbstractType::Handle(zone, instance.GetType());
+        AbstractType::Handle(zone, instance.GetType(Heap::kNew));
     if (!type.IsInstantiated()) {
       // Instantiate type before reporting the error.
       type = type.InstantiateFrom(instantiator_type_arguments, NULL, NULL, NULL,
diff --git a/runtime/observatory/lib/object_graph.dart b/runtime/observatory/lib/object_graph.dart
index c2b4169..d1c171b 100644
--- a/runtime/observatory/lib/object_graph.dart
+++ b/runtime/observatory/lib/object_graph.dart
@@ -214,14 +214,19 @@
   static const int maxUnsignedDataPerByte = byteMask;
 }
 
+// Node indices for the root and sentinel nodes. Note that using 0 as the
+// sentinel means a newly allocated typed array comes initialized with all
+// elements as the sentinel.
+const ROOT = 1;
+const SENTINEL = 0;
+
 class ObjectVertex {
-  // 0 represents invalid/uninitialized, 1 is the root.
   final int _id;
   final ObjectGraph _graph;
 
   ObjectVertex._(this._id, this._graph);
 
-  bool get isRoot => _id == 1;
+  bool get isRoot => ROOT == _id;
 
   bool operator ==(other) => _id == other._id && _graph == other._graph;
   int get hashCode => _id;
@@ -272,7 +277,7 @@
     var parentId = _id;
     var domChildren = [];
 
-    for (var childId = 1; childId <= N; childId++) {
+    for (var childId = ROOT; childId <= N; childId++) {
       if (doms[childId] == parentId) {
         domChildren.add(new ObjectVertex._(childId, _graph));
       }
@@ -282,6 +287,81 @@
   }
 }
 
+// A node in the dominator tree where siblings with the same class are merged.
+// That is, a set of objects with the same cid whose parent chains in the
+// dominator tree have the same cids at each level. [id_] is the representative
+// object of this set. The other members of the set are found by walking the
+// mergedDomNext links until finding the sentinel node or a node with a
+// different class.
+class MergedObjectVertex {
+  final int _id;
+  final ObjectGraph _graph;
+
+  MergedObjectVertex._(this._id, this._graph);
+
+  bool get isRoot => ROOT == _id;
+
+  bool operator ==(other) => _id == other._id && _graph == other._graph;
+  int get hashCode => _id;
+
+  int get vmCid => _graph._cids[_id];
+
+  int get shallowSize {
+    var cids = _graph._cids;
+    var size = 0;
+    var sibling = _id;
+    while (sibling != SENTINEL &&
+           cids[sibling] == cids[_id]) {
+      size += _graph._shallowSizes[sibling];
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return size;
+  }
+  int get retainedSize {
+    var cids = _graph._cids;
+    var size = 0;
+    var sibling = _id;
+    while (sibling != SENTINEL &&
+           cids[sibling] == cids[_id]) {
+      size += _graph._retainedSizes[sibling];
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return size;
+  }
+  int get instanceCount {
+    var cids = _graph._cids;
+    var count = 0;
+    var sibling = _id;
+    while (sibling != SENTINEL &&
+           cids[sibling] == cids[_id]) {
+      count++;
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return count;
+  }
+
+  List<MergedObjectVertex> dominatorTreeChildren() {
+    var next = _graph._mergedDomNext;
+    var cids = _graph._cids;
+
+    var domChildren = [];
+    var prev = SENTINEL;
+    var child = _graph._mergedDomHead[_id];
+    // Walk the list of children and look for the representative objects, i.e.
+    // the first sibling of each cid.
+    while (child != SENTINEL) {
+      if (prev == SENTINEL ||
+          cids[prev] != cids[child]) {
+        domChildren.add(new MergedObjectVertex._(child, _graph));
+      }
+      prev = child;
+      child = next[child];
+    }
+
+    return domChildren;
+  }
+}
+
 class _SuccessorsIterable extends IterableBase<ObjectVertex> {
   final ObjectGraph _graph;
   final int _id;
@@ -345,7 +425,8 @@
   int get vertexCount => _N;
   int get edgeCount => _E;
 
-  ObjectVertex get root => new ObjectVertex._(1, this);
+  ObjectVertex get root => new ObjectVertex._(ROOT, this);
+  MergedObjectVertex get mergedRoot => new MergedObjectVertex._(ROOT, this);
   Iterable<ObjectVertex> get vertices => new _VerticesIterable(this);
 
   Iterable<ObjectVertex> getMostRetained({int classId, int limit}) {
@@ -381,10 +462,10 @@
       controller.add(["Finding depth-first order...", 30.0]);
       await new Future(() => _dfs());
 
-      controller.add(["Finding predecessors...", 45.0]);
+      controller.add(["Finding predecessors...", 40.0]);
       await new Future(() => _buildPredecessors());
 
-      controller.add(["Finding dominators...", 60.0]);
+      controller.add(["Finding dominators...", 50.0]);
       await new Future(() => _buildDominators());
 
       _firstPreds = null;
@@ -393,12 +474,21 @@
       _semi = null;
       _parent = null;
 
-      controller.add(["Finding retained sizes...", 75.0]);
+      controller.add(["Finding retained sizes...", 60.0]);
       await new Future(() => _calculateRetainedSizes());
 
       _vertex = null;
 
-      controller.add(["Loaded", 100.0]);
+      controller.add(["Linking dominator tree children...", 70.0]);
+      await new Future(() => _linkDominatorChildren());
+
+      controller.add(["Sorting dominator tree children...", 80.0]);
+      await new Future(() => _sortDominatorChildren());
+
+      controller.add(["Merging dominator tree siblings...", 90.0]);
+      await new Future(() => _mergeDominatorSiblings());
+
+      controller.add(["Processed", 100.0]);
       controller.close();
     }());
     return controller.stream;
@@ -431,6 +521,8 @@
   // Outputs.
   Uint32List _doms;
   Uint32List _retainedSizes;
+  Uint32List _mergedDomHead;
+  Uint32List _mergedDomNext;
 
   void _remapNodes() {
     var N = _N;
@@ -446,7 +538,7 @@
     stream.readUnsigned();
     _kObjectAlignment = stream.clampedUint32;
 
-    var id = 1;
+    var id = ROOT;
     while (stream.pendingBytes > 0) {
       stream.readUnsigned(); // addr
       addrToId.put(stream.high, stream.mid, stream.low, id);
@@ -466,8 +558,7 @@
     }
     assert(id == (N + 1));
 
-    var root = addrToId.get(0, 0, 0);
-    assert(root == 1);
+    assert(ROOT == addrToId.get(0, 0, 0));
 
     _E = E;
     _addrToId = addrToId;
@@ -503,7 +594,8 @@
           succs[edge] = childId;
           edge++;
         } else {
-          // Reference into VM isolate's heap.
+          throw new Exception(
+              "Heap snapshot contains an edge but lacks its target node");
         }
         stream.readUnsigned();
       }
@@ -512,8 +604,7 @@
     firstSuccs[id] = edge; // Extra entry for cheap boundary detection.
 
     assert(id == N + 1);
-    assert(edge <= E); // edge is smaller because E was computed before we knew
-    // if references pointed into the VM isolate
+    assert(edge == E);
 
     _E = edge;
     _firstSuccs = firstSuccs;
@@ -534,11 +625,10 @@
     var dfsNumber = 0;
 
     var stackTop = 0;
-    var root = 1;
 
     // Push root.
-    stackNodes[0] = root;
-    stackCurrentEdgePos[0] = firstSuccs[root];
+    stackNodes[0] = ROOT;
+    stackCurrentEdgePos[0] = firstSuccs[ROOT];
 
     while (stackTop >= 0) {
       var v = stackNodes[stackTop];
@@ -571,12 +661,12 @@
     }
 
     assert(dfsNumber == N);
-    for (var i = 1; i <= N; i++) {
-      assert(semi[i] != 0);
+    for (var i = ROOT; i <= N; i++) {
+      assert(semi[i] != SENTINEL);
     }
-    assert(parent[1] == 0);
-    for (var i = 2; i <= N; i++) {
-      assert(parent[i] != 0);
+    assert(parent[ROOT] == SENTINEL);
+    for (var i = ROOT + 1; i <= N; i++) {
+      assert(parent[i] != SENTINEL);
     }
 
     _vertex = vertex;
@@ -636,7 +726,7 @@
 
   static int _eval(int v, Uint32List ancestor, Uint32List semi,
       Uint32List label, Uint32List stackNode, Uint8List stackState) {
-    if (ancestor[v] == 0) {
+    if (ancestor[v] == SENTINEL) {
       return label[v];
     } else {
       {
@@ -719,7 +809,6 @@
     var firstPreds = _firstPreds;
     var preds = _preds;
 
-    var root = 1;
     var dom = new Uint32List(N + 1);
 
     var ancestor = new Uint32List(N + 1);
@@ -738,7 +827,7 @@
 
     for (var i = N; i > 1; i--) {
       var w = vertex[i];
-      assert(w != root);
+      assert(w != ROOT);
 
       // Lengauer & Tarjan Step 2.
       var startPred = firstPreds[w];
@@ -771,7 +860,7 @@
         }
       }
     }
-    for (var i = 1; i <= N; i++) {
+    for (var i = ROOT; i <= N; i++) {
       assert(buckets[i] == null);
     }
     // Lengauer & Tarjan Step 4.
@@ -794,7 +883,7 @@
     var doms = _doms;
 
     // Sum shallow sizes.
-    for (var i = 1; i < N; i++) {
+    for (var i = ROOT; i < N; i++) {
       size += shallowSizes[i];
     }
 
@@ -805,11 +894,172 @@
     // size, skipping root.
     for (var i = N; i > 1; i--) {
       var v = vertex[i];
-      assert(v != 1);
+      assert(v != ROOT);
       retainedSizes[doms[i]] += retainedSizes[i];
     }
 
     _retainedSizes = retainedSizes;
     _size = size;
   }
+
+  // Build linked lists of the children for each node in the dominator tree.
+  void _linkDominatorChildren() {
+    var N = _N;
+    var doms = _doms;
+    var head = new Uint32List(N + 1);
+    var next = new Uint32List(N + 1);
+
+    for (var child = ROOT; child <= N; child++) {
+      var parent = doms[child];
+      next[child] = head[parent];
+      head[parent] = child;
+    }
+
+    _mergedDomHead = head;
+    _mergedDomNext = next;
+  }
+
+  // Merge the given lists according to the given key in ascending order.
+  // Returns the head of the merged list.
+  static int _mergeSorted(int head1, int head2,
+                          Uint32List next, Uint16List key) {
+    var head = head1;
+    var beforeInsert = SENTINEL;
+    var afterInsert = head1;
+    var startInsert = head2;
+
+    while (startInsert != SENTINEL) {
+      while ((afterInsert != SENTINEL) &&
+             (key[afterInsert] <= key[startInsert])) {
+        beforeInsert = afterInsert;
+        afterInsert = next[beforeInsert];
+      }
+
+      var endInsert = startInsert;
+      var peek = next[endInsert];
+
+      while ((peek != SENTINEL) && (key[peek] < key[afterInsert])) {
+        endInsert = peek;
+        peek = next[endInsert];
+      }
+      assert(endInsert != SENTINEL);
+
+      if (beforeInsert == SENTINEL) {
+        head = startInsert;
+      } else {
+        next[beforeInsert] = startInsert;
+      }
+      next[endInsert] = afterInsert;
+
+      startInsert = peek;
+      beforeInsert = endInsert;
+    }
+
+    return head;
+  }
+
+  void _sortDominatorChildren() {
+    var N = _N;
+    var cids = _cids;
+    var head = _mergedDomHead;
+    var next = _mergedDomNext;
+
+    // Returns the new head of the sorted list.
+    int sort(int head) {
+      if (head == SENTINEL) return SENTINEL;
+      if (next[head] == SENTINEL) return head;
+
+      // Find the middle of the list.
+      int head1 = head;
+      int slow = head;
+      int fast = head;
+      while (next[fast] != SENTINEL &&
+             next[next[fast]] != SENTINEL) {
+        slow = next[slow];
+        fast = next[next[fast]];
+      }
+
+      // Split the list in half.
+      int head2 = next[slow];
+      next[slow] = SENTINEL;
+
+      // Recursively sort the sublists and merge.
+      assert(head1 != head2);
+      int newHead1 = sort(head1);
+      int newHead2 = sort(head2);
+      return _mergeSorted(newHead1, newHead2, next, cids);
+    }
+
+    // Sort all list of dominator tree children by cid.
+    for (var parent = ROOT; parent <= N; parent++) {
+      head[parent] = sort(head[parent]);
+    }
+  }
+
+  void _mergeDominatorSiblings() {
+    var N = _N;
+    var cids = _cids;
+    var head = _mergedDomHead;
+    var next = _mergedDomNext;
+    var workStack = new Uint32List(N);
+    var workStackTop = 0;
+
+    mergeChildrenAndSort(var parent1, var end) {
+      assert(parent1 != SENTINEL);
+      if (next[parent1] == end) return;
+
+      // Find the middle of the list.
+      int cid = cids[parent1];
+      int slow = parent1;
+      int fast = parent1;
+      while (next[fast] != end &&
+             next[next[fast]] != end) {
+        slow = next[slow];
+        fast = next[next[fast]];
+      }
+
+      int parent2 = next[slow];
+
+      assert(parent2 != SENTINEL);
+      assert(parent1 != parent2);
+      assert(cids[parent1] == cids[parent2]);
+
+      // Recursively sort the sublists.
+      mergeChildrenAndSort(parent1, parent2);
+      mergeChildrenAndSort(parent2, end);
+
+      // Merge sorted sublists.
+      head[parent1] = _mergeSorted(head[parent1], head[parent2], next, cids);
+
+      // Children moved to parent1.
+      head[parent2] = SENTINEL;
+    }
+
+    // Push root.
+    workStack[workStackTop++] = ROOT;
+
+    while (workStackTop > 0) {
+      var parent = workStack[--workStackTop];
+
+      var prev = SENTINEL;
+      var child = head[parent];
+      while (child != SENTINEL) {
+        // Push child.
+        workStack[workStackTop++] = child;
+
+        // Find next sibling with a different cid.
+        var after = child;
+        while (after != SENTINEL &&
+               cids[after] == cids[child]) {
+          after = next[after];
+        }
+
+        // From all the siblings between child and after, take their children,
+        // merge them and given to child.
+        mergeChildrenAndSort(child, after);
+
+        child = after;
+      }
+    }
+  }
 }
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
index 03e6cc6..a4b73ff 100644
--- a/runtime/observatory/lib/repositories.dart
+++ b/runtime/observatory/lib/repositories.dart
@@ -13,7 +13,6 @@
 import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart' as S;
 import 'package:observatory/service_common.dart' as SC;
-import 'package:observatory/utils.dart';
 
 part 'src/repositories/allocation_profile.dart';
 part 'src/repositories/breakpoint.dart';
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
index 2fd6e78..7389daa 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
@@ -24,7 +24,7 @@
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/utils.dart';
 
-enum HeapSnapshotTreeMode { dominatorTree, groupByClass }
+enum HeapSnapshotTreeMode { dominatorTree, mergedDominatorTree, groupByClass }
 
 class HeapSnapshotElement extends HtmlElement implements Renderable {
   static const tag =
@@ -266,6 +266,23 @@
           _tree
         ]);
         break;
+      case HeapSnapshotTreeMode.mergedDominatorTree:
+        _tree = new VirtualTreeElement(
+            _createMergedDominator, _updateMergedDominator,
+            _getChildrenMergedDominator,
+            items: _getChildrenMergedDominator(_snapshot.mergedDominatorTree),
+            queue: _r.queue);
+        _tree.expand(_snapshot.mergedDominatorTree);
+        final text = 'A heap dominator tree, where siblings with the same class'
+                     ' have been merged into a single node.';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text
+            ..title = text,
+          _tree
+        ]);
+        break;
       case HeapSnapshotTreeMode.groupByClass:
         final items = _snapshot.classReferences.toList();
         items.sort((a, b) => b.shallowSize - a.shallowSize);
@@ -299,6 +316,24 @@
       ];
   }
 
+  static Element _createMergedDominator(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = [
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size',
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap being retained',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
   static Element _createGroup(toggle) {
     return new DivElement()
       ..classes = ['tree-item']
@@ -327,6 +362,13 @@
         .where((child) => child.retainedSize >= kMinRetainedSize)
         .take(kMaxChildren);
   }
+  static _getChildrenMergedDominator(M.HeapSnapshotMergedDominatorNode node) {
+    final list = node.children.toList();
+    list.sort((a, b) => b.retainedSize - a.retainedSize);
+    return list
+        .where((child) => child.retainedSize >= kMinRetainedSize)
+        .take(kMaxChildren);
+  }
 
   static _getChildrenGroup(item) {
     if (item is M.HeapSnapshotClassReferences) {
@@ -361,6 +403,31 @@
     });
   }
 
+  void _updateMergedDominator(
+      HtmlElement element, M.HeapSnapshotMergedDominatorNode node, int depth) {
+    element.children[0].text = Utils.formatSize(node.retainedSize);
+    _updateLines(element.children[1].children, depth);
+    if (_getChildrenMergedDominator(node).isNotEmpty) {
+      element.children[2].text = _tree.isExpanded(node) ? 'â–¼' : 'â–º';
+    } else {
+      element.children[2].text = '';
+    }
+    element.children[3].text =
+        Utils.formatPercentNormalized(node.retainedSize * 1.0 / _snapshot.size);
+    final wrapper = new SpanElement()
+      ..classes = ['name']
+      ..text = 'Loading...';
+    element.children[4] = wrapper;
+    node.klass.then((klass) {
+      wrapper
+        ..text = ''
+        ..children = [
+          new SpanElement()..text = '${node.instanceCount} instances of ',
+          anyRef(_isolate, klass, _instances, queue: _r.queue)
+        ];
+    });
+  }
+
   void _updateGroup(HtmlElement element, item, int depth) {
     _updateLines(element.children[1].children, depth);
     if (item is M.HeapSnapshotClassReferences) {
@@ -424,6 +491,8 @@
     switch (mode) {
       case HeapSnapshotTreeMode.dominatorTree:
         return 'Dominator tree';
+      case HeapSnapshotTreeMode.mergedDominatorTree:
+        return 'Dominator tree (merged siblings by class)';
       case HeapSnapshotTreeMode.groupByClass:
         return 'Group by class';
     }
diff --git a/runtime/observatory/lib/src/heap_snapshot/heap_snapshot.dart b/runtime/observatory/lib/src/heap_snapshot/heap_snapshot.dart
index 5345d8c..2d7abcd 100644
--- a/runtime/observatory/lib/src/heap_snapshot/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/heap_snapshot/heap_snapshot.dart
@@ -11,6 +11,7 @@
   int get references => graph.edgeCount;
   int get size => graph.size;
   HeapSnapshotDominatorNode dominatorTree;
+  HeapSnapshotMergedDominatorNode mergedDominatorTree;
   List<MergedVertex> classReferences;
 
   static Future sleep([Duration duration = const Duration(microseconds: 0)]) {
@@ -36,6 +37,8 @@
       });
       await stream.last;
       dominatorTree = new HeapSnapshotDominatorNode(isolate, graph.root);
+      mergedDominatorTree =
+          new HeapSnapshotMergedDominatorNode(isolate, graph.mergedRoot);
       classReferences = await buildMergedVertices(isolate, graph, signal);
       progress.close();
     }());
@@ -151,6 +154,36 @@
         v = vertex;
 }
 
+class HeapSnapshotMergedDominatorNode
+    implements M.HeapSnapshotMergedDominatorNode {
+  final MergedObjectVertex v;
+  final S.Isolate isolate;
+
+  Future<S.HeapObject> get klass {
+    return new Future.value(isolate.getClassByCid(v.vmCid));
+  }
+
+  Iterable<HeapSnapshotMergedDominatorNode> _children;
+  Iterable<HeapSnapshotMergedDominatorNode> get children {
+    if (_children != null) {
+      return _children;
+    } else {
+      return _children =
+          new List.unmodifiable(v.dominatorTreeChildren().map((v) {
+        return new HeapSnapshotMergedDominatorNode(isolate, v);
+      }));
+    }
+  }
+
+  int get instanceCount => v.instanceCount;
+  int get retainedSize => v.retainedSize;
+  int get shallowSize => v.shallowSize;
+
+  HeapSnapshotMergedDominatorNode(S.Isolate isolate, MergedObjectVertex vertex)
+      : isolate = isolate,
+        v = vertex;
+}
+
 class MergedEdge {
   final MergedVertex sourceVertex;
   final MergedVertex targetVertex;
diff --git a/runtime/observatory/lib/src/models/objects/heap_snapshot.dart b/runtime/observatory/lib/src/models/objects/heap_snapshot.dart
index 19392f9..ff4cefe 100644
--- a/runtime/observatory/lib/src/models/objects/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/models/objects/heap_snapshot.dart
@@ -10,6 +10,7 @@
   int get references;
   int get size;
   HeapSnapshotDominatorNode get dominatorTree;
+  HeapSnapshotMergedDominatorNode get mergedDominatorTree;
   Iterable<HeapSnapshotClassReferences> get classReferences;
 }
 
@@ -20,6 +21,14 @@
   Iterable<HeapSnapshotDominatorNode> get children;
 }
 
+abstract class HeapSnapshotMergedDominatorNode {
+  int get instanceCount;
+  int get shallowSize;
+  int get retainedSize;
+  Future<ObjectRef> get klass;
+  Iterable<HeapSnapshotMergedDominatorNode> get children;
+}
+
 abstract class HeapSnapshotClassReferences {
   ClassRef get clazz;
   int get instances;
diff --git a/runtime/observatory/tests/observatory_ui/observatory_ui.status b/runtime/observatory/tests/observatory_ui/observatory_ui.status
index 1b96aa6..a5665d5 100644
--- a/runtime/observatory/tests/observatory_ui/observatory_ui.status
+++ b/runtime/observatory/tests/observatory_ui/observatory_ui.status
@@ -14,6 +14,7 @@
 allocation_profile: Skip
 cpu_profile_table: Skip
 persistent_handles_page: Skip
+vm_connect/element_test: Skip # See issue 27714
 
 [ $runtime == ff || $runtime == chrome ]
-vm_connect/element_test: Skip # Times out
\ No newline at end of file
+vm_connect/element_test: Skip # Times out
diff --git a/runtime/observatory/tests/service/issue_27238_test.dart b/runtime/observatory/tests/service/issue_27238_test.dart
index 07cf335..77302ae 100644
--- a/runtime/observatory/tests/service/issue_27238_test.dart
+++ b/runtime/observatory/tests/service/issue_27238_test.dart
@@ -3,17 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug
 
-import 'package:observatory/service_io.dart';
 import 'service_test_common.dart';
 import 'dart:async';
 import 'test_helper.dart';
 import 'dart:developer';
 
-const int LINE_A = 20;
-const int LINE_B = 23;
-const int LINE_C = 24;
-const int LINE_D = 26;
-const int LINE_E = 27;
+const int LINE_A = 19;
+const int LINE_B = 22;
+const int LINE_C = 23;
+const int LINE_D = 25;
+const int LINE_E = 26;
 
 testMain() async {
   debugger();
diff --git a/runtime/observatory/tests/service/issue_27287_test.dart b/runtime/observatory/tests/service/issue_27287_test.dart
index 58633b33..85d3e97 100644
--- a/runtime/observatory/tests/service/issue_27287_test.dart
+++ b/runtime/observatory/tests/service/issue_27287_test.dart
@@ -3,14 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug
 
-import 'package:observatory/service_io.dart';
 import 'service_test_common.dart';
-import 'dart:async';
 import 'test_helper.dart';
 import 'dart:developer';
 
-const int LINE_A = 19;
-const int LINE_B = 20;
+const int LINE_A = 17;
+const int LINE_B = 18;
 
 var libVariable;
 
diff --git a/runtime/observatory/tests/service/reload_sources_test.dart b/runtime/observatory/tests/service/reload_sources_test.dart
index 4c8b4d9..64f5eac 100644
--- a/runtime/observatory/tests/service/reload_sources_test.dart
+++ b/runtime/observatory/tests/service/reload_sources_test.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--error_on_bad_type --error_on_bad_override
 
-import 'package:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
 import 'dart:developer';
 import 'service_test_common.dart';
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 8cdaef3..638f447 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -20,7 +20,6 @@
 debugger_location_second_test: Pass, Slow
 debugger_location_test: Pass, Slow
 
-
 # Disable on simulators.
 [ $arch == simarm || $arch == simmips || $arch == simarm64 ]
 *: SkipSlow
@@ -43,13 +42,18 @@
 [ $runtime == vm ]
 developer_extension_test: Pass, Fail # Issue 27225
 
-# Service protocol is not supported in product mode.
-[ $mode == product ]
-*: SkipByDesign
-
-# Service protocol is not supported when running a full application snapshot.
 [ $runtime == dart_app ]
-*: SkipByDesign
+address_mapper_test: CompileTimeError # Issue 27806
+capture_stdio_test: CompileTimeError # Issue 27806
+debugger_location_second_test: RuntimeError # Issue 27806
+dev_fs_spawn_test: RuntimeError # Issue 27806
+developer_extension_test: RuntimeError # Issue 27806
+evaluate_activation_test/instance: RuntimeError # Issue 27806
+evaluate_activation_test/scope: RuntimeError # Issue 27806
+get_object_rpc_test: RuntimeError # Issue 27806
+get_source_report_test: RuntimeError # Issue 27806
+set_name_rpc_test: RuntimeError # Issue 27806
+vm_restart_test: CompileTimeError # Issue 27806
 
 [ $compiler == dart2analyzer ]
 evaluate_activation_in_method_class_test: CompileTimeError # Issue 24478
@@ -66,3 +70,7 @@
 [ $system == windows ]
 dev_fs_weird_char_test: Skip # Windows disallows question mark in paths
 dev_fs_http_put_weird_char_test: Skip # Windows disallows carriage returns in paths
+
+# Service protocol is not supported in product mode.
+[ $mode == product ]
+*: SkipByDesign
diff --git a/runtime/observatory/tests/service/step_test.dart b/runtime/observatory/tests/service/step_test.dart
new file mode 100644
index 0000000..47009dc
--- /dev/null
+++ b/runtime/observatory/tests/service/step_test.dart
@@ -0,0 +1,38 @@
+import 'dart:async';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+const int LINE_A = 10;
+
+code() {
+  var x = {}; // LINE_A
+}
+
+Future<Isolate> stepThroughProgram(Isolate isolate) async {
+  Completer completer = new Completer();
+  int pauseEventsSeen = 0;
+
+  await subscribeToStream(isolate.vm, VM.kDebugStream,
+      (ServiceEvent event) async {
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      // We are paused: Step further.
+      pauseEventsSeen++;
+      isolate.stepInto();
+    } else if (event.kind == ServiceEvent.kPauseExit) {
+      // We are at the exit: The test is done.
+      expect(pauseEventsSeen > 20, true,
+          reason: "Saw only $pauseEventsSeen pause events.");
+      await cancelStreamSubscription(VM.kDebugStream);
+      completer.complete();
+    }
+  });
+  isolate.resume();
+  return completer.future;
+}
+
+var tests = [hasPausedAtStart, setBreakpointAtLine(LINE_A), stepThroughProgram];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 7ff1030..61d2bac 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -8,7 +8,6 @@
 cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: Fail, Crash
 cc/IsolateReload_PendingStaticCall_DefinedToNSM: Fail, Crash
 cc/IsolateReload_PendingStaticCall_NSMToDefined: Fail, Crash
-cc/IsolateReload_EnumDelete: Skip # Issue 27802
 
 # These tests are expected to crash on all platforms.
 cc/ArrayNew_Overflow_Crash: Crash, Timeout
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index e0eab68..8e47ef7 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -102,22 +102,6 @@
   include_dirs = [ ".." ]
 }
 
-static_library("libdart_vm_nosnapshot_precompiled_runtime") {
-  configs += [
-    "..:dart_config",
-    "..:dart_maybe_product_config",
-    "..:dart_precompiled_runtime_config",
-    "..:dart_no_snapshot_config",
-  ]
-  public_configs = [ ":libdart_vm_config" ]
-  set_sources_assignment_filter([
-                                  "*_test.cc",
-                                  "*_test.h",
-                                ])
-  sources = vm_sources_list
-  include_dirs = [ ".." ]
-}
-
 static_library("libdart_vm_nosnapshot_with_precompiler") {
   configs += [
     "..:dart_config",
@@ -239,16 +223,6 @@
     sources = all_libsources + [ "bootstrap.cc" ] + liboutputs
     include_dirs = [ ".." ]
   }
-  static_library("libdart_lib_nosnapshot_precompiled_runtime") {
-    configs += [
-      "..:dart_config",
-      "..:dart_maybe_product_config",
-      "..:dart_precompiled_runtime_config",
-    ]
-    deps = libdeps
-    sources = all_libsources + [ "bootstrap.cc" ] + liboutputs
-    include_dirs = [ ".." ]
-  }
   static_library("libdart_lib_nosnapshot_with_precompiler") {
     configs += [
       "..:dart_config",
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 168471c..0013157 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -291,6 +291,18 @@
         call->set_ic_data(&ic_data);
         if (has_unique_no_such_method_) {
           call->set_has_unique_selector(true);
+          // Add redefinition of the receiver to prevent code motion across
+          // this call.
+          RedefinitionInstr* redefinition =
+              new (Z) RedefinitionInstr(new (Z) Value(call->ArgumentAt(0)));
+          redefinition->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
+          redefinition->InsertAfter(call);
+          // Replace all uses of the receiver dominated by this call.
+          FlowGraph::RenameDominatedUses(call->ArgumentAt(0), redefinition,
+                                         redefinition);
+          if (!redefinition->HasUses()) {
+            redefinition->RemoveFromGraph();
+          }
         }
         return true;
       }
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index d242edab..5b4c20f 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -10,6 +10,10 @@
 #include "vm/class_finalizer.h"
 #include "vm/compiler.h"
 #include "vm/dart_api_impl.h"
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/kernel.h"
+#include "vm/kernel_reader.h"
+#endif
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/symbols.h"
@@ -244,6 +248,24 @@
 }
 
 
+static void Finish(Thread* thread, bool from_kernel) {
+  Bootstrap::SetupNativeResolver();
+  if (!ClassFinalizer::ProcessPendingClasses(from_kernel)) {
+    FATAL("Error in class finalization during bootstrapping.");
+  }
+
+  // Eagerly compile the _Closure class as it is the class of all closure
+  // instances. This allows us to just finalize function types without going
+  // through the hoops of trying to compile their scope class.
+  ObjectStore* object_store = thread->isolate()->object_store();
+  Class& cls = Class::Handle(thread->zone(), object_store->closure_class());
+  Compiler::CompileClass(cls);
+  // Eagerly compile Bool class, bool constants are used from within compiler.
+  cls = object_store->bool_class();
+  Compiler::CompileClass(cls);
+}
+
+
 static RawError* BootstrapFromSource(Thread* thread) {
   Isolate* isolate = thread->isolate();
   Zone* zone = thread->zone();
@@ -285,19 +307,8 @@
   }
 
   if (error.IsNull()) {
-    Bootstrap::SetupNativeResolver();
-    ClassFinalizer::ProcessPendingClasses();
-
-    // Eagerly compile the _Closure class as it is the class of all closure
-    // instances. This allows us to just finalize function types
-    // without going through the hoops of trying to compile their scope class.
-    Class& cls = Class::Handle(zone, isolate->object_store()->closure_class());
-    Compiler::CompileClass(cls);
-    // Eagerly compile Bool class, bool constants are used from within compiler.
-    cls = isolate->object_store()->bool_class();
-    Compiler::CompileClass(cls);
+    Finish(thread, /*from_kernel=*/false);
   }
-
   // Restore the library tag handler for the isolate.
   isolate->set_library_tag_handler(saved_tag_handler);
 
@@ -305,7 +316,65 @@
 }
 
 
-RawError* Bootstrap::DoBootstrapping() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+static RawError* BootstrapFromKernel(Thread* thread,
+                                     const uint8_t* buffer,
+                                     intptr_t buffer_size) {
+  Zone* zone = thread->zone();
+  kernel::Program* program =
+      ReadPrecompiledKernelFromBuffer(buffer, buffer_size);
+  if (program == NULL) {
+    const String& message =
+        String::Handle(zone, String::New("Failed to read Kernel file"));
+    return ApiError::New(message);
+  }
+
+  Isolate* isolate = thread->isolate();
+  // Mark the already-pending classes.  This mark bit will be used to avoid
+  // adding classes to the list more than once.
+  GrowableObjectArray& pending_classes = GrowableObjectArray::Handle(
+      zone, isolate->object_store()->pending_classes());
+  dart::Class& pending = dart::Class::Handle(zone);
+  for (intptr_t i = 0; i < pending_classes.Length(); ++i) {
+    pending ^= pending_classes.At(i);
+    pending.set_is_marked_for_parsing();
+  }
+
+  Library& library = Library::Handle(zone);
+  String& dart_name = String::Handle(zone);
+  String& kernel_name = String::Handle(zone);
+  kernel::KernelReader reader(NULL, -1, true);
+  for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
+    ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
+    library = isolate->object_store()->bootstrap_library(id);
+    dart_name = library.url();
+    for (intptr_t j = 0; j < program->libraries().length(); ++j) {
+      kernel::Library* kernel_library = program->libraries()[j];
+      kernel::String* uri = kernel_library->import_uri();
+      kernel_name = Symbols::FromUTF8(thread, uri->buffer(), uri->size());
+      if (kernel_name.Equals(dart_name)) {
+        reader.ReadLibrary(kernel_library);
+        library.SetLoaded();
+        break;
+      }
+    }
+  }
+
+  Finish(thread, /*from_kernel=*/true);
+  return Error::null();
+}
+#else
+static RawError* BootstrapFromKernel(Thread* thread,
+                                     const uint8_t* buffer,
+                                     intptr_t buffer_size) {
+  UNREACHABLE();
+  return Error::null();
+}
+#endif
+
+
+RawError* Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
+                                     intptr_t kernel_buffer_length) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   Zone* zone = thread->zone();
@@ -328,7 +397,9 @@
     }
   }
 
-  return BootstrapFromSource(thread);
+  return (kernel_buffer == NULL)
+             ? BootstrapFromSource(thread)
+             : BootstrapFromKernel(thread, kernel_buffer, kernel_buffer_length);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index 0c2d912..77fb556 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -15,7 +15,15 @@
 
 class Bootstrap : public AllStatic {
  public:
-  static RawError* DoBootstrapping();
+  // Compile the bootstrap libraries, either from sources or a Kernel binary.
+  // If kernel_buffer is NULL, compile from sources or source paths linked into
+  // the VM.  If it is non-NULL it represents a buffer holding a Kernel binary.
+  // The caller of this function is responsible for managing the kernel
+  // buffer's memory, and is welcome to deallocate it after this function
+  // returns.
+  static RawError* DoBootstrapping(const uint8_t* kernel_buffer,
+                                   intptr_t kernel_buffer_length);
+
   static void SetupNativeResolver();
   static bool IsBootstapResolver(Dart_NativeEntryResolver resolver);
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 559f44a..7ae1810 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -346,6 +346,7 @@
   V(UserTag_makeCurrent, 1)                                                    \
   V(Profiler_getCurrentTag, 0)                                                 \
   V(ClassID_getID, 1)                                                          \
+  V(ClassID_byName, 1)                                                         \
   V(VMService_SendIsolateServiceMessage, 2)                                    \
   V(VMService_SendRootServiceMessage, 1)                                       \
   V(VMService_SendObjectRootServiceMessage, 1)                                 \
diff --git a/runtime/vm/bootstrap_nocore.cc b/runtime/vm/bootstrap_nocore.cc
index 64db0eb..d804b24 100644
--- a/runtime/vm/bootstrap_nocore.cc
+++ b/runtime/vm/bootstrap_nocore.cc
@@ -6,15 +6,136 @@
 
 #include "include/dart_api.h"
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/class_finalizer.h"
+#include "vm/compiler.h"
+#include "vm/kernel_reader.h"
+#endif
 #include "vm/object.h"
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/object_store.h"
+#endif
 
 namespace dart {
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#define MAKE_PROPERTIES(CamelName, name)                                       \
+  {ObjectStore::k##CamelName, "dart:" #name},
 
-RawError* Bootstrap::DoBootstrapping() {
-  UNREACHABLE();
+
+struct BootstrapLibProps {
+  ObjectStore::BootstrapLibraryId index;
+  const char* uri;
+};
+
+
+static BootstrapLibProps bootstrap_libraries[] = {
+    FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_PROPERTIES)};
+
+
+#undef MAKE_PROPERTIES
+
+
+static const intptr_t bootstrap_library_count = ARRAY_SIZE(bootstrap_libraries);
+
+
+void Finish(Thread* thread, bool from_kernel) {
+  Bootstrap::SetupNativeResolver();
+  ClassFinalizer::ProcessPendingClasses(from_kernel);
+
+  // Eagerly compile the _Closure class as it is the class of all closure
+  // instances. This allows us to just finalize function types without going
+  // through the hoops of trying to compile their scope class.
+  ObjectStore* object_store = thread->isolate()->object_store();
+  Class& cls = Class::Handle(thread->zone(), object_store->closure_class());
+  Compiler::CompileClass(cls);
+  // Eagerly compile Bool class, bool constants are used from within compiler.
+  cls = object_store->bool_class();
+  Compiler::CompileClass(cls);
+}
+
+
+RawError* BootstrapFromKernel(Thread* thread,
+                              const uint8_t* buffer,
+                              intptr_t buffer_length) {
+  Zone* zone = thread->zone();
+  kernel::Program* program =
+      ReadPrecompiledKernelFromBuffer(buffer, buffer_length);
+  if (program == NULL) {
+    const String& message =
+        String::Handle(zone, String::New("Failed to read Kernel file"));
+    return ApiError::New(message);
+  }
+
+  Isolate* isolate = thread->isolate();
+  // Mark the already-pending classes.  This mark bit will be used to avoid
+  // adding classes to the list more than once.
+  GrowableObjectArray& pending_classes = GrowableObjectArray::Handle(
+      zone, isolate->object_store()->pending_classes());
+  dart::Class& pending = dart::Class::Handle(zone);
+  for (intptr_t i = 0; i < pending_classes.Length(); ++i) {
+    pending ^= pending_classes.At(i);
+    pending.set_is_marked_for_parsing();
+  }
+
+  Library& library = Library::Handle(zone);
+  String& dart_name = String::Handle(zone);
+  String& kernel_name = String::Handle(zone);
+  kernel::KernelReader reader(NULL, -1, true);
+  for (intptr_t i = 0; i < bootstrap_library_count; ++i) {
+    ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
+    library = isolate->object_store()->bootstrap_library(id);
+    dart_name = library.url();
+    for (intptr_t j = 0; j < program->libraries().length(); ++j) {
+      kernel::Library* kernel_library = program->libraries()[j];
+      kernel::String* uri = kernel_library->import_uri();
+      kernel_name = Symbols::FromUTF8(thread, uri->buffer(), uri->size());
+      if (kernel_name.Equals(dart_name)) {
+        reader.ReadLibrary(kernel_library);
+        library.SetLoaded();
+        break;
+      }
+    }
+  }
+
+  Finish(thread, /*from_kernel=*/true);
   return Error::null();
 }
 
 
+RawError* Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
+                                     intptr_t kernel_buffer_length) {
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
+  Zone* zone = thread->zone();
+  String& uri = String::Handle(zone);
+  Library& lib = Library::Handle(zone);
+
+  HANDLESCOPE(thread);
+
+  // Ensure there are library objects for all the bootstrap libraries.
+  for (intptr_t i = 0; i < bootstrap_library_count; ++i) {
+    ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
+    uri = Symbols::New(thread, bootstrap_libraries[i].uri);
+    lib = isolate->object_store()->bootstrap_library(id);
+    ASSERT(lib.raw() == Library::LookupLibrary(thread, uri));
+    if (lib.IsNull()) {
+      lib = Library::NewLibraryHelper(uri, false);
+      lib.SetLoadRequested();
+      lib.Register(thread);
+      isolate->object_store()->set_bootstrap_library(id, lib);
+    }
+  }
+
+  ASSERT(kernel_buffer != NULL);
+  return BootstrapFromKernel(thread, kernel_buffer, kernel_buffer_length);
+}
+#else
+RawError* Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
+                                     intptr_t kernel_buffer_length) {
+  UNREACHABLE();
+  return Error::null();
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 }  // namespace dart
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 98d74ff..c8683ee 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -118,7 +118,7 @@
 // Processing ObjectStore::pending_classes_ occurs:
 // a) when bootstrap process completes (VerifyBootstrapClasses).
 // b) after the user classes are loaded (dart_api).
-bool ClassFinalizer::ProcessPendingClasses() {
+bool ClassFinalizer::ProcessPendingClasses(bool from_kernel) {
   Thread* thread = Thread::Current();
   NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(),
                                            "ProcessPendingClasses"));
@@ -150,6 +150,12 @@
     for (intptr_t i = 0; i < class_array.Length(); i++) {
       cls ^= class_array.At(i);
       FinalizeTypesInClass(cls);
+      // Classes compiled from Dart sources are finalized more lazily, classes
+      // compiled from Kernel binaries can be finalized now (and should be,
+      // since we will not revisit them).
+      if (from_kernel) {
+        FinalizeClass(cls);
+      }
     }
     if (FLAG_print_classes) {
       for (intptr_t i = 0; i < class_array.Length(); i++) {
@@ -188,7 +194,7 @@
 }
 
 
-#if defined(DART_NO_SNAPSHOT)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void ClassFinalizer::VerifyBootstrapClasses() {
   if (FLAG_trace_class_finalization) {
     OS::Print("VerifyBootstrapClasses START.\n");
@@ -254,7 +260,7 @@
   }
   Isolate::Current()->heap()->Verify();
 }
-#endif  // defined(DART_NO_SNAPSHOT).
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 
 static bool IsLoaded(const Type& type) {
@@ -263,9 +269,15 @@
   }
   const UnresolvedClass& unresolved_class =
       UnresolvedClass::Handle(type.unresolved_class());
-  const LibraryPrefix& prefix =
-      LibraryPrefix::Handle(unresolved_class.library_prefix());
-  return prefix.IsNull() || prefix.is_loaded();
+  const Object& prefix =
+      Object::Handle(unresolved_class.library_or_library_prefix());
+  if (prefix.IsNull()) {
+    return true;
+  } else if (prefix.IsLibraryPrefix()) {
+    return LibraryPrefix::Cast(prefix).is_loaded();
+  } else {
+    return true;
+  }
 }
 
 
@@ -276,15 +288,19 @@
   const String& class_name = String::Handle(unresolved_class.ident());
   Library& lib = Library::Handle();
   Class& resolved_class = Class::Handle();
-  if (unresolved_class.library_prefix() == LibraryPrefix::null()) {
+  if (unresolved_class.library_or_library_prefix() == Object::null()) {
     lib = cls.library();
     ASSERT(!lib.IsNull());
     resolved_class = lib.LookupClass(class_name);
   } else {
-    LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
-    lib_prefix = unresolved_class.library_prefix();
-    ASSERT(!lib_prefix.IsNull());
-    resolved_class = lib_prefix.LookupClass(class_name);
+    const Object& prefix =
+        Object::Handle(unresolved_class.library_or_library_prefix());
+
+    if (prefix.IsLibraryPrefix()) {
+      resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name);
+    } else {
+      resolved_class = Library::Cast(prefix).LookupClass(class_name);
+    }
   }
   return resolved_class.raw();
 }
@@ -1422,7 +1438,7 @@
                                      &error))) {
         if (Isolate::Current()->error_on_bad_type()) {
           const AbstractType& const_value_type =
-              AbstractType::Handle(zone, const_value.GetType());
+              AbstractType::Handle(zone, const_value.GetType(Heap::kNew));
           const String& const_value_type_name =
               String::Handle(zone, const_value_type.UserVisibleName());
           const String& type_name =
@@ -2189,12 +2205,25 @@
   const GrowableObjectArray& cloned_funcs =
       GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
 
-  CreateForwardingConstructors(cls, mixin_cls, cloned_funcs);
-
   Array& functions = Array::Handle(zone);
   Function& func = Function::Handle(zone);
+
   // The parser creates the mixin application class with no functions.
-  ASSERT((functions = cls.functions(), functions.Length() == 0));
+  // But the Kernel frontend will generate mixin classes with only
+  // constructors inside them, which forward to the base class constructors.
+  //
+  // => We generate the constructors if they are not already there.
+  functions = cls.functions();
+  if (functions.Length() == 0) {
+    CreateForwardingConstructors(cls, mixin_cls, cloned_funcs);
+  } else {
+    for (intptr_t i = 0; i < functions.Length(); i++) {
+      func ^= functions.At(i);
+      ASSERT(func.kernel_function() != 0);
+      cloned_funcs.Add(func);
+    }
+  }
+
   // Now clone the functions from the mixin class.
   functions = mixin_cls.functions();
   const intptr_t num_functions = functions.Length();
@@ -2384,8 +2413,20 @@
     // if the class is being refinalized because a patch is being applied
     // after the class has been finalized then it is ok for the class to have
     // functions.
-    ASSERT((Array::Handle(cls.functions()).Length() == 0) ||
-           cls.is_refinalize_after_patch());
+    //
+    // TODO(kmillikin): This ASSERT will fail when bootstrapping from Kernel
+    // because classes are first created, methods are added, and then classes
+    // are finalized.  It is not easy to finalize classes earlier because not
+    // all bootstrap classes have been created yet.  It would be possible to
+    // create all classes, delay adding methods, finalize the classes, and then
+    // reprocess all classes to add methods, but that seems unnecessary.
+    // Marking the bootstrap classes as is_refinalize_after_patch seems cute but
+    // it causes other things to fail by violating their assumptions.  Reenable
+    // this ASSERT if it's important, remove it if it's just a sanity check and
+    // not required for correctness.
+    //
+    // ASSERT((Array::Handle(cls.functions()).Length() == 0) ||
+    //        cls.is_refinalize_after_patch());
   }
 }
 
@@ -2478,17 +2519,31 @@
   ASSERT(Instance::Handle(zone, values_field.StaticValue()).IsArray());
   Array& values_list =
       Array::Handle(zone, Array::RawCast(values_field.StaticValue()));
-
-  const Array& fields = Array::Handle(zone, enum_cls.fields());
-  Field& field = Field::Handle(zone);
-  Instance& ordinal_value = Instance::Handle(zone);
-  Instance& enum_value = Instance::Handle(zone);
-
   const String& enum_name = String::Handle(enum_cls.ScrubbedName());
   const String& name_prefix =
       String::Handle(String::Concat(enum_name, Symbols::Dot()));
 
+  Field& field = Field::Handle(zone);
+  Instance& ordinal_value = Instance::Handle(zone);
+  Instance& enum_value = Instance::Handle(zone);
+
   String& enum_ident = String::Handle();
+
+  enum_ident =
+      Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), enum_name);
+  enum_value = Instance::New(enum_cls, Heap::kOld);
+  enum_value.SetField(index_field, Smi::Handle(zone, Smi::New(-1)));
+  enum_value.SetField(name_field, enum_ident);
+  const char* error_msg = NULL;
+  enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
+  ASSERT(!enum_value.IsNull());
+  ASSERT(enum_value.IsCanonical());
+  field = enum_cls.LookupStaticField(Symbols::_DeletedEnumSentinel());
+  ASSERT(!field.IsNull());
+  field.SetStaticValue(enum_value, true);
+  field.RecordStore(enum_value);
+
+  const Array& fields = Array::Handle(zone, enum_cls.fields());
   for (intptr_t i = 0; i < fields.Length(); i++) {
     field = Field::RawCast(fields.At(i));
     if (!field.is_static()) continue;
@@ -2509,7 +2564,6 @@
     enum_value = Instance::New(enum_cls, Heap::kOld);
     enum_value.SetField(index_field, ordinal_value);
     enum_value.SetField(name_field, enum_ident);
-    const char* error_msg = "";
     enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
     ASSERT(!enum_value.IsNull());
     ASSERT(enum_value.IsCanonical());
@@ -2520,7 +2574,6 @@
     values_list.SetAt(ord, enum_value);
   }
   values_list.MakeImmutable();
-  const char* error_msg = NULL;
   values_list ^= values_list.CheckAndCanonicalize(thread, &error_msg);
   ASSERT(!values_list.IsNull());
 }
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index 5bcfc6b..f30f7a5 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -70,7 +70,7 @@
   // failed. The function returns true if the processing was successful.
   // If processing fails, an error message is set in the sticky error field
   // in the object store.
-  static bool ProcessPendingClasses();
+  static bool ProcessPendingClasses(bool from_kernel = false);
 
   // Finalize the types appearing in the declaration of class 'cls', i.e. its
   // type parameters and their upper bounds, its super type and interfaces.
@@ -81,11 +81,11 @@
   // Finalize the class including its fields and functions.
   static void FinalizeClass(const Class& cls);
 
-#if defined(DART_NO_SNAPSHOT)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   // Verify that the classes have been properly prefinalized. This is
   // needed during bootstrapping where the classes have been preloaded.
   static void VerifyBootstrapClasses();
-#endif  // defined(DART_NO_SNAPSHOT).
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   // Resolve the class of the type, but not the type's type arguments.
   // May promote the type to function type by setting its signature field.
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 396e6ad..d8ae134 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5307,21 +5307,29 @@
 
   WriteIsolateFullSnapshot(num_base_objects);
 
+  if (FLAG_print_snapshot_sizes) {
+    OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
+    OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
+  }
+  intptr_t total_size = VmIsolateSnapshotSize() + IsolateSnapshotSize();
+
   if (Snapshot::IncludesCode(kind_)) {
     instructions_writer_->Write(
         *vm_isolate_snapshot_buffer_, vm_isolate_snapshot_size_,
         *isolate_snapshot_buffer_, isolate_snapshot_size_);
 
-    OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
-    OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
-    OS::Print("ReadOnlyData(CodeSize): %" Pd "\n",
-              instructions_writer_->data_size());
-    OS::Print("Instructions(CodeSize): %" Pd "\n",
-              instructions_writer_->text_size());
-    intptr_t total = VmIsolateSnapshotSize() + IsolateSnapshotSize() +
-                     instructions_writer_->data_size() +
-                     instructions_writer_->text_size();
-    OS::Print("Total(CodeSize): %" Pd "\n", total);
+    if (FLAG_print_snapshot_sizes) {
+      OS::Print("ReadOnlyData(CodeSize): %" Pd "\n",
+                instructions_writer_->data_size());
+      OS::Print("Instructions(CodeSize): %" Pd "\n",
+                instructions_writer_->text_size());
+    }
+    total_size +=
+        instructions_writer_->data_size() + instructions_writer_->text_size();
+  }
+
+  if (FLAG_print_snapshot_sizes) {
+    OS::Print("Total(CodeSize): %" Pd "\n", total_size);
   }
 }
 
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index ef90b54..4a35895 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -338,7 +338,8 @@
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
 
-  const AbstractType& instance_type = AbstractType::Handle(instance.GetType());
+  const AbstractType& instance_type =
+      AbstractType::Handle(instance.GetType(Heap::kNew));
   ASSERT(instance_type.IsInstantiated());
   if (type.IsInstantiated()) {
     OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", message,
@@ -551,7 +552,7 @@
     // Throw a dynamic type error.
     const TokenPosition location = GetCallerLocation();
     const AbstractType& src_type =
-        AbstractType::Handle(zone, src_instance.GetType());
+        AbstractType::Handle(zone, src_instance.GetType(Heap::kNew));
     if (!dst_type.IsInstantiated()) {
       // Instantiate dst_type before reporting the error.
       dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL,
@@ -603,7 +604,7 @@
   ASSERT(!src_instance.IsBool());
   const Type& bool_interface = Type::Handle(Type::BoolType());
   const AbstractType& src_type =
-      AbstractType::Handle(zone, src_instance.GetType());
+      AbstractType::Handle(zone, src_instance.GetType(Heap::kNew));
   const String& no_bound_error = String::Handle(zone);
   Exceptions::CreateAndThrowTypeError(location, src_type, bool_interface,
                                       Symbols::BooleanExpression(),
@@ -624,7 +625,7 @@
   const AbstractType& dst_type =
       AbstractType::CheckedHandle(zone, arguments.ArgAt(2));
   const AbstractType& src_type =
-      AbstractType::Handle(zone, src_value.GetType());
+      AbstractType::Handle(zone, src_value.GetType(Heap::kNew));
   Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
                                       String::Handle(zone));
   UNREACHABLE();
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index c2b7e76..16f2e18 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -167,7 +167,9 @@
   // Check for ARMv5TE, ARMv6, ARMv7, or aarch64.
   // It can be in either the Processor or Model information fields.
   if (CpuInfo::FieldContains(kCpuInfoProcessor, "aarch64") ||
-      CpuInfo::FieldContains(kCpuInfoModel, "aarch64")) {
+      CpuInfo::FieldContains(kCpuInfoModel, "aarch64") ||
+      CpuInfo::FieldContains(kCpuInfoArchitecture, "8") ||
+      CpuInfo::FieldContains(kCpuInfoArchitecture, "AArch64")) {
     // pretend that this arm64 cpu is really an ARMv7
     arm_version_ = ARMv7;
     is_arm64 = true;
diff --git a/runtime/vm/cpuinfo.h b/runtime/vm/cpuinfo.h
index 6e8da6d..89e2432 100644
--- a/runtime/vm/cpuinfo.h
+++ b/runtime/vm/cpuinfo.h
@@ -16,7 +16,8 @@
   kCpuInfoModel = 1,
   kCpuInfoHardware = 2,
   kCpuInfoFeatures = 3,
-  kCpuInfoMax = 4,
+  kCpuInfoArchitecture = 4,
+  kCpuInfoMax = 5,
 };
 
 // For Intel architectures, the method to use to get CPU information.
diff --git a/runtime/vm/cpuinfo_android.cc b/runtime/vm/cpuinfo_android.cc
index 1e4229c..077de16 100644
--- a/runtime/vm/cpuinfo_android.cc
+++ b/runtime/vm/cpuinfo_android.cc
@@ -25,16 +25,19 @@
   fields_[kCpuInfoModel] = "model name";
   fields_[kCpuInfoHardware] = "model name";
   fields_[kCpuInfoFeatures] = "flags";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
 #elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
   fields_[kCpuInfoProcessor] = "Processor";
   fields_[kCpuInfoModel] = "model name";
   fields_[kCpuInfoHardware] = "Hardware";
   fields_[kCpuInfoFeatures] = "Features";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
 #elif defined(HOST_ARCH_MIPS)
   fields_[kCpuInfoProcessor] = "system type";
   fields_[kCpuInfoModel] = "cpu model";
   fields_[kCpuInfoHardware] = "cpu model";
   fields_[kCpuInfoFeatures] = "ASEs implemented";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
 #else
 #error Unrecognized target architecture
 #endif
diff --git a/runtime/vm/cpuinfo_fuchsia.cc b/runtime/vm/cpuinfo_fuchsia.cc
index 899223e..a46f842 100644
--- a/runtime/vm/cpuinfo_fuchsia.cc
+++ b/runtime/vm/cpuinfo_fuchsia.cc
@@ -27,6 +27,7 @@
   fields_[kCpuInfoModel] = "Hardware";
   fields_[kCpuInfoHardware] = "Hardware";
   fields_[kCpuInfoFeatures] = "Features";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
 #endif
 }
 
diff --git a/runtime/vm/cpuinfo_linux.cc b/runtime/vm/cpuinfo_linux.cc
index 8d76233..6f47be0 100644
--- a/runtime/vm/cpuinfo_linux.cc
+++ b/runtime/vm/cpuinfo_linux.cc
@@ -26,6 +26,7 @@
   fields_[kCpuInfoModel] = "model name";
   fields_[kCpuInfoHardware] = "model name";
   fields_[kCpuInfoFeatures] = "flags";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
   method_ = kCpuInfoCpuId;
   CpuId::InitOnce();
 #elif defined(HOST_ARCH_ARM)
@@ -33,6 +34,7 @@
   fields_[kCpuInfoModel] = "model name";
   fields_[kCpuInfoHardware] = "Hardware";
   fields_[kCpuInfoFeatures] = "Features";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
   method_ = kCpuInfoSystem;
   ProcCpuInfo::InitOnce();
 #elif defined(HOST_ARCH_ARM64)
@@ -40,6 +42,7 @@
   fields_[kCpuInfoModel] = "CPU implementer";
   fields_[kCpuInfoHardware] = "CPU implementer";
   fields_[kCpuInfoFeatures] = "Features";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
   method_ = kCpuInfoSystem;
   ProcCpuInfo::InitOnce();
 #elif defined(HOST_ARCH_MIPS)
@@ -47,6 +50,7 @@
   fields_[kCpuInfoModel] = "cpu model";
   fields_[kCpuInfoHardware] = "cpu model";
   fields_[kCpuInfoFeatures] = "ASEs implemented";
+  fields_[kCpuInfoArchitecture] = "CPU architecture";
   method_ = kCpuInfoSystem;
   ProcCpuInfo::InitOnce();
 #else
diff --git a/runtime/vm/cpuinfo_macos.cc b/runtime/vm/cpuinfo_macos.cc
index 64e46f3..f878a5b 100644
--- a/runtime/vm/cpuinfo_macos.cc
+++ b/runtime/vm/cpuinfo_macos.cc
@@ -25,6 +25,7 @@
   fields_[kCpuInfoModel] = "machdep.cpu.brand_string";
   fields_[kCpuInfoHardware] = "machdep.cpu.brand_string";
   fields_[kCpuInfoFeatures] = "machdep.cpu.features";
+  fields_[kCpuInfoArchitecture] = NULL;
 }
 
 
diff --git a/runtime/vm/cpuinfo_win.cc b/runtime/vm/cpuinfo_win.cc
index 1570af7..6f18a35 100644
--- a/runtime/vm/cpuinfo_win.cc
+++ b/runtime/vm/cpuinfo_win.cc
@@ -29,6 +29,7 @@
   fields_[kCpuInfoModel] = "Hardware";
   fields_[kCpuInfoHardware] = "Hardware";
   fields_[kCpuInfoFeatures] = "Features";
+  fields_[kCpuInfoArchitecture] = NULL;
 }
 
 
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index bf490bf..a3d3da6 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -491,7 +491,10 @@
 }
 
 
-RawError* Dart::InitializeIsolate(const uint8_t* snapshot_buffer, void* data) {
+RawError* Dart::InitializeIsolate(const uint8_t* snapshot_buffer,
+                                  intptr_t snapshot_length,
+                                  bool from_kernel,
+                                  void* data) {
   // Initialize the new isolate.
   Thread* T = Thread::Current();
   Isolate* I = T->isolate();
@@ -508,11 +511,18 @@
     ObjectStore::Init(I);
   }
 
-  const Error& error = Error::Handle(Object::Init(I));
+  Error& error = Error::Handle(T->zone());
+  if (from_kernel) {
+    ASSERT(snapshot_buffer != NULL);
+    ASSERT(snapshot_length > 0);
+    error = Object::Init(I, snapshot_buffer, snapshot_length);
+  } else {
+    error = Object::Init(I, NULL, -1);
+  }
   if (!error.IsNull()) {
     return error.raw();
   }
-  if (snapshot_buffer != NULL) {
+  if ((snapshot_buffer != NULL) && !from_kernel) {
     // Read the snapshot and setup the initial state.
     NOT_IN_PRODUCT(TimelineDurationScope tds(T, Timeline::GetIsolateStream(),
                                              "IsolateSnapshotReader"));
@@ -553,7 +563,7 @@
       MegamorphicCacheTable::PrintSizes(I);
     }
   } else {
-    if (snapshot_kind_ != Snapshot::kNone) {
+    if ((snapshot_kind_ != Snapshot::kNone) && !from_kernel) {
       const String& message =
           String::Handle(String::New("Missing isolate snapshot"));
       return ApiError::New(message);
@@ -581,7 +591,7 @@
       Code::Handle(I->object_store()->megamorphic_miss_code());
   I->set_ic_miss_code(miss_code);
 
-  if (snapshot_buffer == NULL) {
+  if ((snapshot_buffer == NULL) || from_kernel) {
     const Error& error = Error::Handle(I->object_store()->PreallocateObjects());
     if (!error.IsNull()) {
       return error.raw();
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index df31995..3480fad 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -37,7 +37,15 @@
 
   static Isolate* CreateIsolate(const char* name_prefix,
                                 const Dart_IsolateFlags& api_flags);
-  static RawError* InitializeIsolate(const uint8_t* snapshot, void* data);
+
+  // Initialize an isolate, either from a snapshot, from a Kernel binary, or
+  // from SDK library sources.  If the snapshot_buffer is non-NULL,
+  // initialize from a snapshot or a Kernel binary depending on the value of
+  // from_kernel.  Otherwise, initialize from sources.
+  static RawError* InitializeIsolate(const uint8_t* snapshot_buffer,
+                                     intptr_t snapshot_length,
+                                     bool from_kernel,
+                                     void* data);
   static void RunShutdownCallback();
   static void ShutdownIsolate(Isolate* isolate);
   static void ShutdownIsolate();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 0992611..e5cf6ae 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1236,12 +1236,15 @@
 }
 
 
-DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri,
-                                            const char* main,
-                                            const uint8_t* snapshot,
-                                            Dart_IsolateFlags* flags,
-                                            void* callback_data,
-                                            char** error) {
+static Dart_Isolate CreateIsolate(const char* script_uri,
+                                  const char* main,
+                                  const uint8_t* snapshot_buffer,
+                                  intptr_t snapshot_length,
+                                  bool from_kernel,
+                                  Dart_IsolateFlags* flags,
+                                  void* callback_data,
+                                  char** error) {
+  ASSERT(!from_kernel || (snapshot_buffer != NULL));
   CHECK_NO_ISOLATE(Isolate::Current());
   char* isolate_name = BuildIsolateName(script_uri, main);
 
@@ -1265,11 +1268,12 @@
     // 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(Z, Dart::InitializeIsolate(snapshot, callback_data));
+    const Error& error_obj = Error::Handle(
+        Z, Dart::InitializeIsolate(snapshot_buffer, snapshot_length,
+                                   from_kernel, callback_data));
     if (error_obj.IsNull()) {
 #if defined(DART_NO_SNAPSHOT) && !defined(PRODUCT)
-      if (FLAG_check_function_fingerprints) {
+      if (FLAG_check_function_fingerprints && !from_kernel) {
         Library::CheckFunctionFingerprints();
       }
 #endif  // defined(DART_NO_SNAPSHOT) && !defined(PRODUCT).
@@ -1292,6 +1296,30 @@
 }
 
 
+DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri,
+                                            const char* main,
+                                            const uint8_t* snapshot_buffer,
+                                            Dart_IsolateFlags* flags,
+                                            void* callback_data,
+                                            char** error) {
+  return CreateIsolate(script_uri, main, snapshot_buffer, -1, false, flags,
+                       callback_data, error);
+}
+
+
+DART_EXPORT Dart_Isolate
+Dart_CreateIsolateFromKernel(const char* script_uri,
+                             const char* main,
+                             const uint8_t* kernel_file,
+                             intptr_t kernel_length,
+                             Dart_IsolateFlags* flags,
+                             void* callback_data,
+                             char** error) {
+  return CreateIsolate(script_uri, main, kernel_file, kernel_length, true,
+                       flags, callback_data, error);
+}
+
+
 DART_EXPORT void Dart_ShutdownIsolate() {
   Thread* T = Thread::Current();
   Isolate* I = T->isolate();
@@ -2108,7 +2136,7 @@
     RETURN_TYPE_ERROR(Z, instance, Instance);
   }
   const AbstractType& type =
-      AbstractType::Handle(Instance::Cast(obj).GetType());
+      AbstractType::Handle(Instance::Cast(obj).GetType(Heap::kNew));
   return Api::NewHandle(T, type.Canonicalize());
 }
 
@@ -4046,7 +4074,8 @@
 
   // Construct name of the constructor to invoke.
   const String& constructor_name = Api::UnwrapStringHandle(Z, name);
-  const AbstractType& type_obj = AbstractType::Handle(Z, instance.GetType());
+  const AbstractType& type_obj =
+      AbstractType::Handle(Z, instance.GetType(Heap::kNew));
   const Class& cls = Class::Handle(Z, type_obj.type_class());
   const String& class_name = String::Handle(Z, cls.Name());
   const Array& strings = Array::Handle(Z, Array::New(3));
@@ -5327,7 +5356,7 @@
   DARTSCOPE(Thread::Current());
   StackZone zone(T);
 
-#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
+#if defined(DART_PRECOMPILED_RUNTIME)
   return Api::NewError("%s: Can't load Kernel files from precompiled runtime.",
                        CURRENT_FUNC);
 #else
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index f0c5532..beb0155 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -606,7 +606,7 @@
 DART_EXPORT Dart_Handle Dart_GetObjClass(Dart_Handle object_in) {
   DARTSCOPE(Thread::Current());
   UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
-  return Api::NewHandle(T, obj.GetType());
+  return Api::NewHandle(T, obj.GetType(Heap::kNew));
 }
 
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 94c0425..7c1a288 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -122,6 +122,8 @@
     "Polymorphic calls with deoptimization / megamorphic call")                \
   P(precompiled_mode, bool, false, "Precompilation compiler mode")             \
   C(precompiled_runtime, true, false, bool, false, "Precompiled runtime mode") \
+  R(print_snapshot_sizes, false, bool, false,                                  \
+    "Print sizes of generated snapshots.")                                     \
   R(print_ssa_liveranges, false, bool, false,                                  \
     "Print live ranges after allocation.")                                     \
   C(print_stop_message, false, false, bool, false, "Print stop message.")      \
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index bcc18fb..b8e84b5 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -2056,6 +2056,46 @@
 }
 
 
+// Returns true if use is dominated by the given instruction.
+// Note: uses that occur at instruction itself are not dominated by it.
+static bool IsDominatedUse(Instruction* dom, Value* use) {
+  BlockEntryInstr* dom_block = dom->GetBlock();
+
+  Instruction* instr = use->instruction();
+
+  PhiInstr* phi = instr->AsPhi();
+  if (phi != NULL) {
+    return dom_block->Dominates(phi->block()->PredecessorAt(use->use_index()));
+  }
+
+  BlockEntryInstr* use_block = instr->GetBlock();
+  if (use_block == dom_block) {
+    // Fast path for the case of block entry.
+    if (dom_block == dom) return true;
+
+    for (Instruction* curr = dom->next(); curr != NULL; curr = curr->next()) {
+      if (curr == instr) return true;
+    }
+
+    return false;
+  }
+
+  return dom_block->Dominates(use_block);
+}
+
+
+void FlowGraph::RenameDominatedUses(Definition* def,
+                                    Instruction* dom,
+                                    Definition* other) {
+  for (Value::Iterator it(def->input_use_list()); !it.Done(); it.Advance()) {
+    Value* use = it.Current();
+    if (IsDominatedUse(dom, use)) {
+      use->BindTo(other);
+    }
+  }
+}
+
+
 static bool IsPositiveOrZeroSmiConst(Definition* d) {
   ConstantInstr* const_instr = d->AsConstant();
   if ((const_instr != NULL) && (const_instr->value().IsSmi())) {
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 8a1b5c6..544dfac 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -285,6 +285,12 @@
   // Merge instructions (only per basic-block).
   void TryOptimizePatterns();
 
+  // Replaces uses that are dominated by dom of 'def' with 'other'.
+  // Note: uses that occur at instruction dom itself are not dominated by it.
+  static void RenameDominatedUses(Definition* def,
+                                  Instruction* dom,
+                                  Definition* other);
+
  private:
   friend class IfConverter;
   friend class BranchSimplifier;
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index dba8c8e..c6b6663 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -84,6 +84,7 @@
     FATAL("Precompilation not supported on IA32");
 #endif
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
     // Flags affecting compilation only:
     // There is no counter feedback in precompilation, so ignore the counter
     // when making inlining decisions.
@@ -97,6 +98,7 @@
     FLAG_inlining_caller_size_threshold = 1000;
     FLAG_inlining_constant_arguments_max_size_threshold = 100;
     FLAG_inlining_constant_arguments_min_size_threshold = 30;
+#endif
 
     FLAG_background_compilation = false;
     FLAG_fields_may_be_reset = true;
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index fe777cf..afdb4cb 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -346,6 +346,11 @@
                     RawPcDescriptors::Kind kind,
                     LocationSummary* locs);
 
+  void GeneratePatchableCall(TokenPosition token_pos,
+                             const StubEntry& stub_entry,
+                             RawPcDescriptors::Kind kind,
+                             LocationSummary* locs);
+
   void GenerateDartCall(intptr_t deopt_id,
                         TokenPosition token_pos,
                         const StubEntry& stub_entry,
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 738a2bb..a66bc10 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1094,6 +1094,16 @@
 }
 
 
+void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+                                              const StubEntry& stub_entry,
+                                              RawPcDescriptors::Kind kind,
+                                              LocationSummary* locs) {
+  __ BranchLinkPatchable(stub_entry);
+  AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+}
+
+
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          const StubEntry& stub_entry,
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 09ff218..862221e 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1090,6 +1090,16 @@
 }
 
 
+void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+                                              const StubEntry& stub_entry,
+                                              RawPcDescriptors::Kind kind,
+                                              LocationSummary* locs) {
+  __ BranchLinkPatchable(stub_entry);
+  AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+}
+
+
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          const StubEntry& stub_entry,
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 729608f..d2ee67e 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1096,6 +1096,15 @@
 }
 
 
+void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+                                              const StubEntry& stub_entry,
+                                              RawPcDescriptors::Kind kind,
+                                              LocationSummary* locs) {
+  // No patchable calls on ia32.
+  GenerateCall(token_pos, stub_entry, kind, locs);
+}
+
+
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          const StubEntry& stub_entry,
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index fe38b17..ef95a0e 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1109,6 +1109,16 @@
 }
 
 
+void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+                                              const StubEntry& stub_entry,
+                                              RawPcDescriptors::Kind kind,
+                                              LocationSummary* locs) {
+  __ BranchLinkPatchable(stub_entry);
+  AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+}
+
+
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          const StubEntry& stub_entry,
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 8a8b24f..a4b1288 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1094,6 +1094,16 @@
 }
 
 
+void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+                                              const StubEntry& stub_entry,
+                                              RawPcDescriptors::Kind kind,
+                                              LocationSummary* locs) {
+  __ CallPatchable(stub_entry);
+  AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+}
+
+
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          const StubEntry& stub_entry,
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 6d2ea72..001535c 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -1,7 +1,7 @@
 // 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.
-
+#if !defined(DART_PRECOMPILED_RUNTIME)
 #include "vm/flow_graph_inliner.h"
 
 #include "vm/aot_optimizer.h"
@@ -3598,3 +3598,4 @@
 
 
 }  // namespace dart
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 28ec325..b19b4e6 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -271,50 +271,6 @@
 }
 
 
-// Returns true if use is dominated by the given instruction.
-// Note: uses that occur at instruction itself are not dominated by it.
-static bool IsDominatedUse(Instruction* dom, Value* use) {
-  BlockEntryInstr* dom_block = dom->GetBlock();
-
-  Instruction* instr = use->instruction();
-
-  PhiInstr* phi = instr->AsPhi();
-  if (phi != NULL) {
-    return dom_block->Dominates(phi->block()->PredecessorAt(use->use_index()));
-  }
-
-  BlockEntryInstr* use_block = instr->GetBlock();
-  if (use_block == dom_block) {
-    // Fast path for the case of block entry.
-    if (dom_block == dom) return true;
-
-    for (Instruction* curr = dom->next(); curr != NULL; curr = curr->next()) {
-      if (curr == instr) return true;
-    }
-
-    return false;
-  }
-
-  return dom_block->Dominates(use_block);
-}
-
-
-void RangeAnalysis::RenameDominatedUses(Definition* def,
-                                        Instruction* dom,
-                                        Definition* other) {
-  for (Value::Iterator it(def->input_use_list()); !it.Done(); it.Advance()) {
-    Value* use = it.Current();
-
-    // Skip dead phis.
-    PhiInstr* phi = use->instruction()->AsPhi();
-    ASSERT((phi == NULL) || phi->is_alive());
-    if (IsDominatedUse(dom, use)) {
-      use->BindTo(other);
-    }
-  }
-}
-
-
 // For a comparison operation return an operation for the equivalent flipped
 // comparison: a (op) b === b (op') a.
 static Token::Kind FlipComparison(Token::Kind op) {
@@ -390,7 +346,7 @@
   constraint = new (Z) ConstraintInstr(use->CopyWithType(), constraint_range);
 
   flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue);
-  RenameDominatedUses(defn, constraint, constraint);
+  FlowGraph::RenameDominatedUses(defn, constraint, constraint);
   constraints_.Add(constraint);
   return constraint;
 }
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index bc4a844..9f96d7d 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -804,8 +804,11 @@
   }
 
   if (value().IsInstance()) {
+    // Allocate in old-space since this may be invoked from the
+    // background compiler.
     return CompileType::Create(
-        cid, AbstractType::ZoneHandle(Instance::Cast(value()).GetType()));
+        cid,
+        AbstractType::ZoneHandle(Instance::Cast(value()).GetType(Heap::kOld)));
   } else {
     // Type info for non-instance objects.
     return CompileType::FromCid(cid);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 8d199c4..395b59a 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -992,8 +992,13 @@
   __ LoadImmediate(R1, argc_tag);
   ExternalLabel label(entry);
   __ LoadNativeEntry(R9, &label, link_lazily() ? kPatchable : kNotPatchable);
-  compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  if (link_lazily()) {
+    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+                                    RawPcDescriptors::kOther, locs());
+  } else {
+    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+                           locs());
+  }
   __ Pop(result);
 }
 
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 55ab860..25a220e 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -837,8 +837,13 @@
   __ LoadImmediate(R1, argc_tag);
   ExternalLabel label(entry);
   __ LoadNativeEntry(R5, &label);
-  compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  if (link_lazily()) {
+    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+                                    RawPcDescriptors::kOther, locs());
+  } else {
+    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+                           locs());
+  }
   __ Pop(result);
 }
 
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 2e94f65..c90b2c5 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -848,15 +848,17 @@
   if (link_lazily()) {
     stub_entry = StubCode::CallBootstrapCFunction_entry();
     __ movl(ECX, Immediate(NativeEntry::LinkNativeCallEntry()));
+    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+                                    RawPcDescriptors::kOther, locs());
   } else {
     stub_entry = (is_bootstrap_native())
                      ? StubCode::CallBootstrapCFunction_entry()
                      : StubCode::CallNativeCFunction_entry();
     const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
     __ movl(ECX, Immediate(label.address()));
+    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+                           locs());
   }
-  compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
-                         locs());
   __ popl(result);
 }
 
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 6a2c623..c5a5af5 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -1053,8 +1053,13 @@
   __ LoadImmediate(A1, argc_tag);
   ExternalLabel label(entry);
   __ LoadNativeEntry(T5, &label, kNotPatchable);
-  compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  if (link_lazily()) {
+    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+                                    RawPcDescriptors::kOther, locs());
+  } else {
+    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+                           locs());
+  }
   __ Pop(result);
 }
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 9510d28..097df6e 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -815,15 +815,17 @@
     stub_entry = StubCode::CallBootstrapCFunction_entry();
     ExternalLabel label(NativeEntry::LinkNativeCallEntry());
     __ LoadNativeEntry(RBX, &label, kPatchable);
+    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+                                    RawPcDescriptors::kOther, locs());
   } else {
     stub_entry = (is_bootstrap_native())
                      ? StubCode::CallBootstrapCFunction_entry()
                      : StubCode::CallNativeCFunction_entry();
     const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
     __ LoadNativeEntry(RBX, &label, kNotPatchable);
+    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+                           locs());
   }
-  compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
-                         locs());
   __ popq(result);
 }
 
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index c2a6ae2..1f50387 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -58,7 +58,7 @@
 }
 
 
-#if defined(DART_NO_SNAPSHOT)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void Intrinsifier::InitializeState() {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -117,7 +117,7 @@
 
 #undef SETUP_FUNCTION
 }
-#endif  // defined(DART_NO_SNAPSHOT).
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 
 // DBC does not use graph intrinsics.
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index c7ff0f8..9242937 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -23,7 +23,7 @@
  public:
   static bool Intrinsify(const ParsedFunction& parsed_function,
                          FlowGraphCompiler* compiler);
-#if defined(DART_NO_SNAPSHOT)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   static void InitializeState();
 #endif
 
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 949cc77..d79a9da 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -1551,7 +1551,12 @@
       random_class.LookupStaticFieldAllowPrivate(Symbols::_A()));
   ASSERT(!random_A_field.IsNull());
   ASSERT(random_A_field.is_const());
-  const Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  if (a_value.raw() == Object::sentinel().raw() ||
+      a_value.raw() == Object::transition_sentinel().raw()) {
+    random_A_field.EvaluateInitializer();
+    a_value = random_A_field.StaticValue();
+  }
   const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
   // 'a_int_value' is a mask.
   ASSERT(Utils::IsUint(32, a_int_value));
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index 5eba9f6..a78bae6 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -1625,7 +1625,12 @@
       random_class.LookupStaticFieldAllowPrivate(Symbols::_A()));
   ASSERT(!random_A_field.IsNull());
   ASSERT(random_A_field.is_const());
-  const Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  if (a_value.raw() == Object::sentinel().raw() ||
+      a_value.raw() == Object::transition_sentinel().raw()) {
+    random_A_field.EvaluateInitializer();
+    a_value = random_A_field.StaticValue();
+  }
   const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
 
   // Receiver.
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 2e810d9a4..9b5cf1d 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -1666,7 +1666,12 @@
       random_class.LookupStaticFieldAllowPrivate(Symbols::_A()));
   ASSERT(!random_A_field.IsNull());
   ASSERT(random_A_field.is_const());
-  const Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  if (a_value.raw() == Object::sentinel().raw() ||
+      a_value.raw() == Object::transition_sentinel().raw()) {
+    random_A_field.EvaluateInitializer();
+    a_value = random_A_field.StaticValue();
+  }
   const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
   // 'a_int_value' is a mask.
   ASSERT(Utils::IsUint(32, a_int_value));
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 0fa3e19..54753a2 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -1668,7 +1668,12 @@
       random_class.LookupStaticFieldAllowPrivate(Symbols::_A()));
   ASSERT(!random_A_field.IsNull());
   ASSERT(random_A_field.is_const());
-  const Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  if (a_value.raw() == Object::sentinel().raw() ||
+      a_value.raw() == Object::transition_sentinel().raw()) {
+    random_A_field.EvaluateInitializer();
+    a_value = random_A_field.StaticValue();
+  }
   const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
   // 'a_int_value' is a mask.
   ASSERT(Utils::IsUint(32, a_int_value));
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index f4f7313..b888804 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -1533,7 +1533,12 @@
       random_class.LookupStaticFieldAllowPrivate(Symbols::_A()));
   ASSERT(!random_A_field.IsNull());
   ASSERT(random_A_field.is_const());
-  const Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  Instance& a_value = Instance::Handle(random_A_field.StaticValue());
+  if (a_value.raw() == Object::sentinel().raw() ||
+      a_value.raw() == Object::transition_sentinel().raw()) {
+    random_A_field.EvaluateInitializer();
+    a_value = random_A_field.StaticValue();
+  }
   const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
   // Receiver.
   __ movq(RAX, Address(RSP, +1 * kWordSize));
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 4370ab1..9d6569e 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -58,11 +58,12 @@
     : from_(Class::Handle(zone, from.raw())),
       to_(Class::Handle(zone, to.raw())),
       mapping_(zone, 0) {
-  ComputeMapping();
   before_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0);
   after_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0);
+  new_fields_ = new (zone) ZoneGrowableArray<const Field*>(zone, 0);
   ASSERT(from_.id() == to_.id());
   cid_ = from_.id();
+  ComputeMapping();
 }
 
 
@@ -86,27 +87,50 @@
 
   // Add copying of the instance fields if matching by name.
   // Note: currently the type of the fields are ignored.
-  const Array& from_fields = Array::Handle(from_.OffsetToFieldMap());
+  const Array& from_fields =
+      Array::Handle(from_.OffsetToFieldMap(true /* original classes */));
   const Array& to_fields = Array::Handle(to_.OffsetToFieldMap());
   Field& from_field = Field::Handle();
   Field& to_field = Field::Handle();
   String& from_name = String::Handle();
   String& to_name = String::Handle();
-  for (intptr_t i = 0; i < from_fields.Length(); i++) {
-    if (from_fields.At(i) == Field::null()) continue;  // Ignore non-fields.
-    from_field = Field::RawCast(from_fields.At(i));
-    ASSERT(from_field.is_instance());
-    from_name = from_field.name();
-    // We now have to find where this field is in the to class.
-    for (intptr_t j = 0; j < to_fields.Length(); j++) {
-      if (to_fields.At(j) == Field::null()) continue;  // Ignore non-fields.
-      to_field = Field::RawCast(to_fields.At(j));
-      ASSERT(to_field.is_instance());
-      to_name = to_field.name();
+
+  // Scan across all the fields in the new class definition.
+  for (intptr_t i = 0; i < to_fields.Length(); i++) {
+    if (to_fields.At(i) == Field::null()) {
+      continue;  // Ignore non-fields.
+    }
+
+    // Grab the field's name.
+    to_field = Field::RawCast(to_fields.At(i));
+    ASSERT(to_field.is_instance());
+    to_name = to_field.name();
+
+    // Did this field not exist in the old class definition?
+    bool new_field = true;
+
+    // Find this field in the old class.
+    for (intptr_t j = 0; j < from_fields.Length(); j++) {
+      if (from_fields.At(j) == Field::null()) {
+        continue;  // Ignore non-fields.
+      }
+      from_field = Field::RawCast(from_fields.At(j));
+      ASSERT(from_field.is_instance());
+      from_name = from_field.name();
       if (from_name.Equals(to_name)) {
         // Success
         mapping_.Add(from_field.Offset());
         mapping_.Add(to_field.Offset());
+        // Field did exist in old class deifnition.
+        new_field = false;
+      }
+    }
+
+    if (new_field) {
+      if (to_field.has_initializer()) {
+        // This is a new field with an initializer.
+        const Field& field = Field::Handle(to_field.raw());
+        new_fields_->Add(&field);
       }
     }
   }
@@ -129,6 +153,48 @@
 }
 
 
+void InstanceMorpher::RunNewFieldInitializers() const {
+  if ((new_fields_->length() == 0) || (after_->length() == 0)) {
+    return;
+  }
+
+  TIR_Print("Running new field initializers for class: %s\n", to_.ToCString());
+  String& initializing_expression = String::Handle();
+  Function& eval_func = Function::Handle();
+  Object& result = Object::Handle();
+  Class& owning_class = Class::Handle();
+  // For each new field.
+  for (intptr_t i = 0; i < new_fields_->length(); i++) {
+    // Create a function that returns the expression.
+    const Field* field = new_fields_->At(i);
+    owning_class ^= field->Owner();
+    ASSERT(!owning_class.IsNull());
+    // Extract the initializing expression.
+    initializing_expression = field->InitializingExpression();
+    TIR_Print("New `%s` has initializing expression `%s`\n", field->ToCString(),
+              initializing_expression.ToCString());
+    eval_func ^= Function::EvaluateHelper(owning_class, initializing_expression,
+                                          Array::empty_array(), true);
+    for (intptr_t j = 0; j < after_->length(); j++) {
+      const Instance* instance = after_->At(j);
+      TIR_Print("Initializing instance %" Pd " / %" Pd "\n", j + 1,
+                after_->length());
+      // Run the function and assign the field.
+      result = DartEntry::InvokeFunction(eval_func, Array::empty_array());
+      if (result.IsError()) {
+        // TODO(johnmccutchan): Report this error in the reload response?
+        OS::PrintErr(
+            "RELOAD: Running initializer for new field `%s` resulted in "
+            "an error: %s\n",
+            field->ToCString(), Error::Cast(result).ToErrorCString());
+        continue;
+      }
+      instance->RawSetFieldAtOffset(field->Offset(), result);
+    }
+  }
+}
+
+
 void InstanceMorpher::CreateMorphedCopies() const {
   for (intptr_t i = 0; i < before()->length(); i++) {
     const Instance& copy = Instance::Handle(Morph(*before()->At(i)));
@@ -1141,6 +1207,9 @@
     Become::ElementsForwardIdentity(before, after);
   }
 
+  // Run the initializers for new instance fields.
+  RunNewFieldInitializers();
+
   if (FLAG_identity_reload) {
     if (saved_num_cids_ != I->class_table()->NumCids()) {
       TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n",
@@ -1302,6 +1371,14 @@
 }
 
 
+void IsolateReloadContext::RunNewFieldInitializers() {
+  // Run new field initializers on all instances.
+  for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+    instance_morphers_.At(i)->RunNewFieldInitializers();
+  }
+}
+
+
 bool IsolateReloadContext::ValidateReload() {
   TIMELINE_SCOPE(ValidateReload);
   if (reload_aborted()) return false;
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index f2a2df9..e5e5da1 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -58,6 +58,8 @@
   // Called on each instance that needs to be morphed.
   RawInstance* Morph(const Instance& instance) const;
 
+  void RunNewFieldInitializers() const;
+
   // Adds an object to be morphed.
   void AddObject(RawObject* object) const;
 
@@ -74,6 +76,8 @@
   ZoneGrowableArray<const Instance*>* before() const { return before_; }
   // Returns the list of morphed objects (matches order in before()).
   ZoneGrowableArray<const Instance*>* after() const { return after_; }
+  // Returns the list of new fields.
+  ZoneGrowableArray<const Field*>* new_fields() const { return new_fields_; }
 
   // Returns the cid associated with the from_ and to_ class.
   intptr_t cid() const { return cid_; }
@@ -84,6 +88,7 @@
   ZoneGrowableArray<intptr_t> mapping_;
   ZoneGrowableArray<const Instance*>* before_;
   ZoneGrowableArray<const Instance*>* after_;
+  ZoneGrowableArray<const Field*>* new_fields_;
   intptr_t cid_;
 
   void ComputeMapping();
@@ -232,6 +237,8 @@
   // Transforms the heap based on instance_morphers_.
   void MorphInstances();
 
+  void RunNewFieldInitializers();
+
   bool ValidateReload();
 
   void Rollback();
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 7c7daa6..287eb71 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -2180,7 +2180,8 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-  EXPECT_STREQ("Fruit.Cantalope true 2", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ("Deleted enum value from Fruit true -1",
+               SimpleInvokeStr(lib, "main"));
 }
 
 
@@ -3123,6 +3124,297 @@
   EXPECT_STREQ("value=0:00:02.000000", SimpleInvokeStr(lib, "main"));
 }
 
+
+TEST_CASE(IsolateReload_RunNewFieldInitializers) {
+  const char* kScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = 7;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return value.y;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  // Verify that we ran field initializers on existing instances.
+  EXPECT_EQ(7, SimpleInvoke(lib, "main"));
+}
+
+
+TEST_CASE(IsolateReload_RunNewFieldInitializersReferenceStaticField) {
+  const char* kScript =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y.
+  const char* kReloadScript =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = myInitialValue;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return value.y;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  // Verify that we ran field initializers on existing instances.
+  EXPECT_EQ(56, SimpleInvoke(lib, "main"));
+}
+
+
+TEST_CASE(IsolateReload_RunNewFieldInitializersMutateStaticField) {
+  const char* kScript =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "Foo value1;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  value1 = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y.
+  const char* kReloadScript =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = myInitialValue++;\n"
+      "}\n"
+      "Foo value;\n"
+      "Foo value1;\n"
+      "main() {\n"
+      "  return myInitialValue;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  // Verify that we ran field initializers on existing instances and that
+  // they affected the value of the field myInitialValue.
+  EXPECT_EQ(58, SimpleInvoke(lib, "main"));
+}
+
+
+// When an initializer expression throws, we leave the field as null.
+TEST_CASE(IsolateReload_RunNewFieldInitializersThrows) {
+  const char* kScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = throw 'a';\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return '${value.y == null}';"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  // Verify that we ran field initializers on existing instances.
+  EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
+}
+
+
+// When an initializer expression has a syntax error, we detect it at reload
+// time.
+TEST_CASE(IsolateReload_RunNewFieldInitializersSyntaxError) {
+  const char* kScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y with a syntax error in the initializing expression.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = ......;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return '${value.y == null}';"
+      "}\n";
+
+  // The reload fails because the initializing expression is parsed at
+  // class finalization time.
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_ERROR(lib, "......");
+}
+
+
+// When an initializer expression has a syntax error, we detect it at reload
+// time.
+TEST_CASE(IsolateReload_RunNewFieldInitializersSyntaxError2) {
+  const char* kScript =
+      "class Foo {\n"
+      "  Foo() { /* default constructor */ }\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y with a syntax error in the initializing expression.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  Foo() { /* default constructor */ }\n"
+      "  int x = 4;\n"
+      "  int y = ......;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return '${value.y == null}';"
+      "}\n";
+
+  // The reload fails because the initializing expression is parsed at
+  // class finalization time.
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_ERROR(lib, "......");
+}
+
+
+// When an initializer expression has a syntax error, we detect it at reload
+// time.
+TEST_CASE(IsolateReload_RunNewFieldInitializersSyntaxError3) {
+  const char* kScript =
+      "class Foo {\n"
+      "  Foo() { /* default constructor */ }\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y with a syntax error in the initializing expression.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  Foo() { /* default constructor */ }\n"
+      "  int x = 4;\n"
+      "  int y = ......\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return '${value.y == null}';"
+      "}\n";
+
+  // The reload fails because the initializing expression is parsed at
+  // class finalization time.
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_ERROR(lib, "......");
+}
+
+
+TEST_CASE(IsolateREload_RunNewFieldInitialiazersSuperClass) {
+  const char* kScript =
+      "class Super {\n"
+      "  static var foo = 'right';\n"
+      "}\n"
+      "class Foo extends Super {\n"
+      "  static var foo = 'wrong';\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  Super.foo;\n"
+      "  Foo.foo;\n"
+      "  value = new Foo();\n"
+      "  return 0;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(0, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Super {\n"
+      "  static var foo = 'right';\n"
+      "  var newField = foo;\n"
+      "}\n"
+      "class Foo extends Super {\n"
+      "  static var foo = 'wrong';\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return value.newField;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  // Verify that we ran field initializers on existing instances in the
+  // correct scope.
+  EXPECT_STREQ("right", SimpleInvokeStr(lib, "main"));
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index d632349..f30e100 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -4,6 +4,7 @@
 
 #include "vm/kernel.h"
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 namespace dart {
 
 namespace kernel {
@@ -1207,3 +1208,4 @@
 }  // namespace kernel
 
 }  // namespace dart
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 09e9f70..93b828b 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -5,10 +5,12 @@
 #ifndef RUNTIME_VM_KERNEL_H_
 #define RUNTIME_VM_KERNEL_H_
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 #include "platform/assert.h"
 #include "vm/allocation.h"
 #include "vm/globals.h"
 
+
 #define KERNEL_NODES_DO(M)                                                     \
   M(Name)                                                                      \
   M(InferredValue)                                                             \
@@ -3243,4 +3245,5 @@
 
 }  // namespace dart
 
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 #endif  // RUNTIME_VM_KERNEL_H_
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index aaf3333..350690d 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+#if !defined(DART_PRECOMPILED_RUNTIME)
 
 #include <map>
 #include <vector>
@@ -2901,3 +2902,4 @@
 
 
 }  // namespace dart
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/kernel_reader.cc b/runtime/vm/kernel_reader.cc
index f9f2277..6c669e4 100644
--- a/runtime/vm/kernel_reader.cc
+++ b/runtime/vm/kernel_reader.cc
@@ -12,6 +12,7 @@
 #include "vm/parser.h"
 #include "vm/symbols.h"
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 namespace dart {
 namespace kernel {
 
@@ -81,19 +82,18 @@
   dart::Instance* simple_value_;
 };
 
-void BuildingTranslationHelper::SetFinalize(bool finalize) {
-  reader_->finalize_ = finalize;
-}
 
 RawLibrary* BuildingTranslationHelper::LookupLibraryByKernelLibrary(
     Library* library) {
   return reader_->LookupLibrary(library).raw();
 }
 
+
 RawClass* BuildingTranslationHelper::LookupClassByKernelClass(Class* klass) {
   return reader_->LookupClass(klass).raw();
 }
 
+
 Object& KernelReader::ReadProgram() {
   ASSERT(!bootstrapping_);
   Program* program = ReadPrecompiledKernelFromBuffer(buffer_, buffer_length_);
@@ -113,29 +113,13 @@
       ReadLibrary(kernel_library);
     }
 
-    // We finalize classes after we've constructed all classes since we
-    // currently don't construct them in pre-order of the class hierarchy (and
-    // finalization of a class needs all of its superclasses to be finalized).
-    dart::String& name = dart::String::Handle(Z);
     for (intptr_t i = 0; i < length; i++) {
-      Library* kernel_library = program->libraries()[i];
-      dart::Library& library = LookupLibrary(kernel_library);
-      name = library.url();
+      dart::Library& library = LookupLibrary(program->libraries()[i]);
+      if (!library.Loaded()) library.SetLoaded();
+    }
 
-      // TODO(27590) unskip this library when we fix underlying issue.
-      if (name.Equals("dart:vmservice_io")) {
-        continue;
-      }
-
-      if (!library.Loaded()) {
-        dart::Class& klass = dart::Class::Handle(Z);
-        for (intptr_t i = 0; i < kernel_library->classes().length(); i++) {
-          klass = LookupClass(kernel_library->classes()[i]).raw();
-          ClassFinalizer::FinalizeTypesInClass(klass);
-          ClassFinalizer::FinalizeClass(klass);
-        }
-        library.SetLoaded();
-      }
+    if (!ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) {
+      FATAL("Error in class finalization during bootstrapping.");
     }
 
     dart::Library& library = LookupLibrary(kernel_main_library);
@@ -161,6 +145,7 @@
   }
 }
 
+
 void KernelReader::ReadLibrary(Library* kernel_library) {
   dart::Library& library = LookupLibrary(kernel_library);
   if (library.Loaded()) return;
@@ -217,13 +202,17 @@
     ReadProcedure(library, toplevel_class, kernel_procedure);
   }
 
+  const GrowableObjectArray& classes =
+      GrowableObjectArray::Handle(I->object_store()->pending_classes());
+
   // Load all classes.
   for (intptr_t i = 0; i < kernel_library->classes().length(); i++) {
     Class* kernel_klass = kernel_library->classes()[i];
-    ReadClass(library, kernel_klass);
+    classes.Add(ReadClass(library, kernel_klass), Heap::kOld);
   }
 }
 
+
 void KernelReader::ReadPreliminaryClass(dart::Class* klass,
                                         Class* kernel_klass) {
   ASSERT(kernel_klass->IsNormalClass());
@@ -284,7 +273,6 @@
   intptr_t interface_count = kernel_klass->implemented_classes().length();
   const dart::Array& interfaces =
       dart::Array::Handle(Z, dart::Array::New(interface_count));
-  dart::Class& interface_class = dart::Class::Handle(Z);
   for (intptr_t i = 0; i < interface_count; i++) {
     InterfaceType* kernel_interface_type =
         kernel_klass->implemented_classes()[i];
@@ -292,33 +280,14 @@
         T.TranslateTypeWithoutFinalization(kernel_interface_type);
     if (type.IsMalformed()) H.ReportError("Malformed interface type.");
     interfaces.SetAt(i, type);
-
-    // NOTE: Normally the DartVM keeps a list of pending classes and iterates
-    // through them later on using `ClassFinalizer::ProcessPendingClasses()`.
-    // This involes calling `ClassFinalizer::ResolveSuperTypeAndInterfaces()`
-    // which does a lot of error validation (e.g. cycle checks) which we don't
-    // need here.  But we do need to do one thing which this resolving phase
-    // normally does for us: set the `is_implemented` boolean.
-
-    // TODO(27590): Maybe we can do this differently once we have
-    // "bootstrapping from kernel"-support.
-    interface_class = type.type_class();
-    interface_class.set_is_implemented();
   }
   klass->set_interfaces(interfaces);
   if (kernel_klass->is_abstract()) klass->set_is_abstract();
-  klass->set_is_cycle_free();
-
-  // When bootstrapping we should not finalize types yet because they will be
-  // finalized when the object store's pending_classes list is drained by
-  // ClassFinalizer::ProcessPendingClasses.  Even when not bootstrapping we are
-  // careful not to eagerly finalize types that may introduce a circularity
-  // (such as type arguments, interface types, field types, etc.).
-  if (finalize_) ClassFinalizer::FinalizeTypesInClass(*klass);
 }
 
-void KernelReader::ReadClass(const dart::Library& library,
-                             Class* kernel_klass) {
+
+dart::Class& KernelReader::ReadClass(const dart::Library& library,
+                                     Class* kernel_klass) {
   // This will trigger a call to [ReadPreliminaryClass] if not already done.
   dart::Class& klass = LookupClass(kernel_klass);
 
@@ -383,8 +352,11 @@
     GrowableObjectArray::Handle(Z, I->object_store()->pending_classes())
         .Add(klass, Heap::kOld);
   }
+
+  return klass;
 }
 
+
 void KernelReader::ReadProcedure(const dart::Library& library,
                                  const dart::Class& owner,
                                  Procedure* kernel_procedure,
@@ -524,6 +496,7 @@
   }
 }
 
+
 void KernelReader::SetupFunctionParameters(TranslationHelper translation_helper,
                                            DartTypeTranslator type_translator,
                                            const dart::Class& klass,
@@ -594,6 +567,7 @@
                                                      : return_type);
 }
 
+
 void KernelReader::SetupFieldAccessorFunction(const dart::Class& klass,
                                               const dart::Function& function) {
   bool is_setter = function.IsImplicitSetterFunction();
@@ -679,6 +653,7 @@
   return *handle;
 }
 
+
 RawFunction::Kind KernelReader::GetFunctionType(Procedure* kernel_procedure) {
   intptr_t lookuptable[] = {
       RawFunction::kRegularFunction,  // Procedure::kMethod
@@ -696,5 +671,7 @@
   }
 }
 
+
 }  // namespace kernel
 }  // namespace dart
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/kernel_reader.h b/runtime/vm/kernel_reader.h
index 23dc2e9..6b1db8a 100644
--- a/runtime/vm/kernel_reader.h
+++ b/runtime/vm/kernel_reader.h
@@ -5,6 +5,7 @@
 #ifndef RUNTIME_VM_KERNEL_READER_H_
 #define RUNTIME_VM_KERNEL_READER_H_
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 #include <map>
 
 #include "vm/kernel.h"
@@ -25,8 +26,6 @@
       : TranslationHelper(thread, zone, isolate), reader_(reader) {}
   virtual ~BuildingTranslationHelper() {}
 
-  virtual void SetFinalize(bool finalize);
-
   virtual RawLibrary* LookupLibraryByKernelLibrary(Library* library);
   virtual RawClass* LookupClassByKernelClass(Class* klass);
 
@@ -60,9 +59,10 @@
         zone_(thread_->zone()),
         isolate_(thread_->isolate()),
         translation_helper_(this, thread_, zone_, isolate_),
-        type_translator_(&translation_helper_, &active_class_, !bootstrapping),
+        type_translator_(&translation_helper_,
+                         &active_class_,
+                         /*finalize=*/false),
         bootstrapping_(bootstrapping),
-        finalize_(!bootstrapping),
         buffer_(buffer),
         buffer_length_(len) {}
 
@@ -83,7 +83,7 @@
   friend class BuildingTranslationHelper;
 
   void ReadPreliminaryClass(dart::Class* klass, Class* kernel_klass);
-  void ReadClass(const dart::Library& library, Class* kernel_klass);
+  dart::Class& ReadClass(const dart::Library& library, Class* kernel_klass);
   void ReadProcedure(const dart::Library& library,
                      const dart::Class& owner,
                      Procedure* procedure,
@@ -110,9 +110,6 @@
 
   bool bootstrapping_;
 
-  // Should created classes be finalized when they are created?
-  bool finalize_;
-
   const uint8_t* buffer_;
   intptr_t buffer_length_;
 
@@ -123,4 +120,5 @@
 }  // namespace kernel
 }  // namespace dart
 
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 #endif  // RUNTIME_VM_KERNEL_READER_H_
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
index 46750fd..5490abb 100644
--- a/runtime/vm/kernel_to_il.cc
+++ b/runtime/vm/kernel_to_il.cc
@@ -18,6 +18,7 @@
 #include "vm/resolver.h"
 #include "vm/stack_frame.h"
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 namespace dart {
 
 DECLARE_FLAG(bool, support_externalizable_strings);
@@ -645,6 +646,16 @@
   for (intptr_t i = 0; i < type_parameters.length(); ++i) {
     VisitTypeParameter(type_parameters[i]);
   }
+
+  if (node->async_marker() == FunctionNode::kSyncYielding) {
+    LocalScope* scope = parsed_function_->node_sequence()->scope();
+    for (intptr_t i = 0;
+         i < parsed_function_->function().NumOptionalPositionalParameters();
+         i++) {
+      scope->VariableAt(i)->set_is_forced_stack();
+    }
+  }
+
   // Do not visit the positional and named parameters, because they've
   // already been added to the scope.
   if (node->body() != NULL) {
@@ -1109,6 +1120,21 @@
 }
 
 
+dart::RawUnresolvedClass* TranslationHelper::ToUnresolvedClass(
+    Class* kernel_klass) {
+  dart::RawClass* klass = NULL;
+
+  const dart::String& class_name = DartClassName(kernel_klass);
+  Library* kernel_library = Library::Cast(kernel_klass->parent());
+  dart::Library& library =
+      dart::Library::Handle(Z, LookupLibraryByKernelLibrary(kernel_library));
+
+  ASSERT(klass != Object::null());
+  return dart::UnresolvedClass::New(library, class_name,
+                                    TokenPosition::kNoSource);
+}
+
+
 dart::RawField* TranslationHelper::LookupFieldByKernelField(
     Field* kernel_field) {
   TreeNode* node = kernel_field->parent();
@@ -1843,7 +1869,9 @@
       try_catch_block_(NULL),
       next_used_try_index_(0),
       catch_block_(NULL),
-      type_translator_(&translation_helper_, &active_class_),
+      type_translator_(&translation_helper_,
+                       &active_class_,
+                       /* finalize= */ true),
       constant_evaluator_(this,
                           zone_,
                           &translation_helper_,
@@ -3861,10 +3889,8 @@
     DartType* node) {
   bool saved_finalize = finalize_;
   finalize_ = false;
-  H.SetFinalize(false);
   AbstractType& result = TranslateType(node);
   finalize_ = saved_finalize;
-  H.SetFinalize(saved_finalize);
   return result;
 }
 
@@ -4020,13 +4046,13 @@
   const TypeArguments& type_arguments = TranslateTypeArguments(
       node->type_arguments().raw_array(), node->type_arguments().length());
 
-  const dart::Class& klass =
-      dart::Class::Handle(Z, H.LookupClassByKernelClass(node->klass()));
 
+  dart::Object& klass =
+      dart::Object::Handle(Z, H.ToUnresolvedClass(node->klass()));
   result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
-  result_.SetIsResolved();
   if (finalize_) {
-    result_ = ClassFinalizer::FinalizeType(klass, result_,
+    ASSERT(active_class_->klass != NULL);
+    result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_,
                                            ClassFinalizer::kCanonicalize);
   }
 }
@@ -5653,9 +5679,6 @@
     ASSERT(stack_trace_var->name().raw() ==
            Symbols::StackTraceParameter().raw());
 
-    exception_var->set_is_forced_stack();
-    stack_trace_var->set_is_forced_stack();
-
     TargetEntryInstr* no_error;
     TargetEntryInstr* error;
 
@@ -5745,3 +5768,4 @@
 
 }  // namespace kernel
 }  // namespace dart
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h
index 5001451..5f2539b 100644
--- a/runtime/vm/kernel_to_il.h
+++ b/runtime/vm/kernel_to_il.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_KERNEL_TO_IL_H_
 #define RUNTIME_VM_KERNEL_TO_IL_H_
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
 #include "vm/growable_array.h"
 #include "vm/hash_map.h"
 
@@ -202,11 +204,6 @@
 
   Heap::Space allocation_space() { return allocation_space_; }
 
-  // Set whether unfinalized classes should be finalized.  The base class
-  // implementation used at flow graph construction time looks up classes in the
-  // VM's heap, all of which should already be finalized.
-  virtual void SetFinalize(bool finalize) {}
-
   RawInstance* Canonicalize(const Instance& instance);
 
   const dart::String& DartString(const char* content) {
@@ -241,6 +238,8 @@
   virtual RawLibrary* LookupLibraryByKernelLibrary(Library* library);
   virtual RawClass* LookupClassByKernelClass(Class* klass);
 
+  RawUnresolvedClass* ToUnresolvedClass(Class* klass);
+
   RawField* LookupFieldByKernelField(Field* field);
   RawFunction* LookupStaticMethodByKernelProcedure(Procedure* procedure);
   RawFunction* LookupConstructorByKernelConstructor(Constructor* constructor);
@@ -282,7 +281,7 @@
  public:
   DartTypeTranslator(TranslationHelper* helper,
                      ActiveClass* active_class,
-                     bool finalize = true)
+                     bool finalize = false)
       : translation_helper_(*helper),
         active_class_(active_class),
         zone_(helper->zone()),
@@ -501,7 +500,9 @@
         node_(node),
         zone_(Thread::Current()->zone()),
         translation_helper_(Thread::Current(), zone_, Isolate::Current()),
-        type_translator_(&translation_helper_, &active_class_),
+        type_translator_(&translation_helper_,
+                         &active_class_,
+                         /*finalize=*/true),
         current_function_scope_(NULL),
         scope_(NULL),
         depth_(0),
@@ -919,5 +920,5 @@
 }  // namespace kernel
 }  // namespace dart
 
-
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 #endif  // RUNTIME_VM_KERNEL_TO_IL_H_
diff --git a/runtime/vm/method_recognizer.cc b/runtime/vm/method_recognizer.cc
index f25e4d3..12694a8 100644
--- a/runtime/vm/method_recognizer.cc
+++ b/runtime/vm/method_recognizer.cc
@@ -132,7 +132,7 @@
 }
 
 
-#if defined(DART_NO_SNAPSHOT)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void MethodRecognizer::InitializeState() {
   GrowableArray<Library*> libs(3);
   libs.Add(&Library::ZoneHandle(Library::CoreLibrary()));
@@ -182,6 +182,7 @@
 #undef SET_IS_POLYMORPHIC_TARGET
 #undef SET_FUNCTION_BIT
 }
-#endif  // defined(DART_NO_SNAPSHOT).
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 
 }  // namespace dart
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index ed079f6..580582f 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -518,19 +518,20 @@
   static intptr_t ResultCid(const Function& function);
   static intptr_t MethodKindToReceiverCid(Kind kind);
   static const char* KindToCString(Kind kind);
-#if defined(DART_NO_SNAPSHOT)
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
   static void InitializeState();
-#endif  // defined(DART_NO_SNAPSHOT).
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
 
 
-#if defined(DART_NO_SNAPSHOT)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 #define CHECK_FINGERPRINT2(f, p0, p1, fp)                                      \
   ASSERT(f.CheckSourceFingerprint(#p0 ", " #p1, fp))
 
 #define CHECK_FINGERPRINT3(f, p0, p1, p2, fp)                                  \
   ASSERT(f.CheckSourceFingerprint(#p0 ", " #p1 ", " #p2, fp))
-#endif  // defined(DART_NO_SNAPSHOT).
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 
 // clang-format off
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 87d48c8..673ae03 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1119,631 +1119,629 @@
 }
 
 
-RawError* Object::Init(Isolate* isolate) {
+// Initialize a new isolate from source or from a snapshot.
+//
+// There are three possibilities:
+//   1. Running a Kernel binary.  This function will bootstrap from the KERNEL
+//      file.
+//   2. There is no snapshot.  This function will bootstrap from source.
+//   3. There is a snapshot.  The caller should initialize from the snapshot.
+//
+// A non-NULL kernel argument indicates (1).  A NULL kernel indicates (2) or
+// (3), depending on whether the VM is compiled with DART_NO_SNAPSHOT defined or
+// not.
+RawError* Object::Init(Isolate* isolate,
+                       const uint8_t* kernel_buffer,
+                       intptr_t kernel_buffer_length) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   ASSERT(isolate == thread->isolate());
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  const bool is_kernel = (kernel_buffer != NULL);
+#endif
   NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(),
-                                           "Object::Init"));
+                                           "Object::Init");)
 
 #if defined(DART_NO_SNAPSHOT)
-  // Object::Init version when we are running in a version of dart that does
-  // not have a full snapshot linked in.
-  ObjectStore* object_store = isolate->object_store();
+  bool bootstrapping = true;
+#elif defined(DART_PRECOMPILED_RUNTIME)
+  bool bootstrapping = false;
+#else
+  bool bootstrapping = is_kernel;
+#endif
 
-  Class& cls = Class::Handle(zone);
-  Type& type = Type::Handle(zone);
-  Array& array = Array::Handle(zone);
-  Library& lib = Library::Handle(zone);
+  if (bootstrapping) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    // Object::Init version when we are bootstrapping from source or from a
+    // Kernel binary.
+    ObjectStore* object_store = isolate->object_store();
 
-  // All RawArray fields will be initialized to an empty array, therefore
-  // initialize array class first.
-  cls = Class::New<Array>();
-  object_store->set_array_class(cls);
+    Class& cls = Class::Handle(zone);
+    Type& type = Type::Handle(zone);
+    Array& array = Array::Handle(zone);
+    Library& lib = Library::Handle(zone);
 
-  // VM classes that are parameterized (Array, ImmutableArray,
-  // GrowableObjectArray, and LinkedHashMap) are also pre-finalized,
-  // so CalculateFieldOffsets() is not called, so we need to set the
-  // offset of their type_arguments_ field, which is explicitly
-  // declared in their respective Raw* classes.
-  cls.set_type_arguments_field_offset(Array::type_arguments_offset());
-  cls.set_num_type_arguments(1);
+    // All RawArray fields will be initialized to an empty array, therefore
+    // initialize array class first.
+    cls = Class::New<Array>();
+    object_store->set_array_class(cls);
 
-  // Set up the growable object array class (Has to be done after the array
-  // class is setup as one of its field is an array object).
-  cls = Class::New<GrowableObjectArray>();
-  object_store->set_growable_object_array_class(cls);
-  cls.set_type_arguments_field_offset(
-      GrowableObjectArray::type_arguments_offset());
-  cls.set_num_type_arguments(1);
+    // VM classes that are parameterized (Array, ImmutableArray,
+    // GrowableObjectArray, and LinkedHashMap) are also pre-finalized, so
+    // CalculateFieldOffsets() is not called, so we need to set the offset of
+    // their type_arguments_ field, which is explicitly declared in their
+    // respective Raw* classes.
+    cls.set_type_arguments_field_offset(Array::type_arguments_offset());
+    cls.set_num_type_arguments(1);
 
-  // Initialize hash set for canonical_type_.
-  const intptr_t kInitialCanonicalTypeSize = 16;
-  array =
-      HashTables::New<CanonicalTypeSet>(kInitialCanonicalTypeSize, Heap::kOld);
-  object_store->set_canonical_types(array);
+    // Set up the growable object array class (Has to be done after the array
+    // class is setup as one of its field is an array object).
+    cls = Class::New<GrowableObjectArray>();
+    object_store->set_growable_object_array_class(cls);
+    cls.set_type_arguments_field_offset(
+        GrowableObjectArray::type_arguments_offset());
+    cls.set_num_type_arguments(1);
 
-  // Initialize hash set for canonical_type_arguments_.
-  const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
-  array = HashTables::New<CanonicalTypeArgumentsSet>(
-      kInitialCanonicalTypeArgumentsSize, Heap::kOld);
-  object_store->set_canonical_type_arguments(array);
+    // Initialize hash set for canonical_type_.
+    const intptr_t kInitialCanonicalTypeSize = 16;
+    array = HashTables::New<CanonicalTypeSet>(kInitialCanonicalTypeSize,
+                                              Heap::kOld);
+    object_store->set_canonical_types(array);
 
-  // Setup type class early in the process.
-  const Class& type_cls = Class::Handle(zone, Class::New<Type>());
-  const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
-  const Class& type_parameter_cls =
-      Class::Handle(zone, Class::New<TypeParameter>());
-  const Class& bounded_type_cls =
-      Class::Handle(zone, Class::New<BoundedType>());
-  const Class& mixin_app_type_cls =
-      Class::Handle(zone, Class::New<MixinAppType>());
-  const Class& library_prefix_cls =
-      Class::Handle(zone, Class::New<LibraryPrefix>());
+    // Initialize hash set for canonical_type_arguments_.
+    const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
+    array = HashTables::New<CanonicalTypeArgumentsSet>(
+        kInitialCanonicalTypeArgumentsSize, Heap::kOld);
+    object_store->set_canonical_type_arguments(array);
 
-  // Pre-allocate the OneByteString class needed by the symbol table.
-  cls = Class::NewStringClass(kOneByteStringCid);
-  object_store->set_one_byte_string_class(cls);
+    // Setup type class early in the process.
+    const Class& type_cls = Class::Handle(zone, Class::New<Type>());
+    const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
+    const Class& type_parameter_cls =
+        Class::Handle(zone, Class::New<TypeParameter>());
+    const Class& bounded_type_cls =
+        Class::Handle(zone, Class::New<BoundedType>());
+    const Class& mixin_app_type_cls =
+        Class::Handle(zone, Class::New<MixinAppType>());
+    const Class& library_prefix_cls =
+        Class::Handle(zone, Class::New<LibraryPrefix>());
 
-  // Pre-allocate the TwoByteString class needed by the symbol table.
-  cls = Class::NewStringClass(kTwoByteStringCid);
-  object_store->set_two_byte_string_class(cls);
+    // Pre-allocate the OneByteString class needed by the symbol table.
+    cls = Class::NewStringClass(kOneByteStringCid);
+    object_store->set_one_byte_string_class(cls);
 
-  // Setup the symbol table for the symbols created in the isolate.
-  Symbols::SetupSymbolTable(isolate);
+    // Pre-allocate the TwoByteString class needed by the symbol table.
+    cls = Class::NewStringClass(kTwoByteStringCid);
+    object_store->set_two_byte_string_class(cls);
 
-  // Set up the libraries array before initializing the core library.
-  const GrowableObjectArray& libraries =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New(Heap::kOld));
-  object_store->set_libraries(libraries);
+    // Setup the symbol table for the symbols created in the isolate.
+    Symbols::SetupSymbolTable(isolate);
 
-  // Pre-register the core library.
-  Library::InitCoreLibrary(isolate);
+    // Set up the libraries array before initializing the core library.
+    const GrowableObjectArray& libraries =
+        GrowableObjectArray::Handle(zone, GrowableObjectArray::New(Heap::kOld));
+    object_store->set_libraries(libraries);
 
-  // Basic infrastructure has been setup, initialize the class dictionary.
-  const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
-  ASSERT(!core_lib.IsNull());
+    // Pre-register the core library.
+    Library::InitCoreLibrary(isolate);
 
-  const GrowableObjectArray& pending_classes =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
-  object_store->set_pending_classes(pending_classes);
+    // Basic infrastructure has been setup, initialize the class dictionary.
+    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
+    ASSERT(!core_lib.IsNull());
 
-  Context& context = Context::Handle(zone, Context::New(0, Heap::kOld));
-  object_store->set_empty_context(context);
+    const GrowableObjectArray& pending_classes =
+        GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+    object_store->set_pending_classes(pending_classes);
 
-  // Now that the symbol table is initialized and that the core dictionary as
-  // well as the core implementation dictionary have been setup, preallocate
-  // remaining classes and register them by name in the dictionaries.
-  String& name = String::Handle(zone);
-  cls = object_store->array_class();  // Was allocated above.
-  RegisterPrivateClass(cls, Symbols::_List(), core_lib);
-  pending_classes.Add(cls);
-  // We cannot use NewNonParameterizedType(cls), because Array is parameterized.
-  // Warning: class _List has not been patched yet. Its declared number of type
-  // parameters is still 0. It will become 1 after patching. The array type
-  // allocated below represents the raw type _List and not _List<E> as we
-  // could expect. Use with caution.
-  type ^= Type::New(Object::Handle(zone, cls.raw()),
-                    TypeArguments::Handle(zone), TokenPosition::kNoSource);
-  type.SetIsFinalized();
-  type ^= type.Canonicalize();
-  object_store->set_array_type(type);
+    Context& context = Context::Handle(zone, Context::New(0, Heap::kOld));
+    object_store->set_empty_context(context);
 
-  cls = object_store->growable_object_array_class();  // Was allocated above.
-  RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib);
-  pending_classes.Add(cls);
+    // Now that the symbol table is initialized and that the core dictionary as
+    // well as the core implementation dictionary have been setup, preallocate
+    // remaining classes and register them by name in the dictionaries.
+    String& name = String::Handle(zone);
+    cls = object_store->array_class();  // Was allocated above.
+    RegisterPrivateClass(cls, Symbols::_List(), core_lib);
+    pending_classes.Add(cls);
+    // We cannot use NewNonParameterizedType(cls), because Array is
+    // parameterized.  Warning: class _List has not been patched yet. Its
+    // declared number of type parameters is still 0. It will become 1 after
+    // patching. The array type allocated below represents the raw type _List
+    // and not _List<E> as we could expect. Use with caution.
+    type ^= Type::New(Object::Handle(zone, cls.raw()),
+                      TypeArguments::Handle(zone), TokenPosition::kNoSource);
+    type.SetIsFinalized();
+    type ^= type.Canonicalize();
+    object_store->set_array_type(type);
 
-  cls = Class::New<Array>(kImmutableArrayCid);
-  object_store->set_immutable_array_class(cls);
-  cls.set_type_arguments_field_offset(Array::type_arguments_offset());
-  cls.set_num_type_arguments(1);
-  ASSERT(object_store->immutable_array_class() != object_store->array_class());
-  cls.set_is_prefinalized();
-  RegisterPrivateClass(cls, Symbols::_ImmutableList(), core_lib);
-  pending_classes.Add(cls);
+    cls = object_store->growable_object_array_class();  // Was allocated above.
+    RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = object_store->one_byte_string_class();  // Was allocated above.
-  RegisterPrivateClass(cls, Symbols::OneByteString(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Array>(kImmutableArrayCid);
+    object_store->set_immutable_array_class(cls);
+    cls.set_type_arguments_field_offset(Array::type_arguments_offset());
+    cls.set_num_type_arguments(1);
+    ASSERT(object_store->immutable_array_class() !=
+           object_store->array_class());
+    cls.set_is_prefinalized();
+    RegisterPrivateClass(cls, Symbols::_ImmutableList(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = object_store->two_byte_string_class();  // Was allocated above.
-  RegisterPrivateClass(cls, Symbols::TwoByteString(), core_lib);
-  pending_classes.Add(cls);
+    cls = object_store->one_byte_string_class();  // Was allocated above.
+    RegisterPrivateClass(cls, Symbols::OneByteString(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::NewStringClass(kExternalOneByteStringCid);
-  object_store->set_external_one_byte_string_class(cls);
-  RegisterPrivateClass(cls, Symbols::ExternalOneByteString(), core_lib);
-  pending_classes.Add(cls);
+    cls = object_store->two_byte_string_class();  // Was allocated above.
+    RegisterPrivateClass(cls, Symbols::TwoByteString(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::NewStringClass(kExternalTwoByteStringCid);
-  object_store->set_external_two_byte_string_class(cls);
-  RegisterPrivateClass(cls, Symbols::ExternalTwoByteString(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::NewStringClass(kExternalOneByteStringCid);
+    object_store->set_external_one_byte_string_class(cls);
+    RegisterPrivateClass(cls, Symbols::ExternalOneByteString(), core_lib);
+    pending_classes.Add(cls);
 
-  // Pre-register the isolate library so the native class implementations
-  // can be hooked up before compiling it.
-  Library& isolate_lib = Library::Handle(
-      zone, Library::LookupLibrary(thread, Symbols::DartIsolate()));
-  if (isolate_lib.IsNull()) {
-    isolate_lib = Library::NewLibraryHelper(Symbols::DartIsolate(), true);
-    isolate_lib.SetLoadRequested();
-    isolate_lib.Register(thread);
+    cls = Class::NewStringClass(kExternalTwoByteStringCid);
+    object_store->set_external_two_byte_string_class(cls);
+    RegisterPrivateClass(cls, Symbols::ExternalTwoByteString(), core_lib);
+    pending_classes.Add(cls);
+
+    // Pre-register the isolate library so the native class implementations can
+    // be hooked up before compiling it.
+    Library& isolate_lib = Library::Handle(
+        zone, Library::LookupLibrary(thread, Symbols::DartIsolate()));
+    if (isolate_lib.IsNull()) {
+      isolate_lib = Library::NewLibraryHelper(Symbols::DartIsolate(), true);
+      isolate_lib.SetLoadRequested();
+      isolate_lib.Register(thread);
+    }
     object_store->set_bootstrap_library(ObjectStore::kIsolate, isolate_lib);
-  }
-  ASSERT(!isolate_lib.IsNull());
-  ASSERT(isolate_lib.raw() == Library::IsolateLibrary());
+    ASSERT(!isolate_lib.IsNull());
+    ASSERT(isolate_lib.raw() == Library::IsolateLibrary());
 
-  cls = Class::New<Capability>();
-  RegisterPrivateClass(cls, Symbols::_CapabilityImpl(), isolate_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Capability>();
+    RegisterPrivateClass(cls, Symbols::_CapabilityImpl(), isolate_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<ReceivePort>();
-  RegisterPrivateClass(cls, Symbols::_RawReceivePortImpl(), isolate_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<ReceivePort>();
+    RegisterPrivateClass(cls, Symbols::_RawReceivePortImpl(), isolate_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<SendPort>();
-  RegisterPrivateClass(cls, Symbols::_SendPortImpl(), isolate_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<SendPort>();
+    RegisterPrivateClass(cls, Symbols::_SendPortImpl(), isolate_lib);
+    pending_classes.Add(cls);
 
-  const Class& stacktrace_cls = Class::Handle(zone, Class::New<Stacktrace>());
-  RegisterPrivateClass(stacktrace_cls, Symbols::_StackTrace(), core_lib);
-  pending_classes.Add(stacktrace_cls);
-  // Super type set below, after Object is allocated.
+    const Class& stacktrace_cls = Class::Handle(zone, Class::New<Stacktrace>());
+    RegisterPrivateClass(stacktrace_cls, Symbols::_StackTrace(), core_lib);
+    pending_classes.Add(stacktrace_cls);
+    // Super type set below, after Object is allocated.
 
-  cls = Class::New<RegExp>();
-  RegisterPrivateClass(cls, Symbols::_RegExp(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<RegExp>();
+    RegisterPrivateClass(cls, Symbols::_RegExp(), core_lib);
+    pending_classes.Add(cls);
 
-  // Initialize the base interfaces used by the core VM classes.
+    // Initialize the base interfaces used by the core VM classes.
 
-  // Allocate and initialize the pre-allocated classes in the core library.
-  // The script and token index of these pre-allocated classes is set up in
-  // the parser when the corelib script is compiled (see
-  // Parser::ParseClassDefinition).
-  cls = Class::New<Instance>(kInstanceCid);
-  object_store->set_object_class(cls);
-  cls.set_name(Symbols::Object());
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  core_lib.AddClass(cls);
-  pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_object_type(type);
+    // Allocate and initialize the pre-allocated classes in the core library.
+    // The script and token index of these pre-allocated classes is set up in
+    // the parser when the corelib script is compiled (see
+    // Parser::ParseClassDefinition).
+    cls = Class::New<Instance>(kInstanceCid);
+    object_store->set_object_class(cls);
+    cls.set_name(Symbols::Object());
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    core_lib.AddClass(cls);
+    pending_classes.Add(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_object_type(type);
 
-  cls = Class::New<Bool>();
-  object_store->set_bool_class(cls);
-  RegisterClass(cls, Symbols::Bool(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Bool>();
+    object_store->set_bool_class(cls);
+    RegisterClass(cls, Symbols::Bool(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<Instance>(kNullCid);
-  object_store->set_null_class(cls);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  RegisterClass(cls, Symbols::Null(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Instance>(kNullCid);
+    object_store->set_null_class(cls);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    RegisterClass(cls, Symbols::Null(), core_lib);
+    pending_classes.Add(cls);
 
-  ASSERT(!library_prefix_cls.IsNull());
-  RegisterPrivateClass(library_prefix_cls, Symbols::_LibraryPrefix(), core_lib);
-  pending_classes.Add(library_prefix_cls);
+    ASSERT(!library_prefix_cls.IsNull());
+    RegisterPrivateClass(library_prefix_cls, Symbols::_LibraryPrefix(),
+                         core_lib);
+    pending_classes.Add(library_prefix_cls);
 
-  RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
-  pending_classes.Add(type_cls);
+    RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
+    pending_classes.Add(type_cls);
 
-  RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
-  pending_classes.Add(type_ref_cls);
+    RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
+    pending_classes.Add(type_ref_cls);
 
-  RegisterPrivateClass(type_parameter_cls, Symbols::TypeParameter(), core_lib);
-  pending_classes.Add(type_parameter_cls);
+    RegisterPrivateClass(type_parameter_cls, Symbols::TypeParameter(),
+                         core_lib);
+    pending_classes.Add(type_parameter_cls);
 
-  RegisterPrivateClass(bounded_type_cls, Symbols::BoundedType(), core_lib);
-  pending_classes.Add(bounded_type_cls);
+    RegisterPrivateClass(bounded_type_cls, Symbols::BoundedType(), core_lib);
+    pending_classes.Add(bounded_type_cls);
 
-  RegisterPrivateClass(mixin_app_type_cls, Symbols::MixinAppType(), core_lib);
-  pending_classes.Add(mixin_app_type_cls);
+    RegisterPrivateClass(mixin_app_type_cls, Symbols::MixinAppType(), core_lib);
+    pending_classes.Add(mixin_app_type_cls);
 
-  cls = Class::New<Integer>();
-  object_store->set_integer_implementation_class(cls);
-  RegisterPrivateClass(cls, Symbols::IntegerImplementation(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Integer>();
+    object_store->set_integer_implementation_class(cls);
+    RegisterPrivateClass(cls, Symbols::IntegerImplementation(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<Smi>();
-  object_store->set_smi_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Smi(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Smi>();
+    object_store->set_smi_class(cls);
+    RegisterPrivateClass(cls, Symbols::_Smi(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<Mint>();
-  object_store->set_mint_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Mint(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Mint>();
+    object_store->set_mint_class(cls);
+    RegisterPrivateClass(cls, Symbols::_Mint(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<Bigint>();
-  object_store->set_bigint_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Bigint(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Bigint>();
+    object_store->set_bigint_class(cls);
+    RegisterPrivateClass(cls, Symbols::_Bigint(), core_lib);
+    pending_classes.Add(cls);
 
-  cls = Class::New<Double>();
-  object_store->set_double_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Double>();
+    object_store->set_double_class(cls);
+    RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
+    pending_classes.Add(cls);
 
-  // Class that represents the Dart class _Closure and C++ class Closure.
-  cls = Class::New<Closure>();
-  cls.set_type_arguments_field_offset(Closure::type_arguments_offset());
-  cls.set_num_type_arguments(0);  // Although a closure has type_arguments_.
-  cls.set_num_own_type_arguments(0);
-  RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
-  pending_classes.Add(cls);
-  object_store->set_closure_class(cls);
+    // Class that represents the Dart class _Closure and C++ class Closure.
+    cls = Class::New<Closure>();
+    cls.set_type_arguments_field_offset(Closure::type_arguments_offset());
+    cls.set_num_type_arguments(0);  // Although a closure has type_arguments_.
+    cls.set_num_own_type_arguments(0);
+    RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
+    pending_classes.Add(cls);
+    object_store->set_closure_class(cls);
 
-  cls = Class::New<WeakProperty>();
-  object_store->set_weak_property_class(cls);
-  RegisterPrivateClass(cls, Symbols::_WeakProperty(), core_lib);
+    cls = Class::New<WeakProperty>();
+    object_store->set_weak_property_class(cls);
+    RegisterPrivateClass(cls, Symbols::_WeakProperty(), core_lib);
 
 // Pre-register the mirrors library so we can place the vm class
 // MirrorReference there rather than the core library.
 #if !defined(PRODUCT)
-  lib = Library::LookupLibrary(thread, Symbols::DartMirrors());
-  if (lib.IsNull()) {
-    lib = Library::NewLibraryHelper(Symbols::DartMirrors(), true);
-    lib.SetLoadRequested();
-    lib.Register(thread);
+    lib = Library::LookupLibrary(thread, Symbols::DartMirrors());
+    if (lib.IsNull()) {
+      lib = Library::NewLibraryHelper(Symbols::DartMirrors(), true);
+      lib.SetLoadRequested();
+      lib.Register(thread);
+    }
     object_store->set_bootstrap_library(ObjectStore::kMirrors, lib);
-  }
-  ASSERT(!lib.IsNull());
-  ASSERT(lib.raw() == Library::MirrorsLibrary());
+    ASSERT(!lib.IsNull());
+    ASSERT(lib.raw() == Library::MirrorsLibrary());
 
-  cls = Class::New<MirrorReference>();
-  RegisterPrivateClass(cls, Symbols::_MirrorReference(), lib);
-#endif  // !defined(PRODUCT)
+    cls = Class::New<MirrorReference>();
+    RegisterPrivateClass(cls, Symbols::_MirrorReference(), lib);
+#endif
 
-  // Pre-register the collection library so we can place the vm class
-  // LinkedHashMap there rather than the core library.
-  lib = Library::LookupLibrary(thread, Symbols::DartCollection());
-  if (lib.IsNull()) {
-    lib = Library::NewLibraryHelper(Symbols::DartCollection(), true);
-    lib.SetLoadRequested();
-    lib.Register(thread);
+    // Pre-register the collection library so we can place the vm class
+    // LinkedHashMap there rather than the core library.
+    lib = Library::LookupLibrary(thread, Symbols::DartCollection());
+    if (lib.IsNull()) {
+      lib = Library::NewLibraryHelper(Symbols::DartCollection(), true);
+      lib.SetLoadRequested();
+      lib.Register(thread);
+    }
+
     object_store->set_bootstrap_library(ObjectStore::kCollection, lib);
-  }
-  ASSERT(!lib.IsNull());
-  ASSERT(lib.raw() == Library::CollectionLibrary());
-  cls = Class::New<LinkedHashMap>();
-  object_store->set_linked_hash_map_class(cls);
-  cls.set_type_arguments_field_offset(LinkedHashMap::type_arguments_offset());
-  cls.set_num_type_arguments(2);
-  cls.set_num_own_type_arguments(2);
-  RegisterPrivateClass(cls, Symbols::_LinkedHashMap(), lib);
-  pending_classes.Add(cls);
+    ASSERT(!lib.IsNull());
+    ASSERT(lib.raw() == Library::CollectionLibrary());
+    cls = Class::New<LinkedHashMap>();
+    object_store->set_linked_hash_map_class(cls);
+    cls.set_type_arguments_field_offset(LinkedHashMap::type_arguments_offset());
+    cls.set_num_type_arguments(2);
+    cls.set_num_own_type_arguments(0);
+    RegisterPrivateClass(cls, Symbols::_LinkedHashMap(), lib);
+    pending_classes.Add(cls);
 
-  // Pre-register the developer library so we can place the vm class
-  // UserTag there rather than the core library.
-  lib = Library::LookupLibrary(thread, Symbols::DartDeveloper());
-  if (lib.IsNull()) {
-    lib = Library::NewLibraryHelper(Symbols::DartDeveloper(), true);
-    lib.SetLoadRequested();
-    lib.Register(thread);
+    // Pre-register the developer library so we can place the vm class
+    // UserTag there rather than the core library.
+    lib = Library::LookupLibrary(thread, Symbols::DartDeveloper());
+    if (lib.IsNull()) {
+      lib = Library::NewLibraryHelper(Symbols::DartDeveloper(), true);
+      lib.SetLoadRequested();
+      lib.Register(thread);
+    }
     object_store->set_bootstrap_library(ObjectStore::kDeveloper, lib);
-  }
-  ASSERT(!lib.IsNull());
-  ASSERT(lib.raw() == Library::DeveloperLibrary());
+    ASSERT(!lib.IsNull());
+    ASSERT(lib.raw() == Library::DeveloperLibrary());
+    cls = Class::New<UserTag>();
+    RegisterPrivateClass(cls, Symbols::_UserTag(), lib);
+    pending_classes.Add(cls);
 
-  lib = Library::LookupLibrary(thread, Symbols::DartDeveloper());
-  ASSERT(!lib.IsNull());
-  cls = Class::New<UserTag>();
-  RegisterPrivateClass(cls, Symbols::_UserTag(), lib);
-  pending_classes.Add(cls);
+    // Setup some default native field classes which can be extended for
+    // specifying native fields in dart classes.
+    Library::InitNativeWrappersLibrary(isolate, is_kernel);
+    ASSERT(object_store->native_wrappers_library() != Library::null());
 
-  // Setup some default native field classes which can be extended for
-  // specifying native fields in dart classes.
-  Library::InitNativeWrappersLibrary(isolate);
-  ASSERT(object_store->native_wrappers_library() != Library::null());
-
-  // Pre-register the typed_data library so the native class implementations
-  // can be hooked up before compiling it.
-  lib = Library::LookupLibrary(thread, Symbols::DartTypedData());
-  if (lib.IsNull()) {
-    lib = Library::NewLibraryHelper(Symbols::DartTypedData(), true);
-    lib.SetLoadRequested();
-    lib.Register(thread);
+    // Pre-register the typed_data library so the native class implementations
+    // can be hooked up before compiling it.
+    lib = Library::LookupLibrary(thread, Symbols::DartTypedData());
+    if (lib.IsNull()) {
+      lib = Library::NewLibraryHelper(Symbols::DartTypedData(), true);
+      lib.SetLoadRequested();
+      lib.Register(thread);
+    }
     object_store->set_bootstrap_library(ObjectStore::kTypedData, lib);
-  }
-  ASSERT(!lib.IsNull());
-  ASSERT(lib.raw() == Library::TypedDataLibrary());
+    ASSERT(!lib.IsNull());
+    ASSERT(lib.raw() == Library::TypedDataLibrary());
 #define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
   cls = Class::NewTypedDataClass(kTypedData##clazz##ArrayCid);                 \
   RegisterClass(cls, Symbols::clazz##List(), lib);
 
-  DART_CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
+    DART_CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
 #undef REGISTER_TYPED_DATA_CLASS
 #define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
   cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid);              \
   RegisterPrivateClass(cls, Symbols::_##clazz##View(), lib);                   \
   pending_classes.Add(cls);
 
-  CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
-  cls = Class::NewTypedDataViewClass(kByteDataViewCid);
-  RegisterPrivateClass(cls, Symbols::_ByteDataView(), lib);
-  pending_classes.Add(cls);
+    CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
+    cls = Class::NewTypedDataViewClass(kByteDataViewCid);
+    RegisterPrivateClass(cls, Symbols::_ByteDataView(), lib);
+    pending_classes.Add(cls);
 #undef REGISTER_TYPED_DATA_VIEW_CLASS
 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
   cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid);      \
   RegisterPrivateClass(cls, Symbols::_External##clazz(), lib);
 
-  cls = Class::New<Instance>(kByteBufferCid);
-  cls.set_instance_size(0);
-  cls.set_next_field_offset(-kWordSize);
-  RegisterClass(cls, Symbols::ByteBuffer(), lib);
-  pending_classes.Add(cls);
+    cls = Class::New<Instance>(kByteBufferCid);
+    cls.set_instance_size(0);
+    cls.set_next_field_offset(-kWordSize);
+    RegisterClass(cls, Symbols::ByteBuffer(), lib);
+    pending_classes.Add(cls);
 
-  CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
+    CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
 #undef REGISTER_EXT_TYPED_DATA_CLASS
-  // Register Float32x4 and Int32x4 in the object store.
-  cls = Class::New<Float32x4>();
-  RegisterClass(cls, Symbols::Float32x4(), lib);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  pending_classes.Add(cls);
-  object_store->set_float32x4_class(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_float32x4_type(type);
+    // Register Float32x4 and Int32x4 in the object store.
+    cls = Class::New<Float32x4>();
+    RegisterClass(cls, Symbols::Float32x4(), lib);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    object_store->set_float32x4_class(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_float32x4_type(type);
 
-  cls = Class::New<Int32x4>();
-  RegisterClass(cls, Symbols::Int32x4(), lib);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  pending_classes.Add(cls);
-  object_store->set_int32x4_class(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_int32x4_type(type);
+    cls = Class::New<Int32x4>();
+    RegisterClass(cls, Symbols::Int32x4(), lib);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    object_store->set_int32x4_class(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_int32x4_type(type);
 
-  cls = Class::New<Float64x2>();
-  RegisterClass(cls, Symbols::Float64x2(), lib);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  pending_classes.Add(cls);
-  object_store->set_float64x2_class(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_float64x2_type(type);
+    cls = Class::New<Float64x2>();
+    RegisterClass(cls, Symbols::Float64x2(), lib);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    object_store->set_float64x2_class(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_float64x2_type(type);
 
-  // Set the super type of class Stacktrace to Object type so that the
-  // 'toString' method is implemented.
-  type = object_store->object_type();
-  stacktrace_cls.set_super_type(type);
+    // Set the super type of class Stacktrace to Object type so that the
+    // 'toString' method is implemented.
+    type = object_store->object_type();
+    stacktrace_cls.set_super_type(type);
 
-  // Abstract class that represents the Dart class Function.
-  cls = Class::New<Instance>(kIllegalCid);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  RegisterClass(cls, Symbols::Function(), core_lib);
-  pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_function_type(type);
+    // Abstract class that represents the Dart class Function.
+    cls = Class::New<Instance>(kIllegalCid);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    RegisterClass(cls, Symbols::Function(), core_lib);
+    pending_classes.Add(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_function_type(type);
 
-  cls = Class::New<Number>();
-  RegisterClass(cls, Symbols::Number(), core_lib);
-  pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_number_type(type);
+    cls = Class::New<Number>();
+    RegisterClass(cls, Symbols::Number(), core_lib);
+    pending_classes.Add(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_number_type(type);
 
-  cls = Class::New<Instance>(kIllegalCid);
-  RegisterClass(cls, Symbols::Int(), core_lib);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_int_type(type);
+    cls = Class::New<Instance>(kIllegalCid);
+    RegisterClass(cls, Symbols::Int(), core_lib);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_int_type(type);
 
-  cls = Class::New<Instance>(kIllegalCid);
-  RegisterClass(cls, Symbols::Double(), core_lib);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_double_type(type);
+    cls = Class::New<Instance>(kIllegalCid);
+    RegisterClass(cls, Symbols::Double(), core_lib);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_double_type(type);
 
-  name = Symbols::_String().raw();
-  cls = Class::New<Instance>(kIllegalCid);
-  RegisterClass(cls, name, core_lib);
-  cls.set_num_type_arguments(0);
-  cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_string_type(type);
+    name = Symbols::_String().raw();
+    cls = Class::New<Instance>(kIllegalCid);
+    RegisterClass(cls, name, core_lib);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_string_type(type);
 
-  cls = object_store->bool_class();
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_bool_type(type);
+    cls = object_store->bool_class();
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_bool_type(type);
 
-  cls = object_store->smi_class();
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_smi_type(type);
+    cls = object_store->smi_class();
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_smi_type(type);
 
-  cls = object_store->mint_class();
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_mint_type(type);
+    cls = object_store->mint_class();
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_mint_type(type);
 
-  // The classes 'void' and 'dynamic' are phoney classes to make type checking
-  // more regular; they live in the VM isolate. The class 'void' is not
-  // registered in the class dictionary because its name is a reserved word.
-  // The class 'dynamic' is registered in the class dictionary because its name
-  // is a built-in identifier (this is wrong).
-  // The corresponding types are stored in the object store.
-  cls = object_store->null_class();
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_null_type(type);
+    // The classes 'void' and 'dynamic' are phony classes to make type checking
+    // more regular; they live in the VM isolate. The class 'void' is not
+    // registered in the class dictionary because its name is a reserved word.
+    // The class 'dynamic' is registered in the class dictionary because its
+    // name is a built-in identifier (this is wrong).  The corresponding types
+    // are stored in the object store.
+    cls = object_store->null_class();
+    type = Type::NewNonParameterizedType(cls);
+    object_store->set_null_type(type);
 
-  // Consider removing when/if Null becomes an ordinary class.
-  type = object_store->object_type();
-  cls.set_super_type(type);
+    // Consider removing when/if Null becomes an ordinary class.
+    type = object_store->object_type();
+    cls.set_super_type(type);
 
-  // Finish the initialization by compiling the bootstrap scripts containing the
-  // base interfaces and the implementation of the internal classes.
-  const Error& error = Error::Handle(Bootstrap::DoBootstrapping());
-  if (!error.IsNull()) {
-    return error.raw();
-  }
+    // Finish the initialization by compiling the bootstrap scripts containing
+    // the base interfaces and the implementation of the internal classes.
+    const Error& error = Error::Handle(
+        zone, Bootstrap::DoBootstrapping(kernel_buffer, kernel_buffer_length));
+    if (!error.IsNull()) {
+      return error.raw();
+    }
 
-  ClassFinalizer::VerifyBootstrapClasses();
+    ClassFinalizer::VerifyBootstrapClasses();
 
-  // Set up the intrinsic state of all functions (core, math and typed data).
-  Intrinsifier::InitializeState();
+    // Set up the intrinsic state of all functions (core, math and typed data).
+    Intrinsifier::InitializeState();
 
-  // Set up recognized state of all functions (core, math and typed data).
-  MethodRecognizer::InitializeState();
+    // Set up recognized state of all functions (core, math and typed data).
+    MethodRecognizer::InitializeState();
 
-  // Adds static const fields (class ids) to the class 'ClassID');
-  lib = Library::LookupLibrary(thread, Symbols::DartInternal());
-  ASSERT(!lib.IsNull());
-  cls = lib.LookupClassAllowPrivate(Symbols::ClassID());
-  ASSERT(!cls.IsNull());
-  Field& field = Field::Handle(zone);
-  Smi& value = Smi::Handle(zone);
-  String& field_name = String::Handle(zone);
+    isolate->object_store()->InitKnownObjects();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+    // Object::Init version when we are running in a version of dart that has a
+    // full snapshot linked in and an isolate is initialized using the full
+    // snapshot.
+    ObjectStore* object_store = isolate->object_store();
 
-#define CLASS_LIST_WITH_NULL(V)                                                \
-  V(Null)                                                                      \
-  CLASS_LIST_NO_OBJECT(V)
+    Class& cls = Class::Handle(zone);
 
-#define ADD_SET_FIELD(clazz)                                                   \
-  field_name = Symbols::New(thread, "cid" #clazz);                             \
-  field =                                                                      \
-      Field::New(field_name, true, false, true, false, cls,                    \
-                 Type::Handle(Type::IntType()), TokenPosition::kMinSource);    \
-  value = Smi::New(k##clazz##Cid);                                             \
-  field.SetStaticValue(value, true);                                           \
-  cls.AddField(field);
+    // Set up empty classes in the object store, these will get initialized
+    // correctly when we read from the snapshot.  This is done to allow
+    // bootstrapping of reading classes from the snapshot.  Some classes are not
+    // stored in the object store. Yet we still need to create their Class
+    // object so that they get put into the class_table (as a side effect of
+    // Class::New()).
+    cls = Class::New<Instance>(kInstanceCid);
+    object_store->set_object_class(cls);
 
-  CLASS_LIST_WITH_NULL(ADD_SET_FIELD)
-#undef ADD_SET_FIELD
+    cls = Class::New<LibraryPrefix>();
+    cls = Class::New<Type>();
+    cls = Class::New<TypeRef>();
+    cls = Class::New<TypeParameter>();
+    cls = Class::New<BoundedType>();
+    cls = Class::New<MixinAppType>();
 
-  isolate->object_store()->InitKnownObjects();
+    cls = Class::New<Array>();
+    object_store->set_array_class(cls);
 
-  return Error::null();
-#else  // defined(DART_NO_SNAPSHOT).
-  // Object::Init version when we are running in a version of dart that has
-  // a full snapshot linked in and an isolate is initialized using the full
-  // snapshot.
-  ObjectStore* object_store = isolate->object_store();
+    cls = Class::New<Array>(kImmutableArrayCid);
+    object_store->set_immutable_array_class(cls);
 
-  Class& cls = Class::Handle();
+    cls = Class::New<GrowableObjectArray>();
+    object_store->set_growable_object_array_class(cls);
 
-  // Set up empty classes in the object store, these will get
-  // initialized correctly when we read from the snapshot.
-  // This is done to allow bootstrapping of reading classes from the snapshot.
-  // Some classes are not stored in the object store. Yet we still need to
-  // create their Class object so that they get put into the class_table
-  // (as a side effect of Class::New()).
+    cls = Class::New<LinkedHashMap>();
+    object_store->set_linked_hash_map_class(cls);
 
-  cls = Class::New<Instance>(kInstanceCid);
-  object_store->set_object_class(cls);
+    cls = Class::New<Float32x4>();
+    object_store->set_float32x4_class(cls);
 
-  cls = Class::New<LibraryPrefix>();
-  cls = Class::New<Type>();
-  cls = Class::New<TypeRef>();
-  cls = Class::New<TypeParameter>();
-  cls = Class::New<BoundedType>();
-  cls = Class::New<MixinAppType>();
+    cls = Class::New<Int32x4>();
+    object_store->set_int32x4_class(cls);
 
-  cls = Class::New<Array>();
-  object_store->set_array_class(cls);
-
-  cls = Class::New<Array>(kImmutableArrayCid);
-  object_store->set_immutable_array_class(cls);
-
-  cls = Class::New<GrowableObjectArray>();
-  object_store->set_growable_object_array_class(cls);
-
-  cls = Class::New<LinkedHashMap>();
-  object_store->set_linked_hash_map_class(cls);
-
-  cls = Class::New<Float32x4>();
-  object_store->set_float32x4_class(cls);
-
-  cls = Class::New<Int32x4>();
-  object_store->set_int32x4_class(cls);
-
-  cls = Class::New<Float64x2>();
-  object_store->set_float64x2_class(cls);
+    cls = Class::New<Float64x2>();
+    object_store->set_float64x2_class(cls);
 
 #define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
   cls = Class::NewTypedDataClass(kTypedData##clazz##Cid);
-  CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
+    CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
 #undef REGISTER_TYPED_DATA_CLASS
 #define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
   cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid);
-  CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
+    CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
 #undef REGISTER_TYPED_DATA_VIEW_CLASS
-  cls = Class::NewTypedDataViewClass(kByteDataViewCid);
+    cls = Class::NewTypedDataViewClass(kByteDataViewCid);
 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
   cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid);
-  CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
+    CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
 #undef REGISTER_EXT_TYPED_DATA_CLASS
 
-  cls = Class::New<Instance>(kByteBufferCid);
+    cls = Class::New<Instance>(kByteBufferCid);
 
-  cls = Class::New<Integer>();
-  object_store->set_integer_implementation_class(cls);
+    cls = Class::New<Integer>();
+    object_store->set_integer_implementation_class(cls);
 
-  cls = Class::New<Smi>();
-  object_store->set_smi_class(cls);
+    cls = Class::New<Smi>();
+    object_store->set_smi_class(cls);
 
-  cls = Class::New<Mint>();
-  object_store->set_mint_class(cls);
+    cls = Class::New<Mint>();
+    object_store->set_mint_class(cls);
 
-  cls = Class::New<Double>();
-  object_store->set_double_class(cls);
+    cls = Class::New<Double>();
+    object_store->set_double_class(cls);
 
-  cls = Class::New<Closure>();
-  object_store->set_closure_class(cls);
+    cls = Class::New<Closure>();
+    object_store->set_closure_class(cls);
 
-  cls = Class::New<Bigint>();
-  object_store->set_bigint_class(cls);
+    cls = Class::New<Bigint>();
+    object_store->set_bigint_class(cls);
 
-  cls = Class::NewStringClass(kOneByteStringCid);
-  object_store->set_one_byte_string_class(cls);
+    cls = Class::NewStringClass(kOneByteStringCid);
+    object_store->set_one_byte_string_class(cls);
 
-  cls = Class::NewStringClass(kTwoByteStringCid);
-  object_store->set_two_byte_string_class(cls);
+    cls = Class::NewStringClass(kTwoByteStringCid);
+    object_store->set_two_byte_string_class(cls);
 
-  cls = Class::NewStringClass(kExternalOneByteStringCid);
-  object_store->set_external_one_byte_string_class(cls);
+    cls = Class::NewStringClass(kExternalOneByteStringCid);
+    object_store->set_external_one_byte_string_class(cls);
 
-  cls = Class::NewStringClass(kExternalTwoByteStringCid);
-  object_store->set_external_two_byte_string_class(cls);
+    cls = Class::NewStringClass(kExternalTwoByteStringCid);
+    object_store->set_external_two_byte_string_class(cls);
 
-  cls = Class::New<Bool>();
-  object_store->set_bool_class(cls);
+    cls = Class::New<Bool>();
+    object_store->set_bool_class(cls);
 
-  cls = Class::New<Instance>(kNullCid);
-  object_store->set_null_class(cls);
+    cls = Class::New<Instance>(kNullCid);
+    object_store->set_null_class(cls);
 
-  cls = Class::New<Capability>();
-  cls = Class::New<ReceivePort>();
-  cls = Class::New<SendPort>();
-  cls = Class::New<Stacktrace>();
-  cls = Class::New<RegExp>();
-  cls = Class::New<Number>();
+    cls = Class::New<Capability>();
+    cls = Class::New<ReceivePort>();
+    cls = Class::New<SendPort>();
+    cls = Class::New<Stacktrace>();
+    cls = Class::New<RegExp>();
+    cls = Class::New<Number>();
 
-  cls = Class::New<WeakProperty>();
-  object_store->set_weak_property_class(cls);
+    cls = Class::New<WeakProperty>();
+    object_store->set_weak_property_class(cls);
 
-  cls = Class::New<MirrorReference>();
-  cls = Class::New<UserTag>();
+    cls = Class::New<MirrorReference>();
+    cls = Class::New<UserTag>();
 
-  const Context& context = Context::Handle(zone, Context::New(0, Heap::kOld));
-  object_store->set_empty_context(context);
-
-#endif  // defined(DART_NO_SNAPSHOT).
-
+    const Context& context = Context::Handle(zone, Context::New(0, Heap::kOld));
+    object_store->set_empty_context(context);
+  }
   return Error::null();
 }
 
@@ -1923,7 +1921,6 @@
 
 
 RawString* Class::Name() const {
-  ASSERT(raw_ptr()->name_ != String::null());
   return raw_ptr()->name_;
 }
 
@@ -2043,7 +2040,7 @@
 }
 
 
-RawArray* Class::OffsetToFieldMap() const {
+RawArray* Class::OffsetToFieldMap(bool original_classes) const {
   Array& array = Array::Handle(raw_ptr()->offset_in_words_to_field_);
   if (array.IsNull()) {
     ASSERT(is_finalized());
@@ -2060,7 +2057,7 @@
           array.SetAt(f.Offset() >> kWordSizeLog2, f);
         }
       }
-      cls = cls.SuperClass();
+      cls = cls.SuperClass(original_classes);
     }
     StorePointer(&raw_ptr()->offset_in_words_to_field_, array.raw());
   }
@@ -2433,12 +2430,20 @@
 }
 
 
-RawClass* Class::SuperClass() const {
+RawClass* Class::SuperClass(bool original_classes) const {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Isolate* isolate = thread->isolate();
   if (super_type() == AbstractType::null()) {
     return Class::null();
   }
-  const AbstractType& sup_type = AbstractType::Handle(super_type());
-  return sup_type.type_class();
+  const AbstractType& sup_type = AbstractType::Handle(zone, super_type());
+  const intptr_t type_class_id = sup_type.type_class_id();
+  if (original_classes) {
+    return isolate->GetClassForHeapWalkAt(type_class_id);
+  } else {
+    return isolate->class_table()->At(type_class_id);
+  }
 }
 
 
@@ -2999,10 +3004,10 @@
 }
 
 
-static RawFunction* EvaluateHelper(const Class& cls,
-                                   const String& expr,
-                                   const Array& param_names,
-                                   bool is_static) {
+RawFunction* Function::EvaluateHelper(const Class& cls,
+                                      const String& expr,
+                                      const Array& param_names,
+                                      bool is_static) {
   const String& func_src =
       String::Handle(BuildClosureSource(param_names, expr));
   Script& script = Script::Handle();
@@ -3037,8 +3042,8 @@
     return UnhandledException::New(exception, stacktrace);
   }
 
-  const Function& eval_func =
-      Function::Handle(EvaluateHelper(*this, expr, param_names, true));
+  const Function& eval_func = Function::Handle(
+      Function::EvaluateHelper(*this, expr, param_names, true));
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(eval_func, param_values));
   return result.raw();
@@ -4398,11 +4403,11 @@
 }
 
 
-RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
+RawUnresolvedClass* UnresolvedClass::New(const Object& library_prefix,
                                          const String& ident,
                                          TokenPosition token_pos) {
   const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New());
-  type.set_library_prefix(library_prefix);
+  type.set_library_or_library_prefix(library_prefix);
   type.set_ident(ident);
   type.set_token_pos(token_pos);
   return type.raw();
@@ -4428,19 +4433,24 @@
 }
 
 
-void UnresolvedClass::set_library_prefix(
-    const LibraryPrefix& library_prefix) const {
-  StorePointer(&raw_ptr()->library_prefix_, library_prefix.raw());
+void UnresolvedClass::set_library_or_library_prefix(
+    const Object& library_prefix) const {
+  StorePointer(&raw_ptr()->library_or_library_prefix_, library_prefix.raw());
 }
 
 
 RawString* UnresolvedClass::Name() const {
-  if (library_prefix() != LibraryPrefix::null()) {
+  if (library_or_library_prefix() != Object::null()) {
     Thread* thread = Thread::Current();
     Zone* zone = thread->zone();
-    const LibraryPrefix& lib_prefix =
-        LibraryPrefix::Handle(zone, library_prefix());
-    const String& name = String::Handle(zone, lib_prefix.name());  // Qualifier.
+    const Object& lib_prefix =
+        Object::Handle(zone, library_or_library_prefix());
+    String& name = String::Handle(zone);  // Qualifier.
+    if (lib_prefix.IsLibraryPrefix()) {
+      name = LibraryPrefix::Cast(lib_prefix).name();
+    } else {
+      name = Library::Cast(lib_prefix).name();
+    }
     GrowableHandlePtrArray<const String> strs(zone, 3);
     strs.Add(name);
     strs.Add(Symbols::Dot());
@@ -7104,7 +7114,7 @@
 
 
 bool Function::CheckSourceFingerprint(const char* prefix, int32_t fp) const {
-  if (SourceFingerprint() != fp) {
+  if ((kernel_function() == NULL) && (SourceFingerprint() != fp)) {
     const bool recalculatingFingerprints = false;
     if (recalculatingFingerprints) {
       // This output can be copied into a file, then used with sed
@@ -7495,6 +7505,36 @@
 }
 
 
+RawString* Field::InitializingExpression() const {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const class Script& scr = Script::Handle(zone, Script());
+  ASSERT(!scr.IsNull());
+  const TokenStream& tkns = TokenStream::Handle(zone, scr.tokens());
+  if (tkns.IsNull()) {
+    ASSERT(Dart::snapshot_kind() == Snapshot::kAppNoJIT);
+    return String::null();
+  }
+  TokenStream::Iterator tkit(zone, tkns, token_pos());
+  ASSERT(Token::IsIdentifier(tkit.CurrentTokenKind()));
+#if defined(DEBUG)
+  const String& literal = String::Handle(zone, tkit.CurrentLiteral());
+  ASSERT(literal.raw() == name());
+#endif
+  tkit.Advance();
+  if (tkit.CurrentTokenKind() != Token::kASSIGN) {
+    return String::null();
+  }
+  tkit.Advance();
+  const TokenPosition start_of_expression = tkit.CurrentPosition();
+  while (tkit.CurrentTokenKind() != Token::kSEMICOLON) {
+    tkit.Advance();
+  }
+  const TokenPosition end_of_expression = tkit.CurrentPosition();
+  return scr.GetSnippet(start_of_expression, end_of_expression);
+}
+
+
 RawString* Field::UserVisibleName() const {
   if (FLAG_show_internal_names) {
     return name();
@@ -8932,6 +8972,17 @@
 }
 
 
+RawString* Script::GetSnippet(TokenPosition from, TokenPosition to) const {
+  intptr_t from_line;
+  intptr_t from_column;
+  intptr_t to_line;
+  intptr_t to_column;
+  GetTokenLocation(from, &from_line, &from_column);
+  GetTokenLocation(to, &to_line, &to_column);
+  return GetSnippet(from_line, from_column, to_line, to_column);
+}
+
+
 RawString* Script::GetSnippet(intptr_t from_line,
                               intptr_t from_column,
                               intptr_t to_line,
@@ -10374,7 +10425,7 @@
 }
 
 
-void Library::InitNativeWrappersLibrary(Isolate* isolate) {
+void Library::InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel) {
   static const int kNumNativeWrappersClasses = 4;
   COMPILE_ASSERT((kNumNativeWrappersClasses > 0) &&
                  (kNumNativeWrappersClasses < 10));
@@ -10400,7 +10451,12 @@
     cls_name = Symbols::New(thread, name_buffer);
     Class::NewNativeWrapper(native_flds_lib, cls_name, fld_cnt);
   }
-  native_flds_lib.SetLoaded();
+  // NOTE: If we bootstrap from a Kernel IR file we want to generate the
+  // synthetic constructors for the native wrapper classes.  We leave this up to
+  // the [KernelReader] who will take care of it later.
+  if (!is_kernel) {
+    native_flds_lib.SetLoaded();
+  }
 }
 
 
@@ -15176,8 +15232,8 @@
                               const String& expr,
                               const Array& param_names,
                               const Array& param_values) const {
-  const Function& eval_func =
-      Function::Handle(EvaluateHelper(method_cls, expr, param_names, false));
+  const Function& eval_func = Function::Handle(
+      Function::EvaluateHelper(method_cls, expr, param_names, false));
   const Array& args = Array::Handle(Array::New(1 + param_values.Length()));
   PassiveObject& param = PassiveObject::Handle();
   args.SetAt(0, *this);
@@ -15351,7 +15407,7 @@
 #endif  // DEBUG
 
 
-RawAbstractType* Instance::GetType() const {
+RawAbstractType* Instance::GetType(Heap::Space space) const {
   if (IsNull()) {
     return Type::NullType();
   }
@@ -15371,8 +15427,8 @@
     const Class& scope_cls = Class::Handle(type.type_class());
     ASSERT(scope_cls.NumTypeArguments() > 0);
     TypeArguments& type_arguments = TypeArguments::Handle(GetTypeArguments());
-    type = Type::New(scope_cls, type_arguments, TokenPosition::kNoSource,
-                     Heap::kNew);
+    type =
+        Type::New(scope_cls, type_arguments, TokenPosition::kNoSource, space);
     type.set_signature(signature);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
@@ -15387,7 +15443,7 @@
     if (cls.NumTypeArguments() > 0) {
       type_arguments = GetTypeArguments();
     }
-    type = Type::New(cls, type_arguments, TokenPosition::kNoSource);
+    type = Type::New(cls, type_arguments, TokenPosition::kNoSource, space);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
   }
@@ -16890,6 +16946,7 @@
 RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
                                            TrailPtr trail) const {
   ASSERT(IsFinalized());
+  ASSERT(IsCanonical());
   ASSERT(!IsMalformed());
   if (IsInstantiated()) {
     return raw();
@@ -16961,6 +17018,7 @@
     clone.set_arguments(type_args);
   }
   clone.SetIsFinalized();
+  clone ^= clone.Canonicalize();
   return clone.raw();
 }
 
@@ -17438,9 +17496,12 @@
 
 
 const char* TypeRef::ToCString() const {
+  AbstractType& ref_type = AbstractType::Handle(type());
+  if (ref_type.IsNull()) {
+    return "TypeRef: null";
+  }
   const char* type_cstr =
       String::Handle(Class::Handle(type_class()).Name()).ToCString();
-  AbstractType& ref_type = AbstractType::Handle(type());
   if (ref_type.IsFinalized()) {
     const intptr_t hash = ref_type.Hash();
     return OS::SCreate(Thread::Current()->zone(),
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index dbf901e..837b833 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -525,8 +525,11 @@
   static void InitOnce(Isolate* isolate);
   static void FinalizeVMIsolate(Isolate* isolate);
 
-  // Initialize a new isolate either from source or from a snapshot.
-  static RawError* Init(Isolate* isolate);
+  // Initialize a new isolate either from a Kernel IR, from source, or from a
+  // snapshot.
+  static RawError* Init(Isolate* isolate,
+                        const uint8_t* kernel,
+                        intptr_t kernel_length);
 
   static void MakeUnusedSpaceTraversable(const Object& obj,
                                          intptr_t original_size,
@@ -1030,7 +1033,10 @@
   }
 
   // Asserts that the class of the super type has been resolved.
-  RawClass* SuperClass() const;
+  // |original_classes| only has an effect when reloading. If true and we
+  // are reloading, it will prefer the original classes to the replacement
+  // classes.
+  RawClass* SuperClass(bool original_classes = false) const;
 
   RawType* mixin() const { return raw_ptr()->mixin_; }
   void set_mixin(const Type& value) const;
@@ -1119,7 +1125,10 @@
 
   // Returns an array of all instance fields of this class and its superclasses
   // indexed by offset in words.
-  RawArray* OffsetToFieldMap() const;
+  // |original_classes| only has an effect when reloading. If true and we
+  // are reloading, it will prefer the original classes to the replacement
+  // classes.
+  RawArray* OffsetToFieldMap(bool original_classes = false) const;
 
   // Returns true if non-static fields are defined.
   bool HasInstanceFields() const;
@@ -1503,8 +1512,8 @@
 // to a class after all classes have been loaded and finalized.
 class UnresolvedClass : public Object {
  public:
-  RawLibraryPrefix* library_prefix() const {
-    return raw_ptr()->library_prefix_;
+  RawObject* library_or_library_prefix() const {
+    return raw_ptr()->library_or_library_prefix_;
   }
   RawString* ident() const { return raw_ptr()->ident_; }
   TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
@@ -1515,12 +1524,12 @@
     return RoundedAllocationSize(sizeof(RawUnresolvedClass));
   }
 
-  static RawUnresolvedClass* New(const LibraryPrefix& library_prefix,
+  static RawUnresolvedClass* New(const Object& library_prefix,
                                  const String& ident,
                                  TokenPosition token_pos);
 
  private:
-  void set_library_prefix(const LibraryPrefix& library_prefix) const;
+  void set_library_or_library_prefix(const Object& library_prefix) const;
   void set_ident(const String& ident) const;
   void set_token_pos(TokenPosition token_pos) const;
 
@@ -2741,6 +2750,11 @@
     return RoundedAllocationSize(sizeof(RawFunction));
   }
 
+  static RawFunction* EvaluateHelper(const Class& cls,
+                                     const String& expr,
+                                     const Array& param_names,
+                                     bool is_static);
+
   static RawFunction* New(const String& name,
                           RawFunction::Kind kind,
                           bool is_static,
@@ -3130,6 +3144,8 @@
 
   TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
 
+  RawString* InitializingExpression() const;
+
   bool has_initializer() const {
     return HasInitializerBit::decode(raw_ptr()->kind_bits_);
   }
@@ -3490,6 +3506,7 @@
   RawLibrary* FindLibrary() const;
   RawString* GetLine(intptr_t line_number,
                      Heap::Space space = Heap::kNew) const;
+  RawString* GetSnippet(TokenPosition from, TokenPosition to) const;
   RawString* GetSnippet(intptr_t from_line,
                         intptr_t from_column,
                         intptr_t to_line,
@@ -3766,7 +3783,7 @@
   static RawLibrary* GetLibrary(intptr_t index);
 
   static void InitCoreLibrary(Isolate* isolate);
-  static void InitNativeWrappersLibrary(Isolate* isolate);
+  static void InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel_file);
 
   static RawLibrary* AsyncLibrary();
   static RawLibrary* ConvertLibrary();
@@ -5427,7 +5444,7 @@
     StorePointer(FieldAddr(field), value.raw());
   }
 
-  RawAbstractType* GetType() const;
+  RawAbstractType* GetType(Heap::Space space) const;
 
   virtual RawTypeArguments* GetTypeArguments() const;
   virtual void SetTypeArguments(const TypeArguments& value) const;
@@ -8183,6 +8200,10 @@
   }
 
   intptr_t Length() const {
+    // The map may be uninitialized.
+    if (raw_ptr()->used_data_ == Object::null()) return 0;
+    if (raw_ptr()->deleted_keys_ == Object::null()) return 0;
+
     intptr_t used = Smi::Value(raw_ptr()->used_data_);
     intptr_t deleted = Smi::Value(raw_ptr()->deleted_keys_);
     return (used >> 1) - deleted;
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 66bbaca..c80c80c 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -491,13 +491,14 @@
       : ObjectPointerVisitor(isolate), stream_(stream), count_(0) {}
   virtual void VisitPointers(RawObject** first, RawObject** last) {
     for (RawObject** current = first; current <= last; ++current) {
-      if (!(*current)->IsHeapObject() || (*current == Object::null())) {
-        // Ignore smis and nulls for now.
+      RawObject* object = *current;
+      if (!object->IsHeapObject() || object->IsVMHeapObject()) {
+        // Ignore smis and objects in the VM isolate for now.
         // TODO(koda): To track which field each pointer corresponds to,
         // we'll need to encode which fields were omitted here.
         continue;
       }
-      WritePtr(*current, stream_);
+      WritePtr(object, stream_);
       ++count_;
     }
   }
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index a1318b7..b41ff6c 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -204,18 +204,10 @@
 //   the ordering is always correct (i.e. enum indicies match slots in values
 //   array)
 // 3) An existing enum value is removed.
-//   We leave old enum values that have no mapping to the reloaded class
-//   in the heap. This means that if a programmer does the following:
-//   enum Foo { A, B }; var x = Foo.A;
-//   *reload*
-//   enum Foo { B };
-//   *reload*
-//   enum Foo { A, B }; expect(identical(x, Foo.A));
-//   The program will fail because we were not able to pair Foo.A on the second
-//   reload.
+//   Each enum class has a canonical 'deleted' enum sentinel instance.
+//   When an enum value is deleted, we 'become' all references to the 'deleted'
+//   sentinel value. The index value is -1.
 //
-//   Deleted enum values still in the heap continue to function but their
-//   index field will not be valid.
 void Class::ReplaceEnum(const Class& old_enum) const {
   // We only do this for finalized enum classes.
   ASSERT(is_enum_class());
@@ -237,6 +229,10 @@
   Instance& old_enum_values = Instance::Handle(zone);
   // The E.values array.
   Instance& enum_values = Instance::Handle(zone);
+  // The E._deleted_enum_sentinel instance.
+  Instance& old_deleted_enum_sentinel = Instance::Handle(zone);
+  // The E._deleted_enum_sentinel instance.
+  Instance& deleted_enum_sentinel = Instance::Handle(zone);
   Array& enum_map_storage =
       Array::Handle(zone, HashTables::New<UnorderedHashMap<EnumMapTraits> >(4));
   ASSERT(!enum_map_storage.IsNull());
@@ -259,6 +255,11 @@
         // Non-enum instance.
         continue;
       }
+      if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
+        old_deleted_enum_sentinel = field.StaticValue();
+        // Non-enum instance.
+        continue;
+      }
       old_enum_value = field.StaticValue();
       ASSERT(!old_enum_value.IsNull());
       VTIR_Print("Element %s being added to mapping\n", enum_ident.ToCString());
@@ -288,6 +289,11 @@
         // Non-enum instance.
         continue;
       }
+      if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
+        deleted_enum_sentinel = field.StaticValue();
+        // Non-enum instance.
+        continue;
+      }
       enum_value = field.StaticValue();
       ASSERT(!enum_value.IsNull());
       old_enum_value ^= enum_map.GetOrNull(enum_ident);
@@ -313,17 +319,29 @@
   ASSERT(!enum_values.IsNull());
   reload_context->AddEnumBecomeMapping(old_enum_values, enum_values);
 
-  if (enums_deleted && FLAG_trace_reload_verbose) {
+  // Map the old E._deleted_enum_sentinel to the new E._deleted_enum_sentinel.
+  ASSERT(!old_deleted_enum_sentinel.IsNull());
+  ASSERT(!deleted_enum_sentinel.IsNull());
+  reload_context->AddEnumBecomeMapping(old_deleted_enum_sentinel,
+                                       deleted_enum_sentinel);
+
+  if (enums_deleted) {
+    // Map all deleted enums to the deleted enum senintel value.
     // TODO(johnmccutchan): Add this to the reload 'notices' list.
     VTIR_Print(
-        "The following enum values were deleted and are forever lost in "
-        "the heap:\n");
+        "The following enum values were deleted from %s and will become the "
+        "deleted enum sentinel:\n",
+        old_enum.ToCString());
     UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
     UnorderedHashMap<EnumMapTraits>::Iterator it(&enum_map);
     while (it.MoveNext()) {
       const intptr_t entry = it.Current();
       enum_ident = String::RawCast(enum_map.GetKey(entry));
       ASSERT(!enum_ident.IsNull());
+      old_enum_value ^= enum_map.GetOrNull(enum_ident);
+      VTIR_Print("Element `%s` was deleted\n", enum_ident.ToCString());
+      reload_context->AddEnumBecomeMapping(old_enum_value,
+                                           deleted_enum_sentinel);
     }
     enum_map.Release();
   }
@@ -577,7 +595,8 @@
 bool Class::RequiresInstanceMorphing(const Class& replacement) const {
   // Get the field maps for both classes. These field maps walk the class
   // hierarchy.
-  const Array& fields = Array::Handle(OffsetToFieldMap());
+  const Array& fields =
+      Array::Handle(OffsetToFieldMap(true /* original classes */));
   const Array& replacement_fields =
       Array::Handle(replacement.OffsetToFieldMap());
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 86264b9..4bad386 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -4854,6 +4854,7 @@
   }
   ExpectToken(Token::kRBRACE);
 
+  const Type& array_type = Type::Handle(Z, Type::ArrayType());
   // Add static field 'const List values'.
   Field& values_field = Field::ZoneHandle(Z);
   values_field =
@@ -4861,10 +4862,19 @@
                  /* is_static = */ true,
                  /* is_final = */ true,
                  /* is_const = */ true,
-                 /* is_reflectable = */ true, cls,
-                 Type::Handle(Z, Type::ArrayType()), cls.token_pos());
+                 /* is_reflectable = */ true, cls, array_type, cls.token_pos());
   enum_members.AddField(values_field);
 
+  // Add static field 'const _deleted_enum_sentinel'.
+  Field& deleted_enum_sentinel = Field::ZoneHandle(Z);
+  deleted_enum_sentinel = Field::New(Symbols::_DeletedEnumSentinel(),
+                                     /* is_static = */ true,
+                                     /* is_final = */ true,
+                                     /* is_const = */ true,
+                                     /* is_reflectable = */ false, cls,
+                                     Object::dynamic_type(), cls.token_pos());
+  enum_members.AddField(deleted_enum_sentinel);
+
   // Allocate the immutable array containing the enumeration values.
   // The actual enum instance values will be patched in later.
   const Array& values_array = Array::Handle(Z, Array::New(i, Heap::kOld));
@@ -11871,7 +11881,7 @@
     const String& unresolved_class_name =
         String::Handle(Z, unresolved_class.ident());
     Class& resolved_type_class = Class::Handle(Z);
-    if (unresolved_class.library_prefix() == LibraryPrefix::null()) {
+    if (unresolved_class.library_or_library_prefix() == Object::null()) {
       // First check if the type is a function type parameter.
       if (!innermost_function().IsNull()) {
         // TODO(regis): Shortcut this lookup if no generic functions in scope.
@@ -11921,9 +11931,11 @@
       }
     } else {
       // Resolve class name in the scope of the library prefix.
-      const LibraryPrefix& lib_prefix =
-          LibraryPrefix::Handle(Z, unresolved_class.library_prefix());
-      resolved_type_class = lib_prefix.LookupClass(unresolved_class_name);
+      const Object& prefix =
+          Object::Handle(Z, unresolved_class.library_or_library_prefix());
+      ASSERT(prefix.IsLibraryPrefix());
+      resolved_type_class =
+          LibraryPrefix::Cast(prefix).LookupClass(unresolved_class_name);
     }
     // At this point, we can only have a parameterized_type.
     const Type& parameterized_type = Type::Cast(*type);
@@ -13468,8 +13480,8 @@
         // into throwing a type error.
         const UnresolvedClass& cls =
             UnresolvedClass::Handle(Z, redirect_type.unresolved_class());
-        const LibraryPrefix& prefix =
-            LibraryPrefix::Handle(Z, cls.library_prefix());
+        const LibraryPrefix& prefix = LibraryPrefix::Cast(
+            Object::Handle(Z, cls.library_or_library_prefix()));
         if (!prefix.IsNull() && !prefix.is_loaded() &&
             !FLAG_load_deferred_eagerly) {
           // If the redirection type is unresolved because it refers to
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 71b64583..50900b4 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -706,10 +706,11 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnresolvedClass);
 
   RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->library_prefix_);
+    return reinterpret_cast<RawObject**>(&ptr()->library_or_library_prefix_);
   }
-  RawLibraryPrefix* library_prefix_;  // Library prefix qualifier for the ident.
-  RawString* ident_;                  // Name of the unresolved identifier.
+  RawObject* library_or_library_prefix_;  // Library or library prefix qualifier
+                                          // for the ident.
+  RawString* ident_;                      // Name of the unresolved identifier.
   RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->ident_); }
   TokenPosition token_pos_;
 };
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 1c05a5c..022199e 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2454,11 +2454,6 @@
                    "Cannot reload source when running a precompiled program.");
     return true;
   }
-  if (Dart::snapshot_kind() == Snapshot::kAppWithJIT) {
-    js->PrintError(kFeatureDisabled,
-                   "Cannot reload source when running an app snapshot.");
-    return true;
-  }
   Dart_LibraryTagHandler handler = isolate->library_tag_handler();
   if (handler == NULL) {
     js->PrintError(kFeatureDisabled,
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index a728610..f15485b 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -55,6 +55,8 @@
   V(Close, "close")                                                            \
   V(Values, "values")                                                          \
   V(_EnumNames, "_enum_names")                                                 \
+  V(_DeletedEnumSentinel, "_deleted_enum_sentinel")                            \
+  V(_DeletedEnumPrefix, "Deleted enum value from ")                            \
   V(ExprTemp, ":expr_temp")                                                    \
   V(FinallyRetVal, ":finally_ret_val")                                         \
   V(AnonymousClosure, "<anonymous closure>")                                   \
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart b/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
index c181c6d..18da81d 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
@@ -751,6 +751,14 @@
 
   static String thisScript = computeThisScript();
 
+  /// Returns the base path added to Uri.base to resolve `package:` Uris.
+  ///
+  /// This is used by `Isolate.resolvePackageUri` to load resources. The default
+  /// value is `packages/` but users can override this by using the
+  /// `defaultPackagesBase` hook.
+  static String get packagesBase =>
+      JS('String', r'self.defaultPackagesBase || "packages/"');
+
   /// Associates an ID with a native worker object.
   static final Expando<int> workerIds = new Expando<int>();
 
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
index ed72e6c..637943b 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
@@ -31,9 +31,12 @@
     throw new UnsupportedError("Isolate.packageConfig");
   }
 
+  static Uri _packageBase = Uri.base.resolve(IsolateNatives.packagesBase);
+
   @patch
-  static Future<Uri> resolvePackageUri(Uri packageUri) {
-    throw new UnsupportedError("Isolate.resolvePackageUri");
+  static Future<Uri> resolvePackageUri(Uri packageUri) async {
+    if (packageUri.scheme != 'package') return packageUri;
+    return _packageBase.resolveUri(packageUri.replace(scheme: ''));
   }
 
   @patch
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 2043449..04ed9e6 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -42766,6 +42766,21 @@
       convertDartClosureToJS(callback, 4));
 }
 
+/// Checks whether the given [element] correctly extends from the native class
+/// with the given [baseClassName]. This method will throw if the base class
+/// doesn't match, except when the element extends from `template` and it's base
+/// class is `HTMLUnknownElement`. This exclusion is needed to support extension
+/// of template elements (used heavily in Polymer 1.0) on IE11 when using the
+/// webcomponents-lite.js polyfill.
+void _checkExtendsNativeClassOrTemplate(
+    Element element, String extendsTag, String baseClassName) {
+  if (!JS('bool', '(# instanceof window[#])', element, baseClassName) &&
+      !((extendsTag == 'template' &&
+       JS('bool', '(# instanceof window["HTMLUnknownElement"])', element)))) {
+    throw new UnsupportedError('extendsTag does not match base native class');
+  }
+}
+
 void _registerCustomElement(context, document, String tag, Type type,
     String extendsTagName) {
   // Function follows the same pattern as the following JavaScript code for
@@ -42809,10 +42824,8 @@
           'native class is not HtmlElement');
     }
   } else {
-    if (!JS('bool', '(#.createElement(#) instanceof window[#])',
-        document, extendsTagName, baseClassName)) {
-      throw new UnsupportedError('extendsTag does not match base native class');
-    }
+    var element = document.createElement(extendsTagName);
+    _checkExtendsNativeClassOrTemplate(element, extendsTagName, baseClassName);
   }
 
   var baseConstructor = JS('=Object', '#[#]', context, baseClassName);
@@ -42882,11 +42895,7 @@
       _nativeType = HtmlElement;
     } else {
       var element = document.createElement(extendsTag);
-      if (!JS('bool', '(# instanceof window[#])',
-          element, baseClassName)) {
-        throw new UnsupportedError(
-            'extendsTag does not match base native class');
-      }
+      _checkExtendsNativeClassOrTemplate(element, extendsTag, baseClassName);
       _nativeType = element.runtimeType;
     }
 
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index 92d5699..8b83fc0 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -11,6 +11,7 @@
   external static _localHostname();
   external static _executable();
   external static _resolvedExecutable();
+
   /**
    * Retrieve the entries of the process environment.
    *
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 7edabe0..a5fdba2 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -2835,10 +2835,8 @@
 LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/drawImage-with-valid-image_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/fillText-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/text-globalAlpha_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-attributes-alpha-depth-stencil-antialias-t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: Pass, RuntimeError # Issue 26898
@@ -8058,7 +8056,6 @@
 LayoutTests/fast/xsl/xslt-string-parameters_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xsl/xslt-transform-to-fragment-crash_t01: RuntimeError # Please triage this failure
 LibTest/async/Future/doWhile_A05_t01: Pass, RuntimeError # Sometimes passes on windows 8. Please triage this failure
-LibTest/async/Future/forEach_A04_t02: RuntimeError # Please triage this failure
 LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Stream/timeout_A01_t01: Pass, RuntimeError # Sometimes passes on windows 8. Please triage this failure
 LibTest/async/Stream/timeout_A03_t01: Pass, RuntimeError # Sometimes passes on windows 8. Please triage this failure
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index e3a01cf..8b0d135 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -32,17 +32,13 @@
 Language/Classes/Setters/name_t13: CompileTimeError
 Language/Classes/Setters/name_t14: CompileTimeError
 Language/Classes/Setters/name_t15: CompileTimeError
-Language/Classes/definition_t23: CompileTimeError
+Language/Classes/definition_t23: Crash
 Language/Enums/declaration_equivalent_t01: RuntimeError
 Language/Enums/syntax_t08: MissingCompileTimeError
 Language/Enums/syntax_t09: MissingCompileTimeError
-Language/Expressions/Assignment/indexed_expression_super_t01: RuntimeError
-Language/Expressions/Assignment/indexed_expression_super_t02: RuntimeError
-Language/Expressions/Assignment/indexed_expression_super_t04: RuntimeError
-Language/Expressions/Assignment/super_assignment_failed_t01: RuntimeError
-Language/Expressions/Assignment/super_assignment_failed_t02: RuntimeError
-Language/Expressions/Assignment/super_assignment_t06: RuntimeError
-Language/Expressions/Assignment/super_assignment_value_t02: RuntimeError
+Language/Expressions/Await_Expressions/syntax_t01: RuntimeError
+Language/Expressions/Await_Expressions/syntax_t02: RuntimeError
+Language/Expressions/Await_Expressions/syntax_t10: RuntimeError
 Language/Expressions/Constants/exception_t01: MissingCompileTimeError
 Language/Expressions/Constants/exception_t02: MissingCompileTimeError
 Language/Expressions/Constants/string_length_t01: Crash
@@ -53,6 +49,15 @@
 Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t03: MissingCompileTimeError
 Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t04: MissingCompileTimeError
 Language/Expressions/Function_Invocation/Unqualified_Invocation/static_method_invocation_t02: RuntimeError
+Language/Expressions/Function_Invocation/async_cleanup_t01: RuntimeError
+Language/Expressions/Function_Invocation/async_cleanup_t02: RuntimeError
+Language/Expressions/Function_Invocation/async_cleanup_t04: Crash
+Language/Expressions/Function_Invocation/async_cleanup_t07: Fail
+Language/Expressions/Function_Invocation/async_cleanup_t08: Fail
+Language/Expressions/Function_Invocation/async_generator_invokation_t05: RuntimeError
+Language/Expressions/Function_Invocation/async_generator_invokation_t06: RuntimeError
+Language/Expressions/Function_Invocation/async_generator_invokation_t09: RuntimeError
+Language/Expressions/Function_Invocation/async_invokation_t05: RuntimeError
 Language/Expressions/Identifier_Reference/built_in_identifier_t35: Pass
 Language/Expressions/Identifier_Reference/built_in_identifier_t36: Pass
 Language/Expressions/Identifier_Reference/built_in_identifier_t37: Pass
@@ -84,11 +89,6 @@
 Language/Expressions/Method_Invocation/Ordinary_Invocation/method_lookup_failed_t18: RuntimeError
 Language/Expressions/Method_Invocation/Ordinary_Invocation/syntax_t05: MissingCompileTimeError
 Language/Expressions/Method_Invocation/Ordinary_Invocation/syntax_t10: MissingCompileTimeError
-Language/Expressions/Method_Invocation/Super_Invocation/evaluation_t05: Crash
-Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t01: RuntimeError
-Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t02: RuntimeError
-Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t03: RuntimeError
-Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t04: RuntimeError
 Language/Expressions/Method_Invocation/Super_Invocation/syntax_t05: MissingCompileTimeError
 Language/Expressions/Object_Identity/string_t01: RuntimeError
 Language/Expressions/Property_Extraction/Anonymous_Constructor_Closurization/identical_t01: CompileTimeError
@@ -225,9 +225,6 @@
 Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/setter_closurization_t06: CompileTimeError
 Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/setter_closurization_t07: CompileTimeError
 Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/setter_closurization_t08: CompileTimeError
-Language/Expressions/Property_Extraction/Super_Getter_Access_and_Method_Closurization/no_such_method_t01: RuntimeError
-Language/Expressions/Property_Extraction/Super_Getter_Access_and_Method_Closurization/no_such_method_t02: RuntimeError
-Language/Expressions/Spawning_an_Isolate/new_isolate_t01: Crash
 Language/Expressions/Strings/adjacent_strings_t02: RuntimeError
 Language/Expressions/Type_Test/evaluation_t10: RuntimeError
 Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError
@@ -242,15 +239,14 @@
 Language/Libraries_and_Scripts/Exports/syntax_t05: MissingCompileTimeError
 Language/Libraries_and_Scripts/Exports/syntax_t06: MissingCompileTimeError
 Language/Libraries_and_Scripts/Imports/deferred_import_t01: RuntimeError
-Language/Libraries_and_Scripts/Imports/deferred_import_t02: RuntimeError
+Language/Libraries_and_Scripts/Imports/deferred_import_t02: CompileTimeError
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t01/01: MissingRuntimeError
 Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t02: CompileTimeError
 Language/Libraries_and_Scripts/Imports/invalid_uri_t02: Pass
 Language/Libraries_and_Scripts/Imports/static_type_t01: RuntimeError
-Language/Libraries_and_Scripts/Parts/compilation_t02: Crash
 Language/Libraries_and_Scripts/Parts/syntax_t06: Pass
 Language/Libraries_and_Scripts/Scripts/top_level_main_t01: Crash
 Language/Libraries_and_Scripts/Scripts/top_level_main_t02: Crash
-Language/Libraries_and_Scripts/Scripts/top_level_main_t05: Crash
 Language/Libraries_and_Scripts/definition_syntax_t01: MissingCompileTimeError
 Language/Libraries_and_Scripts/definition_syntax_t03: MissingCompileTimeError
 Language/Libraries_and_Scripts/definition_syntax_t04: MissingCompileTimeError
@@ -300,26 +296,38 @@
 Language/Statements/Rethrow/execution_t04: RuntimeError
 Language/Statements/Switch/syntax_t02: Pass
 Language/Statements/Try/catch_scope_t01: RuntimeError
+Language/Statements/Yield_and_Yield_Each/Yield/execution_async_t04: Fail
+Language/Statements/Yield_and_Yield_Each/Yield/execution_async_t05: Fail
+Language/Statements/Yield_and_Yield_Each/Yield/execution_async_t06: Fail
+Language/Statements/Yield_and_Yield_Each/Yield_Each/execution_async_t01: RuntimeError
 Language/Types/Interface_Types/subtype_t44: RuntimeError
 Language/Types/Static_Types/deferred_type_t01: RuntimeError
 Language/Variables/final_or_static_initialization_t01: MissingCompileTimeError
 Language/Variables/final_or_static_initialization_t02: MissingCompileTimeError
 Language/Variables/final_or_static_initialization_t03: MissingCompileTimeError
+Language/Variables/final_t01/01: MissingRuntimeError
+Language/Variables/final_t02/01: MissingRuntimeError
 Language/Variables/final_t04: MissingCompileTimeError
 Language/Variables/final_t05: MissingCompileTimeError
 Language/Variables/final_t06: MissingCompileTimeError
 Language/Variables/final_t07: MissingCompileTimeError
-LibTest/core/Invocation/isAccessor_A01_t01: RuntimeError
-LibTest/core/Invocation/isAccessor_A01_t02: RuntimeError
-LibTest/core/Invocation/isGetter_A01_t01: RuntimeError
-LibTest/core/Invocation/isGetter_A01_t02: RuntimeError
-LibTest/core/Invocation/isMethod_A01_t01: RuntimeError
-LibTest/core/Invocation/isMethod_A01_t02: RuntimeError
-LibTest/core/Invocation/isSetter_A01_t01: RuntimeError
-LibTest/core/Invocation/isSetter_A01_t02: RuntimeError
-LibTest/core/Invocation/memberName_A01_t01: RuntimeError
-LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError
-LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError
+
+# These tests should throw RuntimeError but they Pass instead.
+Language/Libraries_and_Scripts/Imports/static_type_t01/04: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/06: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/01: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/05: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/03: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/07: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/02: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/04: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/06: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/01: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/05: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/03: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/07: Pass
+Language/Libraries_and_Scripts/Imports/static_type_t01/02: Pass
+
 
 # dartk: precompilation failures
 [ $compiler == dartkp && $runtime == dart_precompiled ]
@@ -623,4 +631,4 @@
 LibTest/core/Invocation/isSetter_A01_t02: Crash
 LibTest/core/Invocation/memberName_A01_t01: RuntimeError
 LibTest/core/Invocation/namedArguments_A01_t01: Crash
-LibTest/core/Invocation/positionalArguments_A01_t01: Crash
+LibTest/core/Invocation/positionalArguments_A01_t01: Crash
\ No newline at end of file
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 24d95eb..ac487d8a 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -220,9 +220,12 @@
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Pass, Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Pass, Timeout
+LibTest/core/List/List_class_A01_t01: Pass, Timeout
 LibTest/core/List/List_class_A01_t02: Pass, Timeout
 LibTest/core/Map/Map_class_A01_t04: Pass, Timeout
 LibTest/core/Uri/Uri_A06_t03: Pass, Timeout
 LibTest/core/Uri/encodeQueryComponent_A01_t02: Pass, Timeout
 LibTest/isolate/Isolate/spawn_A01_t04: Pass, Timeout
+LibTest/isolate/Isolate/spawnUri_A01_t06: Pass, Fail # Timing dependent
+LibTest/isolate/Isolate/spawnUri_A01_t07: Pass, Fail # Timing dependent
 LibTest/isolate/ReceivePort/take_A01_t02: Crash, Fail # Issue 27773
diff --git a/tests/compiler/dart2js/kernel/assert_test.dart b/tests/compiler/dart2js/kernel/assert_test.dart
index 1495ff4..48c8997 100644
--- a/tests/compiler/dart2js/kernel/assert_test.dart
+++ b/tests/compiler/dart2js/kernel/assert_test.dart
@@ -24,9 +24,6 @@
   assert(foo(), "foo failed");
 }''';
     return check(code,
-        // disable type inference because kernel doesn't yet support
-        // checked mode type checks
-        disableTypeInference: false,
         extraOptions: const <String>[
           Flags.enableCheckedMode,
           Flags.enableAssertMessage,
diff --git a/tests/compiler/dart2js/kernel/constructors_test.dart b/tests/compiler/dart2js/kernel/constructors_test.dart
new file mode 100644
index 0000000..1d30c1c
--- /dev/null
+++ b/tests/compiler/dart2js/kernel/constructors_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:compiler/src/compiler.dart' show Compiler;
+import 'package:compiler/src/elements/elements.dart';
+import 'package:test/test.dart';
+
+import 'helper.dart' show check;
+
+main() {
+  test('simple default constructor', () {
+    String code = '''
+class A {
+}
+
+main() {
+  var a = new A();
+  return a;
+}''';
+    return check(code, lookup: defaultConstructorFor('A'));
+  });
+
+  test('simple default constructor with field', () {
+    String code = '''
+class A {
+  int x = 1;
+}
+
+main() {
+  var a = new A();
+  return a;
+}''';
+    return check(code, lookup: defaultConstructorFor('A'));
+  });
+}
+
+defaultConstructorFor(String className) => (Compiler compiler) {
+      ClassElement clazz = compiler.mainApp.find(className);
+      return clazz.lookupDefaultConstructor();
+    };
diff --git a/tests/compiler/dart2js/kernel/helper.dart b/tests/compiler/dart2js/kernel/helper.dart
index d7d4b11..cbb1638b 100644
--- a/tests/compiler/dart2js/kernel/helper.dart
+++ b/tests/compiler/dart2js/kernel/helper.dart
@@ -14,7 +14,7 @@
 import '../memory_compiler.dart';
 
 Future<String> compile(String code,
-    {String entry: 'main',
+    {dynamic lookup: 'main',
     bool useKernel: true,
     bool disableTypeInference: true,
     List<String> extraOptions: const <String>[]}) async {
@@ -25,29 +25,41 @@
   if (useKernel) options.add(Flags.useKernel);
   options.addAll(extraOptions);
 
-  if (entry != 'main' && !code.contains('main')) {
-    code = "$code\n\nmain() => $entry;";
+  if (lookup is String && lookup != 'main' && !code.contains('main')) {
+    code = "$code\n\nmain() => $lookup;";
   }
   CompilationResult result = await runCompiler(
       memorySourceFiles: {'main.dart': code}, options: options);
   expect(result.isSuccess, isTrue);
   Compiler compiler = result.compiler;
-  Element element = compiler.mainApp.find(entry);
+  Element element;
+  if (lookup is String) {
+    element = compiler.mainApp.find(lookup);
+  } else {
+    element = lookup(compiler);
+  }
   js.JavaScriptBackend backend = compiler.backend;
   return backend.getGeneratedCode(element);
 }
 
+/// Checks that the given Dart [code] compiles to the same JS in kernel and
+/// normal mode.
+///
+/// The function to check at the end is given by [lookup]. If [lookup] is a
+/// String, then the generated code for a top-level element named [lookup] is
+/// checked. Otherwise, [lookup] is a function that takes a [Compiler] and
+/// returns an [Element], and the returned [Element] is checked.
 Future check(String code,
-    {String entry: 'main',
+    {dynamic lookup: 'main',
     bool disableTypeInference: true,
     List<String> extraOptions: const <String>[]}) async {
   var original = await compile(code,
-      entry: entry,
+      lookup: lookup,
       useKernel: false,
       disableTypeInference: disableTypeInference,
       extraOptions: extraOptions);
   var kernel = await compile(code,
-      entry: entry,
+      lookup: lookup,
       useKernel: true,
       disableTypeInference: disableTypeInference,
       extraOptions: extraOptions);
diff --git a/tests/compiler/dart2js/kernel/simple_function_test.dart b/tests/compiler/dart2js/kernel/simple_function_test.dart
index 6539134..d58ca33 100644
--- a/tests/compiler/dart2js/kernel/simple_function_test.dart
+++ b/tests/compiler/dart2js/kernel/simple_function_test.dart
@@ -42,6 +42,6 @@
       main() {
         foo(1);
       }''';
-    return check(code, entry: 'foo');
+    return check(code, lookup: 'foo');
   });
 }
diff --git a/tests/compiler/dart2js_extra/inference_super_set_call_test.dart b/tests/compiler/dart2js_extra/inference_super_set_call_test.dart
new file mode 100644
index 0000000..5a56023
--- /dev/null
+++ b/tests/compiler/dart2js_extra/inference_super_set_call_test.dart
@@ -0,0 +1,46 @@
+// 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 for dart2js: we incorrectly modeled `super.x = rhs` as a
+// call and not an assignment, so the type of the expression was incorrectly
+// assumed to be the return type of the setter rather than the type of the rhs.
+import 'package:expect/expect.dart';
+
+abstract class A {
+  set x(v) {}
+  set z(v) {}
+  set y(v) { return 'hi';}
+}
+
+class S extends A {
+  var _x;      // was bad: inferred as null, than [null | int]
+  var _y = ''; // was bad: inferred as String, rather than [String | int]
+  var _z;      // was ok : inferred as [null | int]
+
+  set x(v) {
+    _x = super.x = v;
+  }
+
+  set z(v) {
+    super.z = v;
+    _z = v;
+  }
+
+  set y(v) {
+    _y = super.y = v;
+  }
+
+  get isXNull => _x == null;
+  get isZNull => _z == null;
+}
+
+main() {
+  var s = new S()
+    ..x = 2
+    ..y = 2
+    ..z = 2;
+  Expect.equals(false, s.isXNull);      // was incorrectly optimized to 'true'
+  Expect.equals(false, s._y is String); // was incorrectly optimized to 'true'
+  Expect.equals(false, s.isZNull);      // prints false
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 24a5cd6..1436f88 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -207,3 +207,7 @@
 
 [ $arch == simdbc || $arch == simdbc64 ]
 regexp/stack-overflow_test: RuntimeError, OK # Smaller limit with irregex interpreter
+
+[ $hot_reload || $hot_reload_rollback ]
+big_integer_parsed_mul_div_vm_test: Pass, Slow # Slow.
+
diff --git a/tests/html/custom/document_register_template_test.dart b/tests/html/custom/document_register_template_test.dart
new file mode 100644
index 0000000..11b0b8d
--- /dev/null
+++ b/tests/html/custom/document_register_template_test.dart
@@ -0,0 +1,24 @@
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'dart:html';
+import '../utils.dart';
+
+main() {
+  useHtmlConfiguration();
+
+  setUp(() => customElementsReady);
+
+  test('can register custom template with webcomponents-lite polyfill', () {
+    document.registerElement('my-element', MyElement, extendsTag: 'template');
+    var e = new Element.tag('template', 'my-element');
+    document.body.append(e);
+    expect(e is TemplateElement, isTrue);
+    expect(e.method(), 'value');
+  });
+}
+
+
+class MyElement extends TemplateElement {
+  MyElement.created() : super.created();
+  method() => 'value';
+}
diff --git a/tests/html/custom/document_register_template_test.html b/tests/html/custom/document_register_template_test.html
new file mode 100644
index 0000000..26f59bf
--- /dev/null
+++ b/tests/html/custom/document_register_template_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> document_register_basic_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents-lite.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running document_register_basic_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/isolate/browser/package_resolve_browser_hook2_test.dart b/tests/isolate/browser/package_resolve_browser_hook2_test.dart
new file mode 100644
index 0000000..7768338
--- /dev/null
+++ b/tests/isolate/browser/package_resolve_browser_hook2_test.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:js';
+import 'dart:isolate';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+main() async {
+  useHtmlConfiguration();
+
+  setUp(() {
+      context['defaultPackagesBase'] = 'path1/';
+  });
+
+  test('hook overrides package-uri resolution', () async {
+    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
+    expect(uri, Uri.base.resolve('path1/foo/bar.txt'));
+  });
+
+  test('hook is read once, on the first use of resolvePackageUri', () async {
+    await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
+    context['defaultPackagesBase'] = 'path2/';
+    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
+    expect(uri, Uri.base.resolve('path1/foo/bar.txt'));
+  });
+}
diff --git a/tests/isolate/browser/package_resolve_browser_hook_test.dart b/tests/isolate/browser/package_resolve_browser_hook_test.dart
new file mode 100644
index 0000000..5c90474
--- /dev/null
+++ b/tests/isolate/browser/package_resolve_browser_hook_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 'dart:isolate';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+main() async {
+  useHtmlConfiguration();
+
+  test('defaultPackagesBase hook overrides package-uri resolution', () async {
+    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
+    expect(uri, Uri.base.resolve('path/set/from/hook/foo/bar.txt'));
+  });
+}
diff --git a/tests/isolate/browser/package_resolve_browser_hook_test.html b/tests/isolate/browser/package_resolve_browser_hook_test.html
new file mode 100644
index 0000000..a3b67b6
--- /dev/null
+++ b/tests/isolate/browser/package_resolve_browser_hook_test.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> mirrors_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running mirrors_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  <script>
+  // Dart2js exposes this hook to override the default base path where resource
+  // package uris are resolved from.
+  defaultPackagesBase = 'path/set/from/hook/';
+  </script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/isolate/browser/package_resolve_browser_test.dart b/tests/isolate/browser/package_resolve_browser_test.dart
new file mode 100644
index 0000000..49ced93
--- /dev/null
+++ b/tests/isolate/browser/package_resolve_browser_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 'dart:isolate';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+main() {
+  useHtmlConfiguration();
+
+  test('by default package-uri resolve under base/packages/', () async {
+    var uri = await Isolate.resolvePackageUri(Uri.parse('package:foo/bar.txt'));
+    expect(uri, Uri.base.resolve('packages/foo/bar.txt'));
+  });
+}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index ffba137..1c39f36 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -152,7 +152,7 @@
 simple_message_test/none: RuntimeError, OK  # Uses Isolate.spawn.
 start_paused_test: RuntimeError, OK  # Uses Isolate.spawn.
 message3_test/int32x4: RuntimeError, OK  # Uses Isolate.spawn.
-
+browser/package_*: Skip # Issue 25594 (missing implementation in Dartium).
 
 [ $compiler == dart2analyzer ]
 browser/typed_data_message_test: StaticWarning
diff --git a/tests/isolate/spawn_uri_child_isolate.dart b/tests/isolate/spawn_uri_child_isolate.dart
index 57f1dde..81f40f9 100644
--- a/tests/isolate/spawn_uri_child_isolate.dart
+++ b/tests/isolate/spawn_uri_child_isolate.dart
@@ -4,9 +4,8 @@
 
 // Child isolate code to be spawned from a URI to this file.
 library SpawnUriChildIsolate;
-import 'dart:isolate';
 
-void main(List<String> args, SendPort replyTo) {
+void main(List<String> args, replyTo) {
   var data = args[0];
   replyTo.send('re: $data');
 }
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 1da0824..5891891 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -270,7 +270,7 @@
 [ $compiler == dart2js && ($runtime == chrome || $runtime == ff) && $system == windows ]
 string_literals_test: RuntimeError # Issue 27533
 
-[ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim)]
+[ $compiler == dart2js && $runtime == safarimobilesim ]
 # Safari codegen bug, fixed on some versions of Safari 7.1 (Version 7.1 (9537.85.10.17.1))
 call_through_getter_test: Fail, OK
 
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index 3571c0c..1346de2 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -17,14 +17,16 @@
 accessor_conflict_import_prefixed_test: RuntimeError
 accessor_conflict_import_test: RuntimeError
 assertion_test: RuntimeError
+async_await_test: Crash
 async_break_in_finally_test: RuntimeError
 async_control_structures_test: RuntimeError
 async_star_cancel_and_throw_in_finally_test: RuntimeError
 async_star_cancel_while_paused_test: RuntimeError
-async_star_regression_fisk_test: Crash
+async_star_pause_test: RuntimeError
+async_star_regression_fisk_test: RuntimeError
 async_star_stream_take_test: Timeout
 async_star_take_reyield_test: Timeout
-async_star_test: Crash
+async_star_test: Timeout
 async_throw_in_catch_test/forceAwait: RuntimeError
 async_throw_in_catch_test/none: RuntimeError
 asyncstar_throw_in_catch_test: Timeout
@@ -46,6 +48,8 @@
 compile_time_constant_k_test/03: RuntimeError
 compile_time_constant_o_test/01: RuntimeError
 compile_time_constant_o_test/02: RuntimeError
+conditional_import_string_test: CompileTimeError
+conditional_import_test: CompileTimeError
 config_import_test: RuntimeError
 conflicting_type_variable_and_setter_test: CompileTimeError
 const_dynamic_type_literal_test/02: RuntimeError
@@ -64,12 +68,13 @@
 constructor_duplicate_final_test/02: MissingRuntimeError
 constructor_duplicate_final_test/03: MissingCompileTimeError
 constructor_named_arguments_test/01: Crash
-cyclic_type2_test: CompileTimeError
+custom_await_stack_trace_test: RuntimeError
+cyclic_type2_test: Crash
 cyclic_type_test/00: RuntimeError
 cyclic_type_test/01: RuntimeError
-cyclic_type_test/02: CompileTimeError
+cyclic_type_test/02: Crash
 cyclic_type_test/03: RuntimeError
-cyclic_type_test/04: CompileTimeError
+cyclic_type_test/04: Crash
 cyclic_type_variable_test/01: Crash
 cyclic_type_variable_test/02: Crash
 cyclic_type_variable_test/03: Crash
@@ -149,7 +154,6 @@
 f_bounded_equality_test: RuntimeError
 field_initialization_order_test: RuntimeError
 final_field_initialization_order_test: RuntimeError
-final_super_field_set_test/01: RuntimeError
 final_syntax_test/01: MissingCompileTimeError
 final_syntax_test/02: MissingCompileTimeError
 final_syntax_test/03: MissingCompileTimeError
@@ -165,7 +169,6 @@
 fixed_type_variable_test/06: RuntimeError
 for2_test: RuntimeError
 for_variable_capture_test: RuntimeError
-forwarding_factory_constructor_default_values_test: RuntimeError
 function_subtype2_test: RuntimeError
 function_subtype_bound_closure3_test: RuntimeError
 function_subtype_bound_closure4_test: RuntimeError
@@ -187,6 +190,7 @@
 generic_inheritance_test: RuntimeError
 generic_local_functions_test: CompileTimeError
 generic_methods_function_type_test: CompileTimeError
+generic_methods_generic_function_parameter_test: CompileTimeError
 generic_methods_new_test: CompileTimeError
 generic_methods_test: CompileTimeError
 generic_methods_type_expression_test: CompileTimeError
@@ -198,26 +202,25 @@
 initializing_formal_access_test: CompileTimeError
 initializing_formal_capture_test: CompileTimeError
 initializing_formal_final_test: CompileTimeError
+initializing_formal_promotion_test: CompileTimeError
 initializing_formal_type_test: CompileTimeError
 instance_creation_in_function_annotation_test: RuntimeError
-invocation_mirror_test: RuntimeError
 is_not_class2_test: RuntimeError
 issue13474_test: RuntimeError
-issue23244_test: Crash
 issue_1751477_test: RuntimeError
-least_upper_bound_expansive_test/01: CompileTimeError
-least_upper_bound_expansive_test/02: CompileTimeError
-least_upper_bound_expansive_test/03: CompileTimeError
-least_upper_bound_expansive_test/04: CompileTimeError
-least_upper_bound_expansive_test/05: CompileTimeError
-least_upper_bound_expansive_test/06: CompileTimeError
-least_upper_bound_expansive_test/07: CompileTimeError
-least_upper_bound_expansive_test/08: CompileTimeError
-least_upper_bound_expansive_test/09: CompileTimeError
-least_upper_bound_expansive_test/10: CompileTimeError
-least_upper_bound_expansive_test/11: CompileTimeError
-least_upper_bound_expansive_test/12: CompileTimeError
-least_upper_bound_expansive_test/none: CompileTimeError
+least_upper_bound_expansive_test/01: Crash
+least_upper_bound_expansive_test/02: Crash
+least_upper_bound_expansive_test/03: Crash
+least_upper_bound_expansive_test/04: Crash
+least_upper_bound_expansive_test/05: Crash
+least_upper_bound_expansive_test/06: Crash
+least_upper_bound_expansive_test/07: Crash
+least_upper_bound_expansive_test/08: Crash
+least_upper_bound_expansive_test/09: Crash
+least_upper_bound_expansive_test/10: Crash
+least_upper_bound_expansive_test/11: Crash
+least_upper_bound_expansive_test/12: Crash
+least_upper_bound_expansive_test/none: Crash
 library_env_test/has_html_support: RuntimeError
 library_env_test/has_no_io_support: RuntimeError
 library_env_test/has_no_mirror_support: RuntimeError
@@ -295,23 +298,22 @@
 named_parameters_type_test/03: MissingRuntimeError
 no_main_test/01: Crash
 not_enough_positional_arguments_test/01: CompileTimeError
-not_enough_positional_arguments_test/02: Crash
-not_enough_positional_arguments_test/05: Crash
+not_enough_positional_arguments_test/02: MissingRuntimeError
+not_enough_positional_arguments_test/05: MissingRuntimeError
 null_test/none: RuntimeError
 number_identifier_test/05: RuntimeError
 positional_parameters_type_test/01: MissingRuntimeError
 positional_parameters_type_test/02: MissingRuntimeError
 prefix10_negative_test: Fail
-prefix16_test: RuntimeError
 prefix21_test: RuntimeError
 redirecting_constructor_initializer_test: RuntimeError
-redirecting_factory_default_values_test/none: RuntimeError
 redirecting_factory_reflection_test: RuntimeError
 regress_18713_test: RuntimeError
 regress_22443_test: RuntimeError
 regress_22700_test: RuntimeError
 regress_23408_test: RuntimeError
 regress_27164_test: CompileTimeError
+regress_27617_test/1: MissingCompileTimeError
 regress_r24720_test: RuntimeError
 reify_typevar_static_test/00: MissingCompileTimeError
 reify_typevar_test: RuntimeError
@@ -320,26 +322,12 @@
 setter_no_getter_call_test/none: RuntimeError
 static_setter_get_test/01: RuntimeError
 super_call3_test/01: Crash
-super_call4_test: RuntimeError
-super_getter_setter_test: RuntimeError
-super_no_such_method1_test/01: RuntimeError
-super_no_such_method2_test/01: RuntimeError
-super_no_such_method3_test/01: RuntimeError
-super_no_such_method4_test/01: RuntimeError
-super_no_such_method5_test/01: RuntimeError
-super_operator_index3_test: RuntimeError
-super_operator_index4_test: RuntimeError
-super_operator_index5_test: RuntimeError
-super_operator_index6_test: RuntimeError
-super_operator_index7_test: RuntimeError
-super_operator_index8_test: RuntimeError
 super_test: RuntimeError
 switch7_negative_test: Fail
 switch_try_catch_test: RuntimeError
 sync_generator3_test/test2: RuntimeError
 tearoff_basic_test: CompileTimeError
 tearoff_constructor_basic_test: CompileTimeError
-throw8_test: RuntimeError
 try_catch_on_syntax_test/10: MissingRuntimeError
 try_catch_on_syntax_test/11: MissingRuntimeError
 try_finally_regress_25654_test: RuntimeError
@@ -482,8 +470,6 @@
 enum_test: RuntimeError
 evaluation_redirecting_constructor_test: RuntimeError
 example_constructor_test: RuntimeError
-execute_finally8_test: RuntimeError
-execute_finally9_test: RuntimeError
 export_double_same_main_test: Crash
 export_main_test: Crash
 external_test/10: MissingRuntimeError
@@ -711,4 +697,4 @@
 vm/debug_break_enabled_vm_test/none: CompileTimeError
 vm/reflect_core_vm_test: CompileTimeError
 vm/type_cast_vm_test: RuntimeError
-vm/type_vm_test: RuntimeError
+vm/type_vm_test: RuntimeError
\ No newline at end of file
diff --git a/tests/language/vm/optimized_unique_selector_test.dart b/tests/language/vm/optimized_unique_selector_test.dart
new file mode 100644
index 0000000..bf0b5e4d
--- /dev/null
+++ b/tests/language/vm/optimized_unique_selector_test.dart
@@ -0,0 +1,42 @@
+// 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 "package:expect/expect.dart";
+
+class A {
+  _uniqueSelector() { }
+  final uniqueField = 10;
+}
+
+test1(obj) {
+  var res = 0;
+  for (var i = 0; i < 2; i++) {
+    obj._uniqueSelector();
+    res += obj.uniqueField;  // This load must not be hoisted out of the loop.
+  }
+  return res;
+}
+
+test2(obj) {
+  final objAlias = obj;
+  closure() => objAlias;
+  var res = 0;
+  for (var i = 0; i < 2; i++) {
+    obj._uniqueSelector();
+    res += objAlias.uniqueField;  // This load must not be hoisted out of the loop.
+  }
+  return res;
+}
+
+var foofoo_ = test1;
+
+main () {
+  Expect.equals(20, foofoo_(new A()));
+  Expect.throws(() => foofoo_(0));
+
+  foofoo_ = test2;
+
+  Expect.equals(20, foofoo_(new A()));
+  Expect.throws(() => foofoo_(0));
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8f43474..9bcdd8e 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -417,3 +417,4 @@
 mirrors/generic_bounded_test/02: Fail # Type equality - Issue 26869
 mirrors/typedef_reflected_type_test/01: Fail # Type equality - Issue 26869
 mirrors/generic_bounded_by_type_parameter_test/02: Fail # Type equality - Issue 26869
+async/timer_regress22626_test: Pass, RuntimeError # Timing dependent.
diff --git a/tests/standalone/io/file_blocking_lock_script.dart b/tests/standalone/io/file_blocking_lock_script.dart
index 5c955c4..9ba2feb 100644
--- a/tests/standalone/io/file_blocking_lock_script.dart
+++ b/tests/standalone/io/file_blocking_lock_script.dart
@@ -11,32 +11,15 @@
   var raf = await file.open(mode: APPEND);
   await raf.setPosition(0);
   int nextToWrite = 1;
-  while (nextToWrite <= len) {
-    await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, len);
-
-    int at;
-    int p;
-    while (true) {
-      p = await raf.position();
-      at = await raf.readByte();
-      if (at == 0 || at == -1) break;
-      nextToWrite++;
-    }
-    await raf.setPosition(p);
-    await raf.writeByte(nextToWrite);
-    await raf.flush();
-    nextToWrite++;
-    await raf.unlock(0, len);
-  }
-
   await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, len);
-  await raf.setPosition(0);
-  for (int i = 1; i <= len; i++) {
-    if ((await raf.readByte()) != i) {
-      await raf.unlock(0, len);
-      await raf.close();
-      return 1;
-    }
+
+  // Make sure the peer fails a non-blocking lock at some point.
+  await new Future.delayed(const Duration(seconds: 1));
+
+  int p = 0;
+  while (p < len) {
+    await raf.writeByte(1);
+    p++;
   }
   await raf.unlock(0, len);
   await raf.close();
diff --git a/tests/standalone/io/file_blocking_lock_test.dart b/tests/standalone/io/file_blocking_lock_test.dart
index aa44bd1..9f665b6 100644
--- a/tests/standalone/io/file_blocking_lock_test.dart
+++ b/tests/standalone/io/file_blocking_lock_test.dart
@@ -39,69 +39,55 @@
   });
 }
 
+const int peerTimeoutMilliseconds = 10000;
+
+Future<bool> waitForPeer(RandomAccessFile raf, int length) async {
+  Stopwatch s = new Stopwatch();
+  s.start();
+  while (true) {
+    await raf.unlock(0, length);
+    if (s.elapsedMilliseconds > peerTimeoutMilliseconds) {
+      s.stop();
+      return false;
+    }
+    try {
+      await raf.lock(FileLock.EXCLUSIVE, 0, length);
+    } on dynamic {
+      await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, length);
+      break;
+    }
+  }
+  s.stop();
+  return true;
+}
+
 testLockWholeFile() async {
   const int length = 25;
   Directory directory = await Directory.systemTemp.createTemp('dart_file_lock');
   File file = new File(join(directory.path, "file"));
   await file.writeAsBytes(new List.filled(length, 0));
   var raf = await file.open(mode: APPEND);
-  await raf.setPosition(0);
   await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, length);
   Process peer = await runPeer(file.path, length, FileLock.BLOCKING_EXCLUSIVE);
 
-  int nextToWrite = 1;
-  int at = 0;
-  List iWrote = new List.filled(length, 0);
-  bool nonBlockingFailed = false;
-  while (nextToWrite <= length) {
-    int p = await raf.position();
-    await raf.writeByte(nextToWrite);
-    await raf.flush();
-    // Record which bytes this process wrote so that we can check that the
-    // other process was able to take the lock and write some bytes.
-    iWrote[nextToWrite-1] = nextToWrite;
-    nextToWrite++;
-    // Let the other process get the lock at least once by spinning until the
-    // non-blocking lock fails.
-    while (!nonBlockingFailed) {
-      await raf.unlock(0, length);
-      try {
-        await raf.lock(FileLock.EXCLUSIVE, 0, length);
-      } catch(e) {
-        // Check that at some point the non-blocking lock fails.
-        nonBlockingFailed = true;
-        await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, length);
-      }
-    }
-    while (true) {
-      p = await raf.position();
-      at = await raf.readByte();
-      if (at == 0 || at == -1) break;
-      nextToWrite++;
-    }
-    await raf.setPosition(p);
-  }
+  // Waits for the peer to take the lock, then takes the lock.
+  Expect.isTrue(await waitForPeer(raf, length));
 
+  // Check that the peer wrote to the file.
+  int p = 0;
   await raf.setPosition(0);
-  for (int i = 1; i <= length; i++) {
-    Expect.equals(i, await raf.readByte());
+  while (p < length) {
+    int at = await raf.readByte();
+    Expect.equals(1, at);
+    p++;
   }
   await raf.unlock(0, length);
 
-  bool wroteAll = true;
-  for (int i = 0; i < length; i++) {
-    // If there's a 0 entry, this process didn't write all bytes.
-    wroteAll = wroteAll && (iWrote[i] == 0);
-  }
-  Expect.equals(false, wroteAll);
-
-  Expect.equals(true, nonBlockingFailed);
-
-  await peer.exitCode.then((v) async {
-    Expect.equals(0, v);
-    await raf.close();
-    await directory.delete(recursive: true);
-  });
+  // Check that the peer exited successfully.
+  int v = await peer.exitCode;
+  Expect.equals(0, v);
+  await raf.close();
+  await directory.delete(recursive: true);
 }
 
 main() async {
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 866135b..fb7510f 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -309,12 +309,16 @@
 # SIMDBC interpreter doesn't support --no_lazy_dispatchers
 no_lazy_dispatchers_test: SkipByDesign
 
-[ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
+[ $system == android ]
 # Issue 26376
+io/platform_resolved_executable_test: RuntimeError
+io/process_path_test: RuntimeError
+io/file_test: RuntimeError
+io/process_path_environment_test: RuntimeError
 io/file_system_watcher_test: RuntimeError
 io/resolve_symbolic_links_test: RuntimeError
 io/file_stat_test: RuntimeError
-# Issue #27638
+# Issue 27638
 io/raw_datagram_socket_test: RuntimeError
 io/http_proxy_advanced_test: RuntimeError
 io/regress_21160_test: RuntimeError
@@ -343,6 +347,9 @@
 [ $hot_reload || $hot_reload_rollback ]
 deferred_transitive_import_error_test: Crash # Uses deferred imports.
 package/*: SkipByDesign # Launches VMs in interesting ways.
+io/raw_datagram_read_all_test: Pass, Fail # Timing dependent.
+io/test_runner_test: Pass, Slow # Slow.
+io/skipping_dart2js_compilations_test: Pass, Slow # Slow.
 
 [ $builder_tag == no_ipv6 ]
 io/http_bind_test: Skip
diff --git a/tools/VERSION b/tools/VERSION
index 4b02ee1e..da4c303 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,5 +28,5 @@
 MAJOR 1
 MINOR 21
 PATCH 0
-PRERELEASE 6
+PRERELEASE 7
 PRERELEASE_PATCH 0
diff --git a/tools/build.py b/tools/build.py
index 0858c27..4f5d2e1 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -408,7 +408,6 @@
     '-m', mode,
     '-a', arch,
     '--os', gn_os,
-    '--check',
     '-v',
   ]
   process = subprocess.Popen(gn_command)
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart
index 62c120d..e82d3fd 100644
--- a/tools/dom/src/dart2js_CustomElementSupport.dart
+++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -47,6 +47,21 @@
       convertDartClosureToJS(callback, 4));
 }
 
+/// Checks whether the given [element] correctly extends from the native class
+/// with the given [baseClassName]. This method will throw if the base class
+/// doesn't match, except when the element extends from `template` and it's base
+/// class is `HTMLUnknownElement`. This exclusion is needed to support extension
+/// of template elements (used heavily in Polymer 1.0) on IE11 when using the
+/// webcomponents-lite.js polyfill.
+void _checkExtendsNativeClassOrTemplate(
+    Element element, String extendsTag, String baseClassName) {
+  if (!JS('bool', '(# instanceof window[#])', element, baseClassName) &&
+      !((extendsTag == 'template' &&
+       JS('bool', '(# instanceof window["HTMLUnknownElement"])', element)))) {
+    throw new UnsupportedError('extendsTag does not match base native class');
+  }
+}
+
 void _registerCustomElement(context, document, String tag, Type type,
     String extendsTagName) {
   // Function follows the same pattern as the following JavaScript code for
@@ -90,10 +105,8 @@
           'native class is not HtmlElement');
     }
   } else {
-    if (!JS('bool', '(#.createElement(#) instanceof window[#])',
-        document, extendsTagName, baseClassName)) {
-      throw new UnsupportedError('extendsTag does not match base native class');
-    }
+    var element = document.createElement(extendsTagName);
+    _checkExtendsNativeClassOrTemplate(element, extendsTagName, baseClassName);
   }
 
   var baseConstructor = JS('=Object', '#[#]', context, baseClassName);
@@ -163,11 +176,7 @@
       _nativeType = HtmlElement;
     } else {
       var element = document.createElement(extendsTag);
-      if (!JS('bool', '(# instanceof window[#])',
-          element, baseClassName)) {
-        throw new UnsupportedError(
-            'extendsTag does not match base native class');
-      }
+      _checkExtendsNativeClassOrTemplate(element, extendsTag, baseClassName);
       _nativeType = element.runtimeType;
     }
 
diff --git a/tools/generate_buildfiles.py b/tools/generate_buildfiles.py
index 391a15a..9aa26e7 100644
--- a/tools/generate_buildfiles.py
+++ b/tools/generate_buildfiles.py
@@ -12,12 +12,17 @@
 SCRIPT_DIR = os.path.dirname(sys.argv[0])
 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
 DART_USE_GN = "DART_USE_GN"
+DART_DISABLE_BUILDFILES = "DART_DISABLE_BUILDFILES"
 
 
 def use_gn():
   return DART_USE_GN in os.environ
 
 
+def disable_buildfiles():
+  return DART_DISABLE_BUILDFILES in os.environ
+
+
 def execute(args):
   process = subprocess.Popen(args, cwd=DART_ROOT)
   process.wait()
@@ -68,6 +73,9 @@
 
 
 def main(argv):
+  # Check the environment and become a no-op if directed.
+  if disable_buildfiles():
+    return 0
   options = parse_args(argv)
   if options.gn:
     return run_gn()
diff --git a/tools/get_archive.py b/tools/get_archive.py
index 7517f54..fe1ac51 100755
--- a/tools/get_archive.py
+++ b/tools/get_archive.py
@@ -114,7 +114,7 @@
         None, we return the latest revision. If the revision number is specified
         but unavailable, find the nearest older revision and use that instead.
   """
-  osdict = {'Darwin':'mac', 'Linux':'lucid64', 'Windows':'win'}
+  osdict = {'Darwin':'mac-x64', 'Linux':'linux-x64', 'Windows':'win-ia32'}
 
   def FindPermanentUrl(out, osname, the_revision_num):
     output_lines = out.split()
@@ -318,7 +318,9 @@
   # Issue 13399 Quick fix, update with channel support.
   bot = 'inc-be'
   if args.debug:
-    bot = 'debug-be'
+    print >>sys.stderr, (
+      'Debug versions of Dartium and content_shell not available')
+    return 1
 
   if positional[0] == 'dartium':
     GetDartiumRevision('Dartium', bot, DARTIUM_DIR, DARTIUM_VERSION,
diff --git a/tools/gn.py b/tools/gn.py
index 2ff3bc2..304bdaa 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -112,7 +112,8 @@
   has_clang = (host_os != 'win'
                and args.os not in ['android']
                and not (gn_args['target_os'] == 'linux' and
-                        gn_args['host_cpu'] == 'x86')
+                        gn_args['host_cpu'] == 'x86' and
+                        not args.asan)  # Use clang for asan builds.
                and not gn_args['target_cpu'].startswith('arm')
                and not gn_args['target_cpu'].startswith('mips'))
   gn_args['is_clang'] = args.clang and has_clang
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index 3bb9965..d92f0a6 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -264,6 +264,17 @@
     partUnit.accept(new PatchApplier(partEdits, patchFinder));
     results.add(partEdits);
   }
+
+  if (patchFinder.patches.length != patchFinder.applied.length) {
+    print('Some elements marked as @patch do not have corresponding elements:');
+    for (var patched in patchFinder.patches.keys) {
+      if (!patchFinder.applied.contains(patched)) {
+        print('*** ${patched}');
+      }
+    }
+    throw "Failed to apply all @patch-es";
+  }
+
   return new List<String>.from(results.map((e) => e.toString()));
 }
 
@@ -343,14 +354,16 @@
     if (node is FieldDeclaration) return;
 
     var externalKeyword = (node as dynamic).externalKeyword;
-    if (externalKeyword == null) return;
 
     var name = _qualifiedName(node);
     var patchNode = patch.patches[name];
     if (patchNode == null) {
-      print('warning: patch not found for $name: $node');
+      if (externalKeyword != null) {
+        print('warning: patch not found for $name: $node');
+      }
       return;
     }
+    patch.applied.add(name);
 
     Annotation patchMeta = patchNode.metadata.lastWhere(_isPatchAnnotation);
     int start = patchMeta.endToken.next.offset;
@@ -359,7 +372,7 @@
     // For some node like static fields, the node's offset doesn't include
     // the external keyword. Also starting from the keyword lets us preserve
     // documentation comments.
-    edits.replace(externalKeyword.offset, node.end, code);
+    edits.replace(externalKeyword?.offset ?? node.offset, node.end, code);
   }
 }
 
@@ -370,6 +383,7 @@
   final Map patches = <String, Declaration>{};
   final Map mergeMembers = <String, List<ClassMember>>{};
   final List mergeDeclarations = <CompilationUnitMember>[];
+  final Set<String> applied = new Set<String>();
 
   PatchFinder.parseAndVisit(String name, String contents)
       : contents = contents,
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 5e8be6e..97c918a 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -310,8 +310,10 @@
     }
 
     String precompiledRunner = suite.dartPrecompiledBinaryFileName;
+    String processTest = suite.processTestBinaryFileName;
     return <Command>[
       commandBuilder.getAdbPrecompiledCommand(precompiledRunner,
+                                              processTest,
                                               script,
                                               arguments,
                                               useBlobs)
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 7b1e596..f9d7b99 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -364,12 +364,16 @@
 
 class AdbPrecompilationCommand extends Command {
   final String precompiledRunnerFilename;
+  final String processTestFilename;
   final String precompiledTestDirectory;
   final List<String> arguments;
   final bool useBlobs;
 
   AdbPrecompilationCommand._(this.precompiledRunnerFilename,
-      this.precompiledTestDirectory, this.arguments, this.useBlobs)
+                             this.processTestFilename,
+                             this.precompiledTestDirectory,
+                             this.arguments,
+                             this.useBlobs)
       : super._("adb_precompilation");
 
   void _buildHashCode(HashCodeBuilder builder) {
@@ -698,9 +702,12 @@
   }
 
   AdbPrecompilationCommand getAdbPrecompiledCommand(String precompiledRunner,
-      String testDirectory, List<String> arguments, bool useBlobs) {
+                                                    String processTest,
+                                                    String testDirectory,
+                                                    List<String> arguments,
+                                                    bool useBlobs) {
     var command = new AdbPrecompilationCommand._(
-        precompiledRunner, testDirectory, arguments, useBlobs);
+        precompiledRunner, processTest, testDirectory, arguments, useBlobs);
     return _getUniqueCommand(command);
   }
 
@@ -2638,6 +2645,7 @@
   Future<CommandOutput> _runAdbPrecompilationCommand(
       AdbDevice device, AdbPrecompilationCommand command, int timeout) async {
     var runner = command.precompiledRunnerFilename;
+    var processTest = command.processTestFilename;
     var testdir = command.precompiledTestDirectory;
     var arguments = command.arguments;
     var devicedir = '/data/local/tmp/precompilation-testing';
@@ -2663,8 +2671,10 @@
     // timing).
     steps.add(() => device.runAdbCommand(
         ['push', runner, '$devicedir/dart_precompiled_runtime']));
+    steps.add(() => device.runAdbCommand(
+        ['push', processTest, '$devicedir/process_test']));
     steps.add(() => device.runAdbShellCommand(
-        ['chmod', '777', '$devicedir/dart_precompiled_runtime']));
+        ['chmod', '777', '$devicedir/dart_precompiled_runtime $devicedir/process_test']));
 
     for (var file in files) {
       steps.add(() => device
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index e994822..c13b69a 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -234,6 +234,13 @@
     return dartExecutable;
   }
 
+  String get processTestBinaryFileName {
+    String suffix = executableBinarySuffix;
+    String processTestExecutable = '$buildDir/process_test$suffix';
+    TestUtils.ensureExists(processTestExecutable, configuration);
+    return processTestExecutable;
+  }
+
   String get d8FileName {
     var suffix = getExecutableSuffix('d8');
     var d8Dir = TestUtils.dartDir.append('third_party/d8');
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index c0e428d..9ec1093 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -62,7 +62,8 @@
   main_dart = "$root_gen_dir/dart2js.dart"
   training_args = [
     "--library-root=" + rebase_path("../../sdk"),
-    rebase_path("../../tests/language/first_test.dart"),
+    "--categories=all",
+    rebase_path("$root_gen_dir/dart2js.dart"),
   ]
 }