Version 2.0.0-dev.60.0

Merge commit '35b17f373014cdb54dc7f80cfa59cc7d5f9f3803' into dev
diff --git a/.gitattributes b/.gitattributes
index 8f4b8ba..b7d52e5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -53,3 +53,5 @@
 *.png binary
 *.jpg binary
 *.xpi binary
+
+*.status diff=status
diff --git a/.gitconfig b/.gitconfig
new file mode 100644
index 0000000..7df539b
--- /dev/null
+++ b/.gitconfig
@@ -0,0 +1,2 @@
+[diff "status"]
+	xfuncname = "^\\[.*\\]$"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36f7387..08bfa29 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 2.0.0-dev.60.0
+
+### Core library changes
+
+* `dart:convert`
+  * Allow `utf8.decoder.fuse(json.decoder)` to ignore leading Unicode BOM.
+
+### Tool Changes
+
+#### Analyzer
+
+* New static checking of duplicate shown or hidden names in an export directive
+  ([issue 33182]).
+
+[issue 33182]: https://github.com/dart-lang/sdk/issues/33182
+
 ## 2.0.0-dev.59.0
 
 ### Language
@@ -565,6 +581,10 @@
   * Renamed `E`, `LN10`, `LN`, `LOG2E`, `LOG10E`, `PI`, `SQRT1_2` and `SQRT2`
     to `e`, `ln10`, `ln`, `log2e`, `log10e`, `pi`, `sqrt1_2` and `sqrt2`.
 
+* `dart.mirrors`
+  * Added `IsolateMirror.loadUri`, which allows dynamically loading additional
+    code.
+
 <!--
 Still need entries for all changes to dart:svg since 1.x
 -->
diff --git a/DEPS b/DEPS
index 114668e..76e7739 100644
--- a/DEPS
+++ b/DEPS
@@ -63,7 +63,7 @@
   "convert_tag": "2.0.1",
   "crypto_tag" : "2.0.2+1",
   "csslib_tag" : "0.14.1",
-  "dart2js_info_tag" : "0.5.6+2",
+  "dart2js_info_tag" : "0.5.6+4",
 
   # Note: updates to dart_style have to be coordinated carefully with
   # the infrastructure-team so that the internal formatter in
@@ -79,7 +79,7 @@
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
   "dart_style_tag": "1.0.14",  # Please see the note above before updating.
 
-  "dartdoc_tag" : "v0.19.1",
+  "dartdoc_tag" : "v0.20.0",
   "fixnum_tag": "0.10.5",
   "func_rev": "25eec48146a58967d75330075ab376b3838b18a8",
   "glob_tag": "1.1.5",
@@ -99,7 +99,7 @@
   "markdown_tag": "2.0.0",
   "matcher_tag": "0.12.1+4",
   "mime_tag": "0.9.6",
-  "mockito_tag": "a92db054fba18bc2d605be7670aee74b7cadc00a",
+  "mockito_tag": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "mustache4dart_tag" : "v2.1.2",
   "oauth2_tag": "1.1.0",
   "observatory_pub_packages_rev": "d3a3aebefbd35aa30fe7bbc2889b772b398f7d7f",
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 5e8b62c..2db8dfe 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -47,6 +47,11 @@
 %   local function evaluates to the closurization of that declaration.
 % - Make `mixin` and `interface` built-in identifiers.
 % - Make `async` *not* a reserved word inside async functions.
+% - Added 'Class Member Conflicts', simplifying and adjusting rules about
+%   member declaration conflicts beyond "`n` declared twice in one scope".
+% - Specify that integer literals are limited to signed 64-bit values,
+%   and that the `int` class is intended as signed 64-bit integer, but
+%   that platforms may differ.
 %
 % 1.15
 % - Change how language specification describes control flow.
@@ -1272,10 +1277,12 @@
 % Maybe the final field hides the setter in scope?
 % I think the original rules were best.
 
-\LMHash{}
-It is a compile-time error if a class declares two members of the same name.
-It is a compile-time error if a class has an instance member and a static member with the same name.
-% It is a compile-time error if a generic (\ref{generics}) class declares a member with the same name as one of its type parameters.
+\commentary{
+It is a compile-time error if a class declares two members of the same name,
+either because it declares the same name twice in the same scope (\ref{scoping}),
+or because it declares a static member and an instance member with the same name
+(\ref{classMemberConflicts}).
+}
 
 \commentary{
 Here are simple examples, that illustrate the difference between ``has a member'' and ``declares a member''.
@@ -1324,9 +1331,11 @@
 \LMHash{}
 It is a static warning if an instance method $m_1$ overrides an instance member $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
 It is a static warning if an instance method $m_1$ overrides an instance member $m_2$, the signature of $m_2$ explicitly specifies a default value for a formal parameter $p$, and the signature of $m_1$ implies a different default value for $p$.
-It is a static warning if a class $C$ declares an instance method named $n$ and has a setter named $n=$.
 
-% Works. If the name is public, no issue. If it's private, if a subclass has a conflicting inst var, it either is in the same lib and will be flagged, or is in another and is not an issue.
+\commentary{
+A method declaration may conflict with other declarations
+(\ref{classMemberConflicts}).
+}
 
 
 \subsubsection{Operators}
@@ -1418,12 +1427,11 @@
 The instance getters of a class $C$ are those instance getters declared by $C$, either implicitly or explicitly, and the instance getters inherited by $C$ from its superclass.
 The static getters of a class $C$ are those static getters declared by $C$.
 
-\LMHash{}
-It is a compile-time error if a class has both a getter and a method with the same name.
-This restriction holds regardless of whether the getter is defined explicitly or implicitly, or whether the getter or the method are inherited or not.
-
 \commentary{
-This implies that a getter can never override a method, and a method can never override a getter or an instance variable.
+A getter declaration may conflict with other declarations
+(\ref{classMemberConflicts}).
+In particular, a getter can never override a method,
+and a method can never override a getter or an instance variable.
 }
 
 \LMHash{}
@@ -1431,22 +1439,6 @@
 It is a static warning if a getter $m_1$ overrides (\ref{inheritanceAndOverriding}) a getter
 $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
 
-\LMHash{}
-It is a static warning if a class declares a static getter named $v$ and also has a non-static setter named $v=$.
-
-% We need not consider implicit declarations: If $v$ is declared
-% implicitly then there is a static variable $v$ and an induced setter
-% $v=$, and then it is already a compile-time error to have an
-% instance setter named $v=$ due to the name clash. Otherwise, $v$ is
-% an explicitly declared static getter (and there may or may not be an
-% explicitly declared static setter $v=$). If the non-static setter
-% $v=$ is declared implicitly then there is an instance variable $v$
-% inducing it, and it will also induce an instance getter $v$, which
-% is again already a compile-time error.  Hence, if any of said
-% declarations are implicit then it is already a compile-time error,
-% so we need not specify how to handle those cases with respect to
-% this static warning.
-
 
 \subsection{Setters}
 \LMLabel{setters}
@@ -1490,22 +1482,10 @@
 It is a static warning if a setter $m_1$ overrides (\ref{inheritanceAndOverriding}) a setter $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
 It is a static warning if a class has a setter named $v=$ with argument type $T$ and a getter named $v$ with return type $S$, and $T$ may not be assigned to $S$.
 
-\LMHash{}
-It is a static warning if a class declares a static setter named $v=$ and has an instance getter named $v$.
-It is a static warning if a class declares a setter named $v=$ and has a method named $v$.
-
-% We need not consider implicit declarations: If $v=$ is declared
-% implicitly then there is a static variable $v$, and then it is
-% already a compile-time error to have an instance member named $v$,
-% both when it is a method and when it is induced by an instance
-% variable. Otherwise, $v=$ is an explicitly declared setter (and
-% there may or may not be an explicitly declared static getter
-% $v$). If the non-static member $v$ is declared implicitly then there
-% is an instance variable $v$ inducing it, and it will also induce an
-% instance setter $v=$, which is again already a compile-time error.
-% Hence, if any of said declarations are implicit then it is already a
-% compile-time error, so we need not specify how to handle those cases
-% with respect to this static warning.
+\commentary{
+A setter declaration may conflict with other declarations
+(\ref{classMemberConflicts}).
+}
 
 
 \subsection{Abstract Instance Members}
@@ -1632,9 +1612,13 @@
 
 \LMHash{}
 A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier $id$.
-It is a compile-time error if $id$ is the name of a member declared in the immediately enclosing class.
 It is a compile-time error if the name of a constructor is not a constructor name.
 
+\commentary{
+A constructor declaration may conflict with static member declarations
+(\ref{classMemberConflicts}).
+}
+
 % In what scope do constructors go? The simple names of named constructors go in the static scope of the class. Unnamed ones go nowhere, but we use the class name to refer to them; the class name could also in the static scope of the class as well to prevent weird errors, or we could ban it explicitly and avoiding duplication. Similarly, the instance scope could contain the constructor names and class name, or we could have special rules to prevent collisions between instance members and constructors or the class.
 
 % The enclosing scope of a generative constructor is the instance scope of the class in which it is declared (but what about redirecting?)
@@ -2170,9 +2154,10 @@
 Dart static methods may be seen as functions of the enclosing library.
 }
 
-\LMHash{}
-It is a static warning if a class $C$ declares a static method named $n$ and has a setter named $n=$.
-It is a static warning if a class $C$ declares a static member named $n$ and has an instance member named $n$.
+\commentary{
+Static method declarations may conflict with other declarations
+(\ref{classMemberConflicts}).
+}
 
 
 \subsection{Static Variables}
@@ -2451,6 +2436,28 @@
 % Should we ignore unimplemented private members?
 
 
+\subsection{Class Member Conflicts}
+\LMLabel{classMemberConflicts}
+
+Some pairs of class member declarations cannot coexist,
+even though they do not both introduce the same name into the same scope.
+This section specifies these errors.
+
+The {\em basename} of a getter or method named $n$ is $n$;
+the basename of a setter named \code{$n$=} is $n$.
+
+Let $C$ be a class.
+It is a compile-time error if $C$ declares a
+\begin{itemize}
+\item constructor named \code{$C$.$n$} and a static member with basename $n$.
+\item getter or a setter with basename $n$, and has a method named $n$.
+\item method named $n$, and has a getter or a setter with basename $n$.
+\item static member with basename $n$, and has an instance member with basename $n$.
+\end{itemize}
+These errors occur when the getters or setters are defined explicitly
+as well as when they are induced by variable declarations.
+
+
 \section{Interfaces}
 \LMLabel{interfaces}
 
@@ -3275,7 +3282,7 @@
 \LMLabel{numbers}
 
 \LMHash{}
-A {\em numeric literal} is either a decimal or hexadecimal integer of arbitrary size, or a decimal double.
+A {\em numeric literal} is either a decimal or hexadecimal numeral representing an integer value, or a decimal double representation.
 
 \begin{grammar}
 {\bf numericLiteral:}NUMBER;
@@ -3286,54 +3293,78 @@
   {`\escapegrammar .}' DIGIT+ EXPONENT?
   .
 
-{\bf EXPONENT:}(`e' $|$ `E') ('+' $|$ `-`)? DIGIT+
+{\bf EXPONENT:}(`e' $|$ `E') (`+' $|$ `-')? DIGIT+
   .
 
 {\bf HEX\_NUMBER:}`0x' HEX\_DIGIT+;
   `0X' HEX\_DIGIT+
   .
 
-{\bf HEX\_DIGIT:}`a'{\escapegrammar ..}'f';
-  `A'{\escapegrammar ..}'F';
+{\bf HEX\_DIGIT:}`a'{\escapegrammar ..}`f';
+  `A'{\escapegrammar ..}`F';
   DIGIT
   .
 \end{grammar}
 
 \LMHash{}
-If a numeric literal begins with the prefix `0x' or `0X',
-it denotes the integer represented by the hexadecimal numeral
+A numeric literal starting with `0x' or `0X'
+is a {\em hexadecimal integer literal}.
+It has the numeric integer value of the hexadecimal numeral
 following `0x' (respectively `0X').
-Otherwise, if the numeric literal contains only decimal digits,
-it denotes an integer represented as a decimal numeral.
-In either case the literal evaluates to an instance of the class \code{int}
-with the integer value represented by that numeral.
-Otherwise, the numeric literal contains either a decimal point or an exponent part
-and it evaluates to a an instance of the `double` class
-representing a 64 bit double precision floating point number
-as specified by the IEEE 754 standard.
 
 \LMHash{}
-In principle, the range of integers supported by a Dart implementations is unlimited.
-In practice, it is limited by available memory.
-Implementations may also be limited by other considerations.
-
-\commentary{
-For example, implementations may choose to limit the range to facilitate efficient compilation to Javascript.
-These limitations should be relaxed as soon as technologically feasible.
-}
-
-\LMHash{}
-It is a compile-time error for a class to extend, mix in or implement \code{int}.
-It is a compile-time error for a class to extend, mix in or implement \code{double}.
-It is a compile-time error for any class other than \code{int} and \code{double} to extend, mix in or implement \code{num}.
+A numeric literal that contains only decimal digits is a {\em decimal integer literal}.
+It has the numeric integer value of the decimal numeral.
 
 \LMHash{}
 An {\em integer literal} is either a hexadecimal integer literal or a decimal integer literal.
 The static type of an integer literal is \code{int}.
 
 \LMHash{}
-A {\em literal double} is a numeric literal that is not an integer literal.
-The static type of a literal double is \code{double}.
+A numeric literal that is not an integer literal is a {\em double literal}.
+\commentary{A double literal always contains either a decimal point or an exponent part.}
+The static type of a double literal is \code{double}.
+
+\LMHash{}
+A hexadecimal integer literal with numeric value $i$ is a compile-time
+error if $i \ge{} 2^{64}$, unless it is prefixed by a unary minus operator,
+in which case it is a compile-time error if $i \gt{} 2^{63}$.
+If the \code{int} class is implemented as signed 64-bit two's complement integers,
+$i \ge{} 2^{63}$, and the literal is not prefixed by a unary minus operator, then
+the literal evaluates to an instance of the \code{int} class representing the integer value $i - 2^{64}$.
+Otherwise the literal evaluates to an instance of the \code{int} class representing
+the integer value $i$,
+and it is a compile-time error if the integer $i$ cannot be represented exactly
+by an instance of \code{int}.
+
+\LMHash{}
+A decimal integer literal with numeric value $i$ is a compile-time error
+if $i \ge{} 2^{63}$, unless $i$ is prefixed by a unary minus operator,
+in which case it is only a compile-time error if $i \gt{} 2^{63}$.
+Otherwise the literal evaluates to an instance of the \code{int} class representing
+the integer value $i$.
+It is a compile-time error if the value $i$ cannot be represented exactly
+by an instance of \code{int}.
+
+\LMHash{}
+A double literal evaluates to a an instance of the \code{double} class
+representing a 64 bit double precision floating point number
+as specified by the IEEE 754 standard.
+
+\commentary{
+Integers in Dart are designed to be implemented as
+64-bit two's complement integer representations.
+In practice, implementations may be limited by other considerations.
+For example, Dart compiled to JavaScript may use the JavaScript number type,
+equivalent to Dart \code{double}, to represent integers, and if so,
+integer literals with more than 53 bits of precision cannot be represented
+exactly.
+}
+
+\LMHash{}
+It is a compile-time error for a class to extend, mix in or implement \code{int}.
+It is a compile-time error for a class to extend, mix in or implement \code{double}.
+It is a compile-time error for any class other than \code{int} and \code{double} to extend, mix in or implement \code{num}.
 
 
 \subsection{Booleans}
@@ -6540,7 +6571,20 @@
 %The expression $-e$ is equivalent to the method invocation \code{$e$.-()}.  The expression \code{-\SUPER{}} is equivalent to the method invocation \code{\SUPER{}.-()}.
 
 \LMHash{}
-An expression of the form \code{$op$ $e$} is equivalent to the method invocation \code{$e.op()$}.
+If $e$ is an expression is of the form \code{-$l$}
+where $l$ is an integer literal (\ref{numbers}) with numerical integer value $i$,
+then it is a compile-time error if $i \gt{} 2^{63}$.
+Otherwise, when $0 \le{} i \le{} 2^{63}$, the static type of $e$ is \code{int}
+and $e$ evaluates to an instance of the class \code{int}
+representing the integer value $-i$,
+and it is a compile-time error if the integer $-i$ cannot be represented exactly
+by an instance of \code{int}.
+\rationale{This treats \code{-$l$} where $l$ is an integer literal as an atomic signed numeral.
+It does not {\em evaluate} $l$ as an individual expression because \code{-9223372036854775808}
+should represent a valid \code{int} even if \code{9223372036854775808} does not.}
+
+\LMHash{}
+Any other expression of the form \code{$op$ $e$} is equivalent to the method invocation \code{$e.op()$}.
 An expression of the form \code{$op$ \SUPER{}} is equivalent to the method invocation (\ref{superInvocation}) \code{\SUPER{}.$op()$}.
 
 
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index 2d9e01e..7c8ac58 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -59,7 +59,7 @@
 
   /**
    * The server is automatically started before every test.
-  */
+   */
   @override
   Future setUp({bool useCFE: false}) {
     onAnalysisErrors.listen((AnalysisErrorsParams params) {
@@ -74,11 +74,7 @@
       outOfTestExpect(serverConnected.isCompleted, isFalse);
       serverConnected.complete();
     });
-    return startServer(
-      servicesPort: vmServicePort,
-      cfe: useCFE,
-      checked: false,
-    ).then((_) {
+    return startServer(servicesPort: vmServicePort, cfe: useCFE).then((_) {
       server.listenToOutput(dispatchNotification);
       server.exitCode.then((_) {
         skipShutdown = true;
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 92eb394..ded8e70 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -601,20 +601,19 @@
    * otherwise in the first driver, otherwise `null` is returned.
    */
   Future<nd.AnalysisResult> getAnalysisResult(String path,
-      {bool sendCachedToStream: false}) async {
+      {bool sendCachedToStream: false}) {
     if (!AnalysisEngine.isDartFileName(path)) {
       return null;
     }
 
-    try {
-      nd.AnalysisDriver driver = getAnalysisDriver(path);
-      return await driver?.getResult(path,
-          sendCachedToStream: sendCachedToStream);
-    } catch (e) {
-      // Ignore the exception.
-      // We don't want to log the same exception again and again.
-      return null;
+    nd.AnalysisDriver driver = getAnalysisDriver(path);
+    if (driver == null) {
+      return new Future.value();
     }
+
+    return driver
+        .getResult(path, sendCachedToStream: sendCachedToStream)
+        .catchError((_) => null);
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 86e8dce..1fd145f 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -569,23 +569,29 @@
     int length = params.length;
     // add refactoring kinds
     List<RefactoringKind> kinds = <RefactoringKind>[];
-    // Try EXTRACT_WIDGETS.
+    // Check nodes.
     {
       var unit = await server.getResolvedCompilationUnit(file);
       var analysisSession = server.getAnalysisDriver(file)?.currentSession;
       if (unit != null && analysisSession != null) {
-        var refactoring = new ExtractWidgetRefactoring(
-            searchEngine, analysisSession, unit, offset);
-        if (refactoring.isAvailable()) {
+        // Try EXTRACT_LOCAL_VARIABLE.
+        if (new ExtractLocalRefactoring(unit, offset, length).isAvailable()) {
+          kinds.add(RefactoringKind.EXTRACT_LOCAL_VARIABLE);
+        }
+        // Try EXTRACT_METHOD.
+        if (new ExtractMethodRefactoring(
+                searchEngine, server.getAstProvider(file), unit, offset, length)
+            .isAvailable()) {
+          kinds.add(RefactoringKind.EXTRACT_METHOD);
+        }
+        // Try EXTRACT_WIDGETS.
+        if (new ExtractWidgetRefactoring(
+                searchEngine, analysisSession, unit, offset, length)
+            .isAvailable()) {
           kinds.add(RefactoringKind.EXTRACT_WIDGET);
         }
       }
     }
-    // try EXTRACT_*
-    if (length != 0) {
-      kinds.add(RefactoringKind.EXTRACT_LOCAL_VARIABLE);
-      kinds.add(RefactoringKind.EXTRACT_METHOD);
-    }
     // check elements
     {
       Element element = await server.getElementAtOffset(file, offset);
@@ -930,7 +936,7 @@
       if (unit != null) {
         var analysisSession = server.getAnalysisDriver(file).currentSession;
         refactoring = new ExtractWidgetRefactoring(
-            searchEngine, analysisSession, unit, offset);
+            searchEngine, analysisSession, unit, offset, length);
         feedback = new ExtractWidgetFeedback();
       }
     }
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index d3ffa60..ab94d11 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:collection';
 
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/src/analysis_server.dart';
@@ -144,7 +145,7 @@
       }
     }
 
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     var declarations = <search.Declaration>[];
 
     protocol.ElementKind getElementKind(search.DeclarationKind kind) {
@@ -209,7 +210,7 @@
     }).toList();
 
     server.sendResponse(new protocol.SearchGetElementDeclarationsResult(
-            elementDeclarations, files)
+            elementDeclarations, files.toList())
         .toResponse(request.id));
   }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 9603adb..769d2ca 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -90,8 +90,9 @@
 class DartFixKind {
   static const ADD_ASYNC =
       const FixKind('ADD_ASYNC', 50, "Add 'async' modifier");
-  static const ADD_EXPLICIT_CAST =
-      const FixKind('ADD_EXPLICIT_CAST', 50, "Add cast");
+  static const ADD_EXPLICIT_CAST = const FixKind(
+      'ADD_EXPLICIT_CAST', 50, "Add cast",
+      appliedTogetherMessage: "Add all casts in file");
   static const ADD_FIELD_FORMAL_PARAMETERS = const FixKind(
       'ADD_FIELD_FORMAL_PARAMETERS', 30, "Add final field formal parameters");
   static const ADD_MISSING_PARAMETER_POSITIONAL = const FixKind(
@@ -104,7 +105,8 @@
       'ADD_MISSING_PARAMETER_REQUIRED', 30, "Add required parameter");
   static const ADD_MISSING_REQUIRED_ARGUMENT = const FixKind(
       'ADD_MISSING_REQUIRED_ARGUMENT', 30, "Add required argument '{0}'");
-  static const ADD_NE_NULL = const FixKind('ADD_NE_NULL', 50, "Add != null");
+  static const ADD_NE_NULL = const FixKind('ADD_NE_NULL', 50, "Add != null",
+      appliedTogetherMessage: "Add != null everywhere in file");
   static const ADD_PACKAGE_DEPENDENCY = const FixKind(
       'ADD_PACKAGE_DEPENDENCY', 50, "Add dependency on package '{0}'");
   static const ADD_STATIC =
@@ -206,8 +208,9 @@
       const FixKind('REMOVE_THIS_EXPRESSION', 50, "Remove this expression");
   static const REMOVE_TYPE_NAME =
       const FixKind('REMOVE_TYPE_NAME', 50, "Remove type name");
-  static const REMOVE_UNNECESSARY_CAST =
-      const FixKind('REMOVE_UNNECESSARY_CAST', 50, "Remove unnecessary cast");
+  static const REMOVE_UNNECESSARY_CAST = const FixKind(
+      'REMOVE_UNNECESSARY_CAST', 50, "Remove unnecessary cast",
+      appliedTogetherMessage: "Remove all unnecessary casts in file");
   static const REMOVE_UNUSED_CATCH_CLAUSE =
       const FixKind('REMOVE_UNUSED_CATCH', 50, "Remove unused 'catch' clause");
   static const REMOVE_UNUSED_CATCH_STACK = const FixKind(
@@ -218,7 +221,8 @@
   static const RENAME_TO_CAMEL_CASE =
       const FixKind('RENAME_TO_CAMEL_CASE', 50, "Rename to '{0}'");
   static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(
-      'REPLACE_BOOLEAN_WITH_BOOL', 50, "Replace 'boolean' with 'bool'");
+      'REPLACE_BOOLEAN_WITH_BOOL', 50, "Replace 'boolean' with 'bool'",
+      appliedTogetherMessage: "Replace all 'boolean' with 'bool' in file");
   static const REPLACE_FINAL_WITH_CONST = const FixKind(
       'REPLACE_FINAL_WITH_CONST', 50, "Replace 'final' with 'const'");
   static const REPLACE_VAR_WITH_DYNAMIC = const FixKind(
@@ -246,12 +250,16 @@
       'USE_EFFECTIVE_INTEGER_DIVISION',
       50,
       "Use effective integer division ~/");
-  static const USE_EQ_EQ_NULL =
-      const FixKind('USE_EQ_EQ_NULL', 50, "Use == null instead of 'is Null'");
+  static const USE_EQ_EQ_NULL = const FixKind(
+      'USE_EQ_EQ_NULL', 50, "Use == null instead of 'is Null'",
+      appliedTogetherMessage:
+          "Use == null instead of 'is Null' everywhere in file");
   static const USE_IS_NOT_EMPTY = const FixKind(
       'USE_NOT_EMPTY', 50, "Use x.isNotEmpty instead of '!x.isEmpty'");
-  static const USE_NOT_EQ_NULL =
-      const FixKind('USE_NOT_EQ_NULL', 50, "Use != null instead of 'is! Null'");
+  static const USE_NOT_EQ_NULL = const FixKind(
+      'USE_NOT_EQ_NULL', 50, "Use != null instead of 'is! Null'",
+      appliedTogetherMessage:
+          "Use != null instead of 'is! Null' everywhere in file");
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index da9de25..26867a4 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -2678,6 +2678,9 @@
     IfStatement ifStatement = node is IfStatement
         ? node
         : node.getAncestor((node) => node is IfStatement);
+    if (ifStatement == null) {
+      return;
+    }
     var thenStatement = ifStatement.thenStatement;
     Statement uniqueStatement(Statement statement) {
       if (statement is Block) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index feb748d..011ce65 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -212,6 +212,11 @@
   }
 
   @override
+  bool isAvailable() {
+    return !_checkSelection().hasFatalError;
+  }
+
+  @override
   bool requiresPreview() => false;
 
   /**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 4a1d37a..f8865c5 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -395,6 +395,11 @@
   }
 
   @override
+  bool isAvailable() {
+    return !_checkSelection().hasFatalError;
+  }
+
+  @override
   bool requiresPreview() => false;
 
   /**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index d304a1c..1ad85d0 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -31,6 +31,7 @@
   final AnalysisSessionHelper sessionHelper;
   final CompilationUnit unit;
   final int offset;
+  final int length;
 
   CompilationUnitElement unitElement;
   LibraryElement libraryElement;
@@ -58,6 +59,12 @@
   /// The widget creation expression to extract.
   InstanceCreationExpression _expression;
 
+  /// The statements covered by [offset] and [length] to extract.
+  List<Statement> _statements;
+
+  /// The [SourceRange] that covers [_statements].
+  SourceRange _statementsRange;
+
   /// The method returning widget to extract.
   MethodDeclaration _method;
 
@@ -66,8 +73,8 @@
   /// and [_method] parameters.
   List<_Parameter> _parameters = [];
 
-  ExtractWidgetRefactoringImpl(
-      this.searchEngine, AnalysisSession session, this.unit, this.offset)
+  ExtractWidgetRefactoringImpl(this.searchEngine, AnalysisSession session,
+      this.unit, this.offset, this.length)
       : sessionHelper = new AnalysisSessionHelper(session) {
     unitElement = unit.element;
     libraryElement = unitElement.library;
@@ -95,8 +102,10 @@
       return result;
     }
 
-    _enclosingUnitMember = (_expression ?? _method).getAncestor(
-        (n) => n is CompilationUnitMember && n.parent is CompilationUnit);
+    AstNode astNode = _expression ?? _method ?? _statements.first;
+    _enclosingUnitMember = astNode.getAncestor((n) {
+      return n is CompilationUnitMember && n.parent is CompilationUnit;
+    });
 
     result.addStatus(await _initializeClasses());
     result.addStatus(await _initializeParameters());
@@ -136,6 +145,12 @@
         builder.addReplacement(range.node(_expression), (builder) {
           _writeWidgetInstantiation(builder);
         });
+      } else if (_statements != null) {
+        builder.addReplacement(_statementsRange, (builder) {
+          builder.write('return ');
+          _writeWidgetInstantiation(builder);
+          builder.write(';');
+        });
       } else {
         _removeMethodDeclaration(builder);
         _replaceInvocationsWithInstantiations(builder);
@@ -156,7 +171,7 @@
 
   /// Checks if [offset] is a widget creation expression that can be extracted.
   RefactoringStatus _checkSelection() {
-    AstNode node = new NodeLocator2(offset, offset).searchWithin(unit);
+    AstNode node = new NodeLocator2(offset, offset + length).searchWithin(unit);
 
     // Find the enclosing class.
     _enclosingClassNode = node?.getAncestor((n) => n is ClassDeclaration);
@@ -169,6 +184,30 @@
       return new RefactoringStatus();
     }
 
+    // Block with selected statements.
+    if (node is Block) {
+      var selectionRange = new SourceRange(offset, length);
+      var statements = <Statement>[];
+      for (var statement in node.statements) {
+        var statementRange = range.node(statement);
+        if (statementRange.intersects(selectionRange)) {
+          statements.add(statement);
+        }
+      }
+      if (statements.isNotEmpty) {
+        var lastStatement = statements.last;
+        if (lastStatement is ReturnStatement &&
+            isWidgetExpression(lastStatement.expression)) {
+          _statements = statements;
+          _statementsRange = range.startEnd(statements.first, statements.last);
+          return new RefactoringStatus();
+        } else {
+          return new RefactoringStatus.fatal(
+              'The last selected statement must return a widget.');
+        }
+      }
+    }
+
     // Widget myMethod(...) { ... }
     for (; node != null; node = node.parent) {
       if (node is FunctionBody) {
@@ -229,6 +268,13 @@
       collector = new _ParametersCollector(_enclosingClassElement, localRange);
       _expression.accept(collector);
     }
+    if (_statements != null) {
+      collector =
+          new _ParametersCollector(_enclosingClassElement, _statementsRange);
+      for (var statement in _statements) {
+        statement.accept(collector);
+      }
+    }
     if (_method != null) {
       SourceRange localRange = range.node(_method);
       collector = new _ParametersCollector(_enclosingClassElement, localRange);
@@ -266,6 +312,29 @@
       }
     }
 
+    // Collect used public names.
+    var usedNames = new Set<String>();
+    for (var parameter in _parameters) {
+      if (!parameter.name.startsWith('_')) {
+        usedNames.add(parameter.name);
+      }
+    }
+
+    // Give each private parameter a public name for the constructor.
+    for (var parameter in _parameters) {
+      var name = parameter.name;
+      if (name.startsWith('_')) {
+        var baseName = name.substring(1);
+        for (var i = 1;; i++) {
+          name = i == 1 ? baseName : '$baseName$i';
+          if (usedNames.add(name)) {
+            break;
+          }
+        }
+      }
+      parameter.constructorName = name;
+    }
+
     return collector.status;
   }
 
@@ -277,6 +346,11 @@
     builder.addDeletion(linesRange);
   }
 
+  String _replaceIndent(String code, String indentOld, String indentNew) {
+    var regExp = new RegExp('^$indentOld', multiLine: true);
+    return code.replaceAll(regExp, indentNew);
+  }
+
   /// Replace invocations of the [_method] with instantiations of the new
   /// widget class.
   void _replaceInvocationsWithInstantiations(DartFileEditBuilder builder) {
@@ -334,18 +408,33 @@
               builder.writeln(',');
 
               // Add parameters for fields, local, and method parameters.
-              for (int i = 0; i < _parameters.length; i++) {
+              for (var parameter in _parameters) {
                 builder.write('    ');
                 builder.write('@');
                 builder.writeReference(accessorRequired);
-                builder.write(' this.');
-                builder.write(_parameters[i].name);
+                builder.write(' ');
+                if (parameter.constructorName != parameter.name) {
+                  builder.writeType(parameter.type);
+                  builder.write(' ');
+                  builder.write(parameter.constructorName);
+                } else {
+                  builder.write('this.');
+                  builder.write(parameter.name);
+                }
                 builder.writeln(',');
               }
 
               builder.write('  }');
             },
             initializerWriter: () {
+              for (var parameter in _parameters) {
+                if (parameter.constructorName != parameter.name) {
+                  builder.write(parameter.name);
+                  builder.write(' = ');
+                  builder.write(parameter.constructorName);
+                  builder.write(', ');
+                }
+              }
               builder.write('super(key: key)');
             },
           );
@@ -378,8 +467,7 @@
                 String indentNew = '    ';
 
                 String code = utils.getNodeText(_expression);
-                code = code.replaceAll(
-                    new RegExp('^$indentOld', multiLine: true), indentNew);
+                code = _replaceIndent(code, indentOld, indentNew);
 
                 builder.writeln('{');
 
@@ -388,6 +476,20 @@
                 builder.writeln(';');
 
                 builder.writeln('  }');
+              } else if (_statements != null) {
+                String indentOld = utils.getLinePrefix(_statementsRange.offset);
+                String indentNew = '    ';
+
+                String code = utils.getRangeText(_statementsRange);
+                code = _replaceIndent(code, indentOld, indentNew);
+
+                builder.writeln('{');
+
+                builder.write(indentNew);
+                builder.write(code);
+                builder.writeln();
+
+                builder.writeln('  }');
               } else {
                 String code = utils.getNodeText(_method.body);
                 builder.writeln(code);
@@ -407,7 +509,7 @@
       if (parameter != _parameters.first) {
         builder.write(', ');
       }
-      builder.write(parameter.name);
+      builder.write(parameter.constructorName);
       builder.write(': ');
       builder.write(parameter.name);
     }
@@ -433,12 +535,19 @@
 }
 
 class _Parameter {
+  /// The name which is used to reference this parameter in the expression
+  /// being extracted, and also the name of the field in the new widget.
   final String name;
+
   final DartType type;
 
   /// Whether the parameter is a parameter of the method being extracted.
   final bool isMethodParameter;
 
+  /// If the [name] is private, the public name to use in the new widget
+  /// constructor. If the [name] is already public, then the [name].
+  String constructorName;
+
   _Parameter(this.name, this.type, {this.isMethodParameter: false});
 }
 
@@ -486,6 +595,7 @@
         }
       }
     }
+    // TODO(scheglov) support for ParameterElement
 
     if (type != null && uniqueElements.add(element)) {
       parameters.add(new _Parameter(elementName, type));
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 74f5d98..f99d9db 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -127,6 +127,12 @@
    * level of checking.
    */
   RefactoringStatus checkName();
+
+  /**
+   * Return `true` if refactoring is available, possibly without checking all
+   * initial conditions.
+   */
+  bool isAvailable();
 }
 
 /**
@@ -220,6 +226,12 @@
    * level of checking.
    */
   RefactoringStatus checkName();
+
+  /**
+   * Return `true` if refactoring is available, possibly without checking all
+   * initial conditions.
+   */
+  bool isAvailable();
 }
 
 /**
@@ -231,9 +243,9 @@
    * Returns a new [ExtractWidgetRefactoring] instance.
    */
   factory ExtractWidgetRefactoring(SearchEngine searchEngine,
-      AnalysisSession session, CompilationUnit unit, int offset) {
+      AnalysisSession session, CompilationUnit unit, int offset, int length) {
     return new ExtractWidgetRefactoringImpl(
-        searchEngine, session, unit, offset);
+        searchEngine, session, unit, offset, length);
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index e11f938..496db3d 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -85,9 +85,10 @@
   Future<List<SearchMatch>> searchMemberReferences(String name) async {
     List<SearchResult> allResults = [];
     List<AnalysisDriver> drivers = _drivers.toList();
+    SearchedFiles searchedFiles = _createSearchedFiles(drivers);
     for (AnalysisDriver driver in drivers) {
       List<SearchResult> results =
-          await driver.search.unresolvedMemberReferences(name);
+          await driver.search.unresolvedMemberReferences(name, searchedFiles);
       allResults.addAll(results);
     }
     return allResults.map(SearchMatchImpl.forSearchResult).toList();
@@ -97,8 +98,10 @@
   Future<List<SearchMatch>> searchReferences(Element element) async {
     List<SearchResult> allResults = [];
     List<AnalysisDriver> drivers = _drivers.toList();
+    SearchedFiles searchedFiles = _createSearchedFiles(drivers);
     for (AnalysisDriver driver in drivers) {
-      List<SearchResult> results = await driver.search.references(element);
+      List<SearchResult> results =
+          await driver.search.references(element, searchedFiles);
       allResults.addAll(results);
     }
     return allResults.map(SearchMatchImpl.forSearchResult).toList();
@@ -122,11 +125,25 @@
     return allElements.map(SearchMatchImpl.forElement).toList();
   }
 
+  /**
+   * Create a new [SearchedFiles] instance in which added files are owned
+   * by the drivers that have them added.
+   */
+  SearchedFiles _createSearchedFiles(List<AnalysisDriver> drivers) {
+    var searchedFiles = new SearchedFiles();
+    for (AnalysisDriver driver in drivers) {
+      searchedFiles.ownAdded(driver.search);
+    }
+    return searchedFiles;
+  }
+
   Future<List<SearchResult>> _searchDirectSubtypes(ClassElement type) async {
     List<SearchResult> allResults = [];
     List<AnalysisDriver> drivers = _drivers.toList();
+    SearchedFiles searchedFiles = _createSearchedFiles(drivers);
     for (AnalysisDriver driver in drivers) {
-      List<SearchResult> results = await driver.search.subTypes(type);
+      List<SearchResult> results =
+          await driver.search.subTypes(type, searchedFiles);
       allResults.addAll(results);
     }
     return allResults;
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index 85945fc..227a3c9 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -5,7 +5,6 @@
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -185,28 +184,6 @@
     }
   }
 
-  test_removeContextAfterRequest() async {
-    addTestFile('''
-main() {
-  var test = 0;
-  print(test);
-}
-''');
-    // handle the request synchronously
-    Request request =
-        _createGetNavigationRequest(testFile, testCode.indexOf('test);'), 0);
-    server.handleRequest(request);
-    // remove context, causes sending an "invalid file" error
-    {
-      Folder projectFolder = getFolder(projectPath);
-      server.contextManager.callbacks.removeContext(projectFolder, <String>[]);
-    }
-    // wait for an error response
-    Response response = await serverChannel.waitForResponse(request);
-    expect(response.error, isNotNull);
-    expect(response.error.code, RequestErrorCode.GET_NAVIGATION_INVALID_FILE);
-  }
-
   test_zeroLength_end() async {
     addTestFile('''
 main() {
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index f40ac66..175454e 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -143,41 +143,43 @@
   }
 
   test_setAnalysisSubscriptions_fileInIgnoredFolder_newOptions() async {
-    String path = '/project/samples/sample.dart';
+    String path = convertPath('/project/samples/sample.dart');
     newFile(path);
     newFile('/project/analysis_options.yaml', content: r'''
 analyzer:
   exclude:
     - 'samples/**'
 ''');
-    server.setAnalysisRoots('0', ['/project'], [], {});
+    server.setAnalysisRoots('0', [convertPath('/project')], [], {});
     server.setAnalysisSubscriptions(<AnalysisService, Set<String>>{
       AnalysisService.NAVIGATION: new Set<String>.from([path])
     });
-    // the file is excluded, so no navigation notification
+
+    // We respect subscriptions, even for excluded files.
     await server.onAnalysisComplete;
     expect(channel.notificationsReceived.any((notification) {
       return notification.event == ANALYSIS_NOTIFICATION_NAVIGATION;
-    }), isFalse);
+    }), isTrue);
   }
 
   test_setAnalysisSubscriptions_fileInIgnoredFolder_oldOptions() async {
-    String path = '/project/samples/sample.dart';
+    String path = convertPath('/project/samples/sample.dart');
     newFile(path);
     newFile('/project/.analysis_options', content: r'''
 analyzer:
   exclude:
     - 'samples/**'
 ''');
-    server.setAnalysisRoots('0', ['/project'], [], {});
+    server.setAnalysisRoots('0', [convertPath('/project')], [], {});
     server.setAnalysisSubscriptions(<AnalysisService, Set<String>>{
       AnalysisService.NAVIGATION: new Set<String>.from([path])
     });
-    // the file is excluded, so no navigation notification
+
+    // We respect subscriptions, even for excluded files.
     await server.onAnalysisComplete;
     expect(channel.notificationsReceived.any((notification) {
       return notification.event == ANALYSIS_NOTIFICATION_NAVIGATION;
-    }), isFalse);
+    }), isTrue);
   }
 
   Future test_shutdown() {
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 5e9e26f..93d6395 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -576,7 +576,7 @@
   }
 
   test_afterAnalysis_noSuchFile() async {
-    String file = '/no-such-file.dart';
+    String file = convertPath('/no-such-file.dart');
     addTestFile('// no matter');
     createProject();
     // wait for analysis, no results initially
@@ -584,9 +584,9 @@
     expect(filesHighlights[testFile], isNull);
     // subscribe
     addAnalysisSubscription(AnalysisService.HIGHLIGHTS, file);
-    await server.onAnalysisComplete;
+    await _resultsAvailable.future;
     // there are results
-    expect(filesHighlights[file], isNull);
+    expect(filesHighlights[file], isEmpty);
   }
 
   test_afterAnalysis_packageFile_external() async {
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index ed61e22..bea742f 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -876,6 +876,18 @@
     expect(kinds, contains(RefactoringKind.EXTRACT_METHOD));
   }
 
+  Future test_extractLocal_withoutSelection() async {
+    addTestFile('''
+main() {
+  var a = 1 + 2;
+}
+''');
+    await waitForTasksFinished();
+    await getRefactoringsAtString('1 + 2');
+    expect(kinds, contains(RefactoringKind.EXTRACT_LOCAL_VARIABLE));
+    expect(kinds, contains(RefactoringKind.EXTRACT_METHOD));
+  }
+
   Future test_extractWidget() async {
     addFlutterPackage();
     addTestFile('''
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk.dart b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk.dart
index d992b66..d58a043 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk.dart
@@ -70,14 +70,9 @@
   }
 
   @override
-  Future startServer(
-      {bool checked: true,
-      int diagnosticPort,
-      int servicesPort,
-      bool cfe: false}) {
+  Future startServer({int diagnosticPort, int servicesPort, bool cfe: false}) {
     String sdkPath = createNonStandardSdk();
     return server.start(
-        checked: checked,
         diagnosticPort: diagnosticPort,
         sdkPath: sdkPath,
         servicesPort: servicesPort,
diff --git a/pkg/analysis_server/test/integration/analysis/highlights_test2.dart b/pkg/analysis_server/test/integration/analysis/highlights_test2.dart
index 5f4a9c3..86e5917 100644
--- a/pkg/analysis_server/test/integration/analysis/highlights_test2.dart
+++ b/pkg/analysis_server/test/integration/analysis/highlights_test2.dart
@@ -21,13 +21,11 @@
 @reflectiveTest
 class AnalysisHighlightsTest extends AbstractAnalysisServerIntegrationTest {
   Future startServer({
-    bool checked: true,
     int diagnosticPort,
     int servicesPort,
     bool cfe: false,
   }) {
     return server.start(
-        checked: checked,
         diagnosticPort: diagnosticPort,
         servicesPort: servicesPort,
         useAnalysisHighlight2: true,
diff --git a/pkg/analysis_server/test/integration/support/integration_tests.dart b/pkg/analysis_server/test/integration/support/integration_tests.dart
index db7ff54..97527b1 100644
--- a/pkg/analysis_server/test/integration/support/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/support/integration_tests.dart
@@ -263,13 +263,11 @@
    * Start [server].
    */
   Future startServer({
-    bool checked: true,
     int diagnosticPort,
     int servicesPort,
     bool cfe: false,
   }) {
     return server.start(
-        checked: checked,
         diagnosticPort: diagnosticPort,
         servicesPort: servicesPort,
         useCFE: cfe || useCFE);
@@ -664,7 +662,6 @@
    * to be used.
    */
   Future start({
-    bool checked: true,
     int diagnosticPort,
     String instrumentationLogFile,
     bool profileServer: false,
@@ -678,9 +675,28 @@
     }
     _time.start();
     String dartBinary = Platform.executable;
-    String rootDir =
-        findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
-    String serverPath = normalize(join(rootDir, 'bin', 'server.dart'));
+
+    // The integration tests run 3x faster when run from snapshots (you need to
+    // run test.py with --use-sdk).
+    final bool useSnapshot = true;
+    String serverPath;
+
+    if (useSnapshot) {
+      // Look for snapshots/analysis_server.dart.snapshot.
+      serverPath = normalize(join(dirname(Platform.resolvedExecutable),
+          'snapshots', 'analysis_server.dart.snapshot'));
+
+      if (!FileSystemEntity.isFileSync(serverPath)) {
+        // Look for dart-sdk/bin/snapshots/analysis_server.dart.snapshot.
+        serverPath = normalize(join(dirname(Platform.resolvedExecutable),
+            'dart-sdk', 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
+      }
+    } else {
+      String rootDir =
+          findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
+      serverPath = normalize(join(rootDir, 'bin', 'server.dart'));
+    }
+
     List<String> arguments = [];
     //
     // Add VM arguments.
@@ -701,9 +717,6 @@
     if (Platform.packageConfig != null) {
       arguments.add('--packages=${Platform.packageConfig}');
     }
-    if (checked) {
-      arguments.add('--checked');
-    }
     //
     // Add the server executable.
     //
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 71bf567..ab58b70 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -85,15 +85,15 @@
 ''').path;
 
     // Limit to exactly one file.
-    await _getDeclarations(pattern: r'[A-D]', maxResults: 2);
+    await _getDeclarations(pattern: r'^[A-D]$', maxResults: 2);
     expect(declarationsResult.declarations, hasLength(2));
 
     // Limit in the middle of the second file.
-    await _getDeclarations(pattern: r'[A-D]', maxResults: 3);
+    await _getDeclarations(pattern: r'^[A-D]$', maxResults: 3);
     expect(declarationsResult.declarations, hasLength(3));
 
     // No limit.
-    await _getDeclarations(pattern: r'[A-D]');
+    await _getDeclarations(pattern: r'^[A-D]$');
     expect(declarationsResult.declarations, hasLength(4));
   }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index d6d8191..024e565 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -475,31 +475,14 @@
         analysisResult, completionOffset, new CompletionPerformance());
 
     // Build the request
-    Completer<DartCompletionRequest> requestCompleter =
-        new Completer<DartCompletionRequest>();
-    DartCompletionRequestImpl
-        .from(baseRequest)
-        .then((DartCompletionRequest request) {
-      requestCompleter.complete(request);
-    });
-    request = await performAnalysis(times, requestCompleter);
+    var request = await DartCompletionRequestImpl.from(baseRequest);
 
     var range = request.target.computeReplacementRange(request.offset);
     replacementOffset = range.offset;
     replacementLength = range.length;
-    Completer<List<CompletionSuggestion>> suggestionCompleter =
-        new Completer<List<CompletionSuggestion>>();
 
     // Request completions
-    contributor
-        .computeSuggestions(request)
-        .then((List<CompletionSuggestion> computedSuggestions) {
-      suggestionCompleter.complete(computedSuggestions);
-    });
-
-    // Perform analysis until the suggestions have been computed
-    // or the max analysis cycles ([times]) has been reached
-    suggestions = await performAnalysis(times, suggestionCompleter);
+    suggestions = await contributor.computeSuggestions(request);
     expect(suggestions, isNotNull, reason: 'expected suggestions');
   }
 
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index dbd1ee2..2a4974a 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -477,6 +477,28 @@
 ''');
   }
 
+  test_addExplicitCast_assignment_general_all() async {
+    await resolveTestUnit('''
+f(A a) {
+  B b, b2;
+  b = a;
+  b2 = a;
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(A a) {
+  B b, b2;
+  b = a as B;
+  b2 = a as B;
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_assignment_list() async {
     await resolveTestUnit('''
 f(List<A> a) {
@@ -496,6 +518,28 @@
 ''');
   }
 
+  test_addExplicitCast_assignment_list_all() async {
+    await resolveTestUnit('''
+f(List<A> a) {
+  List<B> b, b2;
+  b = a.where((e) => e is B).toList();
+  b2 = a.where((e) => e is B).toList();
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(List<A> a) {
+  List<B> b, b2;
+  b = a.where((e) => e is B).cast<B>().toList();
+  b2 = a.where((e) => e is B).cast<B>().toList();
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_assignment_map() async {
     await resolveTestUnit('''
 f(Map<A, B> a) {
@@ -515,6 +559,28 @@
 ''');
   }
 
+  test_addExplicitCast_assignment_map_all() async {
+    await resolveTestUnit('''
+f(Map<A, B> a) {
+  Map<B, A> b, b2;
+  b = a;
+  b2 = a;
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(Map<A, B> a) {
+  Map<B, A> b, b2;
+  b = a.cast<B, A>();
+  b2 = a.cast<B, A>();
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_assignment_needsParens() async {
     await resolveTestUnit('''
 f(A a) {
@@ -538,6 +604,32 @@
 ''');
   }
 
+  test_addExplicitCast_assignment_needsParens_all() async {
+    await resolveTestUnit('''
+f(A a) {
+  B b, b2;
+  b = a..m();
+  b2 = a..m();
+}
+class A {
+  int m() => 0;
+}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(A a) {
+  B b, b2;
+  b = (a..m()) as B;
+  b2 = (a..m()) as B;
+}
+class A {
+  int m() => 0;
+}
+class B {}
+''');
+  }
+
   test_addExplicitCast_assignment_set() async {
     await resolveTestUnit('''
 f(Set<A> a) {
@@ -557,6 +649,28 @@
 ''');
   }
 
+  test_addExplicitCast_assignment_set_all() async {
+    await resolveTestUnit('''
+f(Set<A> a) {
+  Set<B> b, b2;
+  b = a;
+  b2 = a;
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(Set<A> a) {
+  Set<B> b, b2;
+  b = a.cast<B>();
+  b2 = a.cast<B>();
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_BAD_as() async {
     await resolveTestUnit('''
 f(A a) {
@@ -597,6 +711,26 @@
 ''');
   }
 
+  test_addExplicitCast_declaration_general_all() async {
+    await resolveTestUnit('''
+f(A a) {
+  B b = a;
+  B b2 = a;
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(A a) {
+  B b = a as B;
+  B b2 = a as B;
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_declaration_list() async {
     await resolveTestUnit('''
 f(List<A> a) {
@@ -614,6 +748,26 @@
 ''');
   }
 
+  test_addExplicitCast_declaration_list_all() async {
+    await resolveTestUnit('''
+f(List<A> a) {
+  List<B> b = a.where((e) => e is B).toList();
+  List<B> b2 = a.where((e) => e is B).toList();
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(List<A> a) {
+  List<B> b = a.where((e) => e is B).cast<B>().toList();
+  List<B> b2 = a.where((e) => e is B).cast<B>().toList();
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_declaration_map() async {
     await resolveTestUnit('''
 f(Map<A, B> a) {
@@ -631,6 +785,26 @@
 ''');
   }
 
+  test_addExplicitCast_declaration_map_all() async {
+    await resolveTestUnit('''
+f(Map<A, B> a) {
+  Map<B, A> b = a;
+  Map<B, A> b2 = a;
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(Map<A, B> a) {
+  Map<B, A> b = a.cast<B, A>();
+  Map<B, A> b2 = a.cast<B, A>();
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addExplicitCast_declaration_needsParens() async {
     await resolveTestUnit('''
 f(A a) {
@@ -652,6 +826,30 @@
 ''');
   }
 
+  test_addExplicitCast_declaration_needsParens_all() async {
+    await resolveTestUnit('''
+f(A a) {
+  B b = a..m();
+  B b2 = a..m();
+}
+class A {
+  int m() => 0;
+}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(A a) {
+  B b = (a..m()) as B;
+  B b2 = (a..m()) as B;
+}
+class A {
+  int m() => 0;
+}
+class B {}
+''');
+  }
+
   test_addExplicitCast_declaration_set() async {
     await resolveTestUnit('''
 f(Set<A> a) {
@@ -669,6 +867,26 @@
 ''');
   }
 
+  test_addExplicitCast_declaration_set_all() async {
+    await resolveTestUnit('''
+f(Set<A> a) {
+  Set<B> b = a;
+  Set<B> b2 = a;
+}
+class A {}
+class B {}
+''');
+    await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
+        DartFixKind.ADD_EXPLICIT_CAST, '''
+f(Set<A> a) {
+  Set<B> b = a.cast<B>();
+  Set<B> b2 = a.cast<B>();
+}
+class A {}
+class B {}
+''');
+  }
+
   test_addFieldFormalParameters_flutter() async {
     addFlutterPackage();
     await resolveTestUnit('''
@@ -1509,6 +1727,22 @@
 ''');
   }
 
+  test_boolean_all() async {
+    await resolveTestUnit('''
+main() {
+  boolean v;
+  boolean w;
+}
+''');
+    await assertHasFixAllFix(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN,
+        DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, '''
+main() {
+  bool v;
+  bool w;
+}
+''');
+  }
+
   test_canBeNullAfterNullAware_chain() async {
     await resolveTestUnit('''
 main(x) {
@@ -4902,6 +5136,22 @@
 ''');
   }
 
+  test_isNotNull_all() async {
+    await resolveTestUnit('''
+main(p, q) {
+  p is! Null;
+  q is! Null;
+}
+''');
+    await assertHasFixAllFix(
+        HintCode.TYPE_CHECK_IS_NOT_NULL, DartFixKind.USE_NOT_EQ_NULL, '''
+main(p, q) {
+  p != null;
+  q != null;
+}
+''');
+  }
+
   test_isNull() async {
     await resolveTestUnit('''
 main(p) {
@@ -4915,6 +5165,22 @@
 ''');
   }
 
+  test_isNull_all() async {
+    await resolveTestUnit('''
+main(p, q) {
+  p is Null;
+  q is Null;
+}
+''');
+    await assertHasFixAllFix(
+        HintCode.TYPE_CHECK_IS_NULL, DartFixKind.USE_EQ_EQ_NULL, '''
+main(p, q) {
+  p == null;
+  q == null;
+}
+''');
+  }
+
   test_makeEnclosingClassAbstract_declaresAbstractMethod() async {
     await resolveTestUnit('''
 class A {
@@ -5011,6 +5277,30 @@
 ''');
   }
 
+  test_nonBoolCondition_addNotNull_all() async {
+    await resolveTestUnit('''
+main(String p, String q) {
+  if (p) {
+    print(p);
+  }
+  if (q) {
+    print(q);
+  }
+}
+''');
+    await assertHasFixAllFix(
+        StaticTypeWarningCode.NON_BOOL_CONDITION, DartFixKind.ADD_NE_NULL, '''
+main(String p, String q) {
+  if (p != null) {
+    print(p);
+  }
+  if (q != null) {
+    print(q);
+  }
+}
+''');
+  }
+
   test_removeDeadCode_condition() async {
     await resolveTestUnit('''
 main(int p) {
@@ -5110,6 +5400,30 @@
 ''');
   }
 
+  test_removeUnnecessaryCast_assignment_all() async {
+    await resolveTestUnit('''
+main(Object p, Object q) {
+  if (p is String) {
+    String v = ((p as String));
+  }
+  if (q is int) {
+    int v = ((q as int));
+  }
+}
+''');
+    await assertHasFixAllFix(
+        HintCode.UNNECESSARY_CAST, DartFixKind.REMOVE_UNNECESSARY_CAST, '''
+main(Object p, Object q) {
+  if (p is String) {
+    String v = p;
+  }
+  if (q is int) {
+    int v = q;
+  }
+}
+''');
+  }
+
   test_removeUnusedCatchClause() async {
     errorFilter = (AnalysisError error) => true;
     await resolveTestUnit('''
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
index d007bc6..0573853 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -915,6 +915,98 @@
     assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
   }
 
+  test_parameters_private() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String _field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(_field);
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String _field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Test(field: _field);
+  }
+}
+
+class Test extends StatelessWidget {
+  const Test({
+    Key key,
+    @required String field,
+  }) : _field = field, super(key: key);
+
+  final String _field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(_field);
+  }
+}
+''');
+  }
+
+  test_parameters_private_conflictWithPublic() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  int field;
+  String _field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text('$field $_field');
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  int field;
+  String _field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Test(field: field, field2: _field);
+  }
+}
+
+class Test extends StatelessWidget {
+  const Test({
+    Key key,
+    @required this.field,
+    @required String field2,
+  }) : _field = field2, super(key: key);
+
+  final int field;
+  final String _field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text('$field $_field');
+  }
+}
+''');
+  }
+
   test_parameters_readField_readLocal() async {
     addFlutterPackage();
     await indexTestUnit(r'''
@@ -989,6 +1081,95 @@
     expect(refactoring.refactoringName, 'Extract Widget');
   }
 
+  test_statements() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+Widget main() {
+  var index = 0;
+  var a = 'a $index';
+// start
+  var b = 'b $index';
+  return new Row(
+    children: <Widget>[
+      new Text(a),
+      new Text(b),
+    ],
+  );
+// end
+}
+''');
+    _createRefactoringForStartEnd();
+
+    await _assertSuccessfulRefactoring(r'''
+import 'package:flutter/material.dart';
+
+Widget main() {
+  var index = 0;
+  var a = 'a $index';
+// start
+  return new Test(index: index, a: a);
+// end
+}
+
+class Test extends StatelessWidget {
+  const Test({
+    Key key,
+    @required this.index,
+    @required this.a,
+  }) : super(key: key);
+
+  final int index;
+  final String a;
+
+  @override
+  Widget build(BuildContext context) {
+    var b = 'b $index';
+    return new Row(
+      children: <Widget>[
+        new Text(a),
+        new Text(b),
+      ],
+    );
+  }
+}
+''');
+  }
+
+  test_statements_BAD_emptySelection() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+void main() {
+// start
+// end
+}
+''');
+    _createRefactoringForStartEnd();
+
+    assertRefactoringStatus(await refactoring.checkInitialConditions(),
+        RefactoringProblemSeverity.FATAL);
+  }
+
+  test_statements_BAD_notReturnStatement() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+void main() {
+// start
+  new Text('text');
+// end
+}
+''');
+    _createRefactoringForStartEnd();
+
+    assertRefactoringStatus(await refactoring.checkInitialConditions(),
+        RefactoringProblemSeverity.FATAL);
+  }
+
   Future<void> _assertRefactoringChange(String expectedCode) async {
     SourceChange refactoringChange = await refactoring.createChange();
     this.refactoringChange = refactoringChange;
@@ -1004,18 +1185,24 @@
     await _assertRefactoringChange(expectedCode);
   }
 
-  void _createRefactoring(int offset) {
+  void _createRefactoring(int offset, int length) {
     refactoring = new ExtractWidgetRefactoring(
-        searchEngine, driver.currentSession, testUnit, offset);
+        searchEngine, driver.currentSession, testUnit, offset, length);
     refactoring.name = 'Test';
   }
 
+  void _createRefactoringForStartEnd() {
+    int offset = findOffset('// start\n') + '// start\n'.length;
+    int length = findOffset('// end') - offset;
+    _createRefactoring(offset, length);
+  }
+
   /**
    * Creates a new refactoring in [refactoring] at the offset of the given
    * [search] pattern.
    */
   void _createRefactoringForStringOffset(String search) {
     int offset = findOffset(search);
-    _createRefactoring(offset);
+    _createRefactoring(offset, 0);
   }
 }
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index bfa202a..9ba434f 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -336,6 +336,38 @@
         matches, contains(predicate((SearchMatch m) => m.element.name == 'b')));
   }
 
+  test_searchReferences_discover_owned() async {
+    var t = newFile('/test/lib/t.dart', content: '''
+import 'package:aaa/a.dart';
+int t;
+''').path;
+    var a = newFile('/aaa/lib/a.dart', content: '''
+int a;
+''').path;
+
+    var driver1 = _newDriver(packageUriResolver: _mapUriResolver('aaa', a));
+    var driver2 = _newDriver();
+
+    driver1.addFile(t);
+    driver2.addFile(a);
+
+    LibraryElement coreLib = await driver1.getLibraryByUri('dart:core');
+    ClassElement intElement = coreLib.getType('int');
+
+    var searchEngine = new SearchEngineImpl([driver1, driver2]);
+    var matches = await searchEngine.searchReferences(intElement);
+
+    void assertHasOne(String path, String name) {
+      expect(matches.where((m) {
+        var element = m.element;
+        return element.name == name && element.source.fullName == path;
+      }), hasLength(1));
+    }
+
+    assertHasOne(t, 't');
+    assertHasOne(a, 'a');
+  }
+
   test_searchTopLevelDeclarations() async {
     var a = newFile('/test/a.dart', content: '''
 class A {}
@@ -377,9 +409,9 @@
   test_searchTopLevelDeclarations_dependentPackage() async {
     var a = newFile('/a/lib/a.dart', content: '''
 class A {}
-''');
+''').path;
     var driver1 = _newDriver();
-    driver1.addFile(a.path);
+    driver1.addFile(a);
 
     // The package:b uses the class A from the package:a,
     // so it sees the declaration the element A.
@@ -387,10 +419,7 @@
 import 'package:a/a.dart';
 class B extends A {}
 ''');
-    var driver2 = _newDriver(
-        packageUriResolver: new PackageMapUriResolver(resourceProvider, {
-      'a': [a.parent]
-    }));
+    var driver2 = _newDriver(packageUriResolver: _mapUriResolver('a', a));
     driver2.addFile(b.path);
 
     while (scheduler.isAnalyzing) {
@@ -415,6 +444,12 @@
     assertHasOneElement('B');
   }
 
+  UriResolver _mapUriResolver(String packageName, String path) {
+    return new PackageMapUriResolver(resourceProvider, {
+      packageName: [resourceProvider.getFile(path).parent]
+    });
+  }
+
   AnalysisDriver _newDriver({UriResolver packageUriResolver}) {
     var resolvers = <UriResolver>[
       new DartUriResolver(sdk),
diff --git a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
index 694d46e..2b8b4ac 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
@@ -54,8 +54,8 @@
         pathContext: resourceProvider.pathContext);
     TestDriver driver = new TestDriver(resourceProvider, contextRoot);
     driver.analysisOptions.enabledPluginNames = ['pkg2'];
-    watcher.addedDriver(driver, contextRoot);
     expect(manager.addedContextRoots, isEmpty);
+    watcher.addedDriver(driver, contextRoot);
     //
     // Test to see whether the listener was configured correctly.
     //
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 92c46dc..29228c2 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 0.32.1-alpha.0
+## 0.32.1
 
 * Add the ability to specify a pathContext when creating a ContextRoot (not part
   of the officially supported API, but needed by some clients).
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 5679752..a47d7a0 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -257,6 +257,8 @@
   HintCode.DEPRECATED_MIXIN_FUNCTION,
   HintCode.DIVISION_OPTIMIZATION,
   HintCode.DUPLICATE_IMPORT,
+  HintCode.DUPLICATE_HIDDEN_NAME,
+  HintCode.DUPLICATE_SHOWN_NAME,
   HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE,
   HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE,
   HintCode.GENERIC_METHOD_COMMENT,
diff --git a/pkg/analyzer/lib/src/context/context_root.dart b/pkg/analyzer/lib/src/context/context_root.dart
index ebb208b7..744f298 100644
--- a/pkg/analyzer/lib/src/context/context_root.dart
+++ b/pkg/analyzer/lib/src/context/context_root.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
 /**
@@ -38,7 +39,7 @@
   /**
    * Initialize a newly created context root.
    */
-  ContextRoot(this.root, this.exclude, {path.Context pathContext})
+  ContextRoot(this.root, this.exclude, {@required path.Context pathContext})
       : pathContext = pathContext ?? path.context;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0563ff8..763beda 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -599,6 +599,15 @@
     _createKernelDriver();
   }
 
+  /**
+   * Return a [Future] that completes when discovery of all files that are
+   * potentially available is done, so that they are included in [knownFiles].
+   */
+  Future<void> discoverAvailableFiles() {
+    _discoverAvailableFiles();
+    return _discoverAvailableFilesTask.completer.future;
+  }
+
   @override
   void dispose() {
     _scheduler.remove(this);
@@ -669,7 +678,7 @@
   }
 
   /**
-   * Return a [Future] that completes with the list of added files that
+   * Return a [Future] that completes with the list of known files that
    * reference the given external [name].
    */
   Future<List<String>> getFilesReferencingName(String name) {
@@ -992,7 +1001,7 @@
     if (_definingClassMemberNameTasks.isNotEmpty) {
       _FilesDefiningClassMemberNameTask task =
           _definingClassMemberNameTasks.first;
-      bool isDone = await task.perform();
+      bool isDone = task.perform();
       if (isDone) {
         _definingClassMemberNameTasks.remove(task);
       }
@@ -1002,7 +1011,7 @@
     // Compute files referencing a name.
     if (_referencingNameTasks.isNotEmpty) {
       _FilesReferencingNameTask task = _referencingNameTasks.first;
-      bool isDone = await task.perform();
+      bool isDone = task.perform();
       if (isDone) {
         _referencingNameTasks.remove(task);
       }
@@ -1012,7 +1021,7 @@
     // Compute top-level declarations.
     if (_topLevelNameDeclarationsTasks.isNotEmpty) {
       _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first;
-      bool isDone = await task.perform();
+      bool isDone = task.perform();
       if (isDone) {
         _topLevelNameDeclarationsTasks.remove(task);
       }
@@ -2259,11 +2268,12 @@
   static const int _MS_WORK_INTERVAL = 5;
 
   final AnalysisDriver driver;
+  final Completer<void> completer = new Completer<void>();
 
   bool isCompleted = false;
 
   Iterator<Folder> folderIterator;
-  List<String> files;
+  List<String> files = [];
   int fileIndex = 0;
 
   _DiscoverAvailableFilesTask(this.driver);
@@ -2274,26 +2284,37 @@
    * task should continue to be run.
    */
   void perform() {
-    // Prepare the iterator of package/lib folders.
     if (folderIterator == null) {
+      files.addAll(driver.addedFiles);
+
+      // Discover SDK libraries.
+      var dartSdk = driver._sourceFactory.dartSdk;
+      if (dartSdk != null) {
+        for (var sdkLibrary in dartSdk.sdkLibraries) {
+          files.add(sdkLibrary.path);
+        }
+      }
+
+      // Discover files in package/lib folders.
       var packageMap = driver._sourceFactory.packageMap;
       if (packageMap != null) {
         folderIterator = packageMap.values.expand((f) => f).iterator;
-        files = <String>[];
       } else {
-        isCompleted = true;
-        return;
+        folderIterator = <Folder>[].iterator;
       }
     }
 
     // List each package/lib folder recursively.
     Stopwatch timer = new Stopwatch()..start();
     while (folderIterator.moveNext()) {
+      var folder = folderIterator.current;
+      _appendFilesRecursively(folder);
+
+      // Note: must check if we are exiting before calling moveNext()
+      // otherwise we will skip one iteration of the loop when we come back.
       if (timer.elapsedMilliseconds > _MS_WORK_INTERVAL) {
         return;
       }
-      var folder = folderIterator.current;
-      _appendFilesRecursively(folder);
     }
 
     // Get know files one by one.
@@ -2309,13 +2330,17 @@
     isCompleted = true;
     folderIterator = null;
     files = null;
+    completer.complete();
   }
 
   void _appendFilesRecursively(Folder folder) {
     try {
       for (var child in folder.getChildren()) {
         if (child is File) {
-          files.add(child.path);
+          var path = child.path;
+          if (AnalysisEngine.isDartFileName(path)) {
+            files.add(path);
+          }
         } else if (child is Folder) {
           _appendFilesRecursively(child);
         }
@@ -2370,7 +2395,7 @@
    * scenarios. Instead we use a fixed length of time, so we can spend less time
    * overall and keep quick enough response time.
    */
-  Future<bool> perform() async {
+  bool perform() {
     Stopwatch timer = new Stopwatch()..start();
     while (timer.elapsedMilliseconds < _MS_WORK_INTERVAL) {
       // Prepare files to check.
@@ -2405,15 +2430,18 @@
  * file.
  */
 class _FilesReferencingNameTask {
+  static const int _WORK_FILES = 100;
   static const int _MS_WORK_INTERVAL = 5;
 
   final AnalysisDriver driver;
   final String name;
   final Completer<List<String>> completer = new Completer<List<String>>();
 
+  int fileStamp = -1;
+  List<FileState> filesToCheck;
+  int filesToCheckIndex;
+
   final List<String> referencingFiles = <String>[];
-  final Set<String> checkedFiles = new Set<String>();
-  final List<String> filesToCheck = <String>[];
 
   _FilesReferencingNameTask(this.driver, this.name);
 
@@ -2427,32 +2455,34 @@
    * scenarios. Instead we use a fixed length of time, so we can spend less time
    * overall and keep quick enough response time.
    */
-  Future<bool> perform() async {
-    Stopwatch timer = new Stopwatch()..start();
-    while (timer.elapsedMilliseconds < _MS_WORK_INTERVAL) {
-      // Prepare files to check.
-      if (filesToCheck.isEmpty) {
-        Set<String> newFiles = driver.addedFiles.difference(checkedFiles);
-        filesToCheck.addAll(newFiles);
-      }
-
-      // If no more files to check, complete and done.
-      if (filesToCheck.isEmpty) {
-        completer.complete(referencingFiles);
-        return true;
-      }
-
-      // Check the next file.
-      String path = filesToCheck.removeLast();
-      FileState file = driver._fsState.getFileForPath(path);
-      if (file.referencedNames.contains(name)) {
-        referencingFiles.add(path);
-      }
-      checkedFiles.add(path);
+  bool perform() {
+    if (driver._fsState.fileStamp != fileStamp) {
+      filesToCheck = null;
+      referencingFiles.clear();
     }
 
-    // We're not done yet.
-    return false;
+    // Prepare files to check.
+    if (filesToCheck == null) {
+      fileStamp = driver._fsState.fileStamp;
+      filesToCheck = driver._fsState.knownFiles;
+      filesToCheckIndex = 0;
+    }
+
+    Stopwatch timer = new Stopwatch()..start();
+    while (filesToCheckIndex < filesToCheck.length) {
+      if (filesToCheckIndex % _WORK_FILES == 0 &&
+          timer.elapsedMilliseconds > _MS_WORK_INTERVAL) {
+        return false;
+      }
+      FileState file = filesToCheck[filesToCheckIndex++];
+      if (file.referencedNames.contains(name)) {
+        referencingFiles.add(file.path);
+      }
+    }
+
+    // If no more files to check, complete and done.
+    completer.complete(referencingFiles);
+    return true;
   }
 }
 
@@ -2478,7 +2508,7 @@
    * return `true` to indicate that the task is done, return `false` to indicate
    * that the task should continue to be run.
    */
-  Future<bool> perform() async {
+  bool perform() {
     // Prepare files to check.
     if (filesToCheck.isEmpty) {
       filesToCheck.addAll(driver.addedFiles.difference(checkedFiles));
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index d775100..530e205 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -723,6 +723,11 @@
   final Set<String> knownFilePaths = new Set<String>();
 
   /**
+   * All known files.
+   */
+  final List<FileState> knownFiles = [];
+
+  /**
    * Mapping from a path to the flag whether there is a URI for the path.
    */
   final Map<String, bool> _hasUriForPath = {};
@@ -743,6 +748,11 @@
   final Map<FileState, List<FileState>> _partToLibraries = {};
 
   /**
+   * The value of this field is incremented when the set of files is updated.
+   */
+  int fileStamp = 0;
+
+  /**
    * The [FileState] instance that correspond to an unresolved URI.
    */
   FileState _unresolvedFile;
@@ -770,12 +780,6 @@
     _testView = new FileSystemStateTestView(this);
   }
 
-  /**
-   * Return the known files.
-   */
-  List<FileState> get knownFiles =>
-      _pathToFiles.values.map((files) => files.first).toList();
-
   @visibleForTesting
   FileSystemStateTestView get test => _testView;
 
@@ -912,6 +916,7 @@
     markFileForReading(path);
     _uriToFile.clear();
     knownFilePaths.clear();
+    knownFiles.clear();
     _pathToFiles.clear();
     _pathToCanonicalFile.clear();
     _partToLibraries.clear();
@@ -921,8 +926,10 @@
     var files = _pathToFiles[path];
     if (files == null) {
       knownFilePaths.add(path);
+      knownFiles.add(file);
       files = <FileState>[];
       _pathToFiles[path] = files;
+      fileStamp++;
     }
     files.add(file);
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index b3b5230..0e6d519 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -334,6 +334,7 @@
       verifier.addImports(unit);
       _usedImportedElementsList.forEach(verifier.removeUsedElements);
       verifier.generateDuplicateImportHints(errorReporter);
+      verifier.generateDuplicateShownHiddenNameHints(errorReporter);
       verifier.generateUnusedImportHints(errorReporter);
       verifier.generateUnusedShownNameHints(errorReporter);
     }
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index a54df1f..1212bdc 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -113,11 +114,9 @@
    * declarations.
    *
    * The path of each file with at least one declaration is added to [files].
-   * The list is for searched, there might be duplicates, but this is OK,
-   * we just want reduce amount of data, not to make it absolute minimum.
    */
   Future<List<Declaration>> declarations(
-      RegExp regExp, int maxResults, List<String> files,
+      RegExp regExp, int maxResults, LinkedHashSet<String> files,
       {String onlyForFile}) async {
     List<Declaration> declarations = <Declaration>[];
 
@@ -139,11 +138,16 @@
       }
     }
 
+    await _driver.discoverAvailableFiles();
+
     try {
-      for (String path in _driver.addedFiles) {
+      for (String path in _driver.knownFiles) {
         if (onlyForFile != null && path != onlyForFile) {
           continue;
         }
+        if (files.contains(path)) {
+          continue;
+        }
 
         FileState file = _driver.fsState.getFileForPath(path);
         int fileIndex;
@@ -166,6 +170,7 @@
             fileIndex = files.length;
             files.add(file.path);
           }
+
           var location = file.lineInfo.getLocation(offset);
           declarations.add(new Declaration(
               fileIndex,
@@ -279,7 +284,8 @@
   /**
    * Returns references to the [element].
    */
-  Future<List<SearchResult>> references(Element element) async {
+  Future<List<SearchResult>> references(
+      Element element, SearchedFiles searchedFiles) async {
     if (element == null) {
       return const <SearchResult>[];
     }
@@ -289,19 +295,19 @@
         kind == ElementKind.CONSTRUCTOR ||
         kind == ElementKind.FUNCTION_TYPE_ALIAS ||
         kind == ElementKind.SETTER) {
-      return _searchReferences(element);
+      return _searchReferences(element, searchedFiles);
     } else if (kind == ElementKind.COMPILATION_UNIT) {
       return _searchReferences_CompilationUnit(element);
     } else if (kind == ElementKind.GETTER) {
-      return _searchReferences_Getter(element);
+      return _searchReferences_Getter(element, searchedFiles);
     } else if (kind == ElementKind.FIELD ||
         kind == ElementKind.TOP_LEVEL_VARIABLE) {
-      return _searchReferences_Field(element);
+      return _searchReferences_Field(element, searchedFiles);
     } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) {
       if (element.enclosingElement is ExecutableElement) {
         return _searchReferences_Local(element, (n) => n is Block);
       }
-      return _searchReferences_Function(element);
+      return _searchReferences_Function(element, searchedFiles);
     } else if (kind == ElementKind.IMPORT) {
       return _searchReferences_Import(element);
     } else if (kind == ElementKind.LABEL ||
@@ -310,7 +316,7 @@
     } else if (kind == ElementKind.LIBRARY) {
       return _searchReferences_Library(element);
     } else if (kind == ElementKind.PARAMETER) {
-      return _searchReferences_Parameter(element);
+      return _searchReferences_Parameter(element, searchedFiles);
     } else if (kind == ElementKind.PREFIX) {
       return _searchReferences_Prefix(element);
     } else if (kind == ElementKind.TYPE_PARAMETER) {
@@ -322,13 +328,18 @@
 
   /**
    * Returns subtypes of the given [type].
+   *
+   * The [searchedFiles] are consulted to see if a file is "owned" by this
+   * [Search] object, so should be only searched by it to avoid duplicate
+   * results; and updated to take ownership if the file is not owned yet.
    */
-  Future<List<SearchResult>> subTypes(ClassElement type) async {
+  Future<List<SearchResult>> subTypes(
+      ClassElement type, SearchedFiles searchedFiles) async {
     if (type == null) {
       return const <SearchResult>[];
     }
     List<SearchResult> results = <SearchResult>[];
-    await _addResults(results, type, const {
+    await _addResults(results, type, searchedFiles, const {
       IndexRelationKind.IS_EXTENDED_BY: SearchResultKind.REFERENCE,
       IndexRelationKind.IS_MIXED_IN_BY: SearchResultKind.REFERENCE,
       IndexRelationKind.IS_IMPLEMENTED_BY: SearchResultKind.REFERENCE
@@ -390,7 +401,8 @@
       }
     }
 
-    for (FileState file in _driver.fsState.knownFiles) {
+    List<FileState> knownFiles = _driver.fsState.knownFiles.toList();
+    for (FileState file in knownFiles) {
       UnitElementResult unitResult = await _driver.getUnitElement(file.path);
       if (unitResult != null) {
         CompilationUnitElement unitElement = unitResult.element;
@@ -408,7 +420,8 @@
   /**
    * Returns unresolved references to the given [name].
    */
-  Future<List<SearchResult>> unresolvedMemberReferences(String name) async {
+  Future<List<SearchResult>> unresolvedMemberReferences(
+      String name, SearchedFiles searchedFiles) async {
     if (name == null) {
       return const <SearchResult>[];
     }
@@ -419,10 +432,11 @@
     // Check the index of every file that references the element name.
     List<SearchResult> results = [];
     for (String file in files) {
-      AnalysisDriverUnitIndex index = await _driver.getIndex(file);
-      if (index != null) {
-        _IndexRequest request = new _IndexRequest(index);
-        var fileResults = await request.getUnresolvedMemberReferences(
+      if (searchedFiles.add(file, this)) {
+        AnalysisDriverUnitIndex index = await _driver.getIndex(file);
+        if (index != null) {
+          _IndexRequest request = new _IndexRequest(index);
+          var fileResults = await request.getUnresolvedMemberReferences(
             name,
             const {
               IndexRelationKind.IS_READ_BY: SearchResultKind.READ,
@@ -430,15 +444,20 @@
               IndexRelationKind.IS_READ_WRITTEN_BY: SearchResultKind.READ_WRITE,
               IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
             },
-            () => _getUnitElement(file));
-        results.addAll(fileResults);
+            () => _getUnitElement(file),
+          );
+          results.addAll(fileResults);
+        }
       }
     }
 
     return results;
   }
 
-  Future<Null> _addResults(List<SearchResult> results, Element element,
+  Future<Null> _addResults(
+      List<SearchResult> results,
+      Element element,
+      SearchedFiles searchedFiles,
       Map<IndexRelationKind, SearchResultKind> relationToResultKind) async {
     // Prepare the element name.
     String name = element.displayName;
@@ -462,14 +481,16 @@
       }
     } else {
       files = await _driver.getFilesReferencingName(name);
-      if (!files.contains(path) && _driver.addedFiles.contains(path)) {
+      if (!files.contains(path)) {
         files.add(path);
       }
     }
 
     // Check the index of every file that references the element name.
     for (String file in files) {
-      await _addResultsInFile(results, element, relationToResultKind, file);
+      if (searchedFiles.add(file, this)) {
+        await _addResultsInFile(results, element, relationToResultKind, file);
+      }
     }
   }
 
@@ -498,9 +519,10 @@
     return result?.element;
   }
 
-  Future<List<SearchResult>> _searchReferences(Element element) async {
+  Future<List<SearchResult>> _searchReferences(
+      Element element, SearchedFiles searchedFiles) async {
     List<SearchResult> results = <SearchResult>[];
-    await _addResults(results, element,
+    await _addResults(results, element, searchedFiles,
         const {IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE});
     return results;
   }
@@ -516,7 +538,8 @@
 
     // Check every file that references the given path.
     List<SearchResult> results = <SearchResult>[];
-    for (FileState file in _driver.fsState.knownFiles) {
+    List<FileState> knownFiles = _driver.fsState.knownFiles.toList();
+    for (FileState file in knownFiles) {
       for (FileState referencedFile in file.directReferencedFiles) {
         if (referencedFile.path == path) {
           await _addResultsInFile(
@@ -533,35 +556,36 @@
   }
 
   Future<List<SearchResult>> _searchReferences_Field(
-      PropertyInducingElement field) async {
+      PropertyInducingElement field, SearchedFiles searchedFiles) async {
     List<SearchResult> results = <SearchResult>[];
     PropertyAccessorElement getter = field.getter;
     PropertyAccessorElement setter = field.setter;
     if (!field.isSynthetic) {
-      await _addResults(results, field, const {
+      await _addResults(results, field, searchedFiles, const {
         IndexRelationKind.IS_WRITTEN_BY: SearchResultKind.WRITE,
         IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE
       });
     }
     if (getter != null) {
-      await _addResults(results, getter, const {
+      await _addResults(results, getter, searchedFiles, const {
         IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.READ,
         IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
       });
     }
     if (setter != null) {
-      await _addResults(results, setter,
+      await _addResults(results, setter, searchedFiles,
           const {IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.WRITE});
     }
     return results;
   }
 
-  Future<List<SearchResult>> _searchReferences_Function(Element element) async {
+  Future<List<SearchResult>> _searchReferences_Function(
+      Element element, SearchedFiles searchedFiles) async {
     if (element is Member) {
       element = (element as Member).baseElement;
     }
     List<SearchResult> results = <SearchResult>[];
-    await _addResults(results, element, const {
+    await _addResults(results, element, searchedFiles, const {
       IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
       IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
     });
@@ -569,9 +593,9 @@
   }
 
   Future<List<SearchResult>> _searchReferences_Getter(
-      PropertyAccessorElement getter) async {
+      PropertyAccessorElement getter, SearchedFiles searchedFiles) async {
     List<SearchResult> results = <SearchResult>[];
-    await _addResults(results, getter, const {
+    await _addResults(results, getter, searchedFiles, const {
       IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
       IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION
     });
@@ -661,14 +685,14 @@
   }
 
   Future<List<SearchResult>> _searchReferences_Parameter(
-      ParameterElement parameter) async {
+      ParameterElement parameter, SearchedFiles searchedFiles) async {
     List<SearchResult> results = <SearchResult>[];
     results.addAll(await _searchReferences_Local(parameter, (AstNode node) {
       AstNode parent = node.parent;
       return parent is ClassDeclaration || parent is CompilationUnit;
     }));
     if (parameter.isOptional) {
-      results.addAll(await _searchReferences(parameter));
+      results.addAll(await _searchReferences(parameter, searchedFiles));
     }
     return results;
   }
@@ -696,6 +720,28 @@
 }
 
 /**
+ * Container that keeps track of file owners.
+ */
+class SearchedFiles {
+  final Map<String, Search> owners = {};
+
+  bool add(String path, Search search) {
+    var owner = owners[path];
+    if (owner == null) {
+      owners[path] = search;
+      return true;
+    }
+    return identical(owner, search);
+  }
+
+  void ownAdded(Search search) {
+    for (var path in search._driver.addedFiles) {
+      owners[path] = search;
+    }
+  }
+}
+
+/**
  * A single search result.
  */
 class SearchResult {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 822d245..883fb08 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4411,8 +4411,7 @@
   @override
   FunctionType get type {
     if (_kernel != null || serializedExecutable != null) {
-      _type ??= new FunctionTypeImpl.elementWithNameAndArgs(
-          this, null, allEnclosingTypeParameterTypes, false);
+      _type ??= new FunctionTypeImpl(this);
     }
     return _type;
   }
@@ -5155,8 +5154,7 @@
 
   @override
   FunctionType get type {
-    return _type ??=
-        new FunctionTypeImpl.elementWithNameAndArgs(this, null, null, false);
+    return _type ??= new FunctionTypeImpl(this);
   }
 
   @override
@@ -5299,8 +5297,7 @@
 
   @override
   FunctionType get type {
-    _type ??= new FunctionTypeImpl.elementWithNameAndArgs(
-        this, null, allEnclosingTypeParameterTypes, false);
+    _type ??= new FunctionTypeImpl(this);
     return _type;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 3ccdac9..e0a73ba 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -139,10 +139,6 @@
       TypeParameterElement.EMPTY_LIST;
 
   @override
-  List<TypeParameterElement> get _explicitTypeParameters =>
-      TypeParameterElement.EMPTY_LIST;
-
-  @override
   bool get _isInstantiated => false;
 
   @override
@@ -193,12 +189,6 @@
   FunctionTypeImpl substitute3(List<DartType> argumentTypes) => this;
 
   @override
-  FunctionType substitute4(
-      List<TypeParameterElement> typeParameters, List<DartType> typeArguments) {
-    return this;
-  }
-
-  @override
   void _forEachParameterType(
       ParameterKind kind, callback(String name, DartType type)) {
     // There are no parameters.
@@ -265,8 +255,7 @@
 
   DeferredFunctionTypeImpl(this._computeElement, String name,
       List<DartType> typeArguments, bool isInstantiated)
-      : super._(
-            null, name, null, typeArguments, null, null, null, isInstantiated);
+      : super._(null, name, null, typeArguments, null, null, isInstantiated);
 
   @override
   FunctionTypedElement get element {
@@ -359,12 +348,6 @@
   List<TypeParameterElement> _typeParameters;
 
   /**
-   * The list of [typeParameters], if there is no element from which they can be
-   * computed, or `null` if they should be computed when necessary.
-   */
-  final List<TypeParameterElement> _explicitTypeParameters;
-
-  /**
    * The return type of the function, or `null` if the return type should be
    * accessed through the element.
    */
@@ -394,27 +377,24 @@
    * [element], and also initialize [typeArguments] to match the
    * [typeParameters], which permits later substitution.
    */
-  FunctionTypeImpl(FunctionTypedElement element,
-      [List<FunctionTypeAliasElement> prunedTypedefs])
-      : this._(element, null, prunedTypedefs, null, null, null, null, false);
-
-  /**
-   * Initialize a newly created function type to be declared by the given
-   * [element], with the given [name] and [typeArguments].
-   */
-  FunctionTypeImpl.elementWithNameAndArgs(Element element, String name,
-      List<DartType> typeArguments, bool isInstantiated)
-      : this._(element, name, null, typeArguments, null, null, null,
-            isInstantiated);
+  factory FunctionTypeImpl(FunctionTypedElement element) {
+    if (element is FunctionTypeAliasElement) {
+      throw new StateError('Use FunctionTypeImpl.forTypedef for typedefs');
+    }
+    return new FunctionTypeImpl._(element, null, null, null, null, null, false);
+  }
 
   /**
    * Initialize a newly created function type to be declared by the given
    * [element].
+   *
+   * If [typeArguments] are provided, they are used to instantiate the typedef.
    */
-  FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
-      [List<FunctionTypeAliasElement> prunedTypedefs])
-      : this._(element, element?.name, prunedTypedefs, null, null, null, null,
-            false);
+  factory FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
+      {List<DartType> typeArguments}) {
+    return new FunctionTypeImpl._(element, element?.name, null, typeArguments,
+        null, null, typeArguments != null);
+  }
 
   /**
    * Initialize a newly created function type that is semantically the same as
@@ -482,11 +462,10 @@
       String name,
       this.prunedTypedefs,
       this._typeArguments,
-      this._explicitTypeParameters,
       this._returnType,
       this._parameters,
       this._isInstantiated)
-      : _typeParameters = _explicitTypeParameters,
+      : _typeParameters = null,
         super(element, name);
 
   /**
@@ -944,7 +923,7 @@
     newTypeArgs.addAll(argumentTypes);
 
     return new FunctionTypeImpl._(element, name, prunedTypedefs, newTypeArgs,
-        _explicitTypeParameters, _returnType, _parameters, true);
+        _returnType, _parameters, true);
   }
 
   @override
@@ -1023,8 +1002,8 @@
       List<DartType> typeArgs = typeArguments
           .map((DartType t) => (t as TypeImpl).pruned(prune))
           .toList(growable: false);
-      return new FunctionTypeImpl._(element, name, prune, typeArgs,
-          _explicitTypeParameters, _returnType, _parameters, _isInstantiated);
+      return new FunctionTypeImpl._(element, name, prune, typeArgs, _returnType,
+          _parameters, _isInstantiated);
     }
   }
 
@@ -1046,8 +1025,8 @@
     }
     List<DartType> typeArgs =
         TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
-    return new FunctionTypeImpl._(element, name, prune, typeArgs,
-        _explicitTypeParameters, _returnType, _parameters, _isInstantiated);
+    return new FunctionTypeImpl._(element, name, prune, typeArgs, _returnType,
+        _parameters, _isInstantiated);
   }
 
   @override
@@ -1055,20 +1034,6 @@
       substitute2(argumentTypes, typeArguments);
 
   /**
-   * Perform simple substitution of [typeParameters] with [typeArguments].
-   */
-  FunctionType substitute4(
-      List<TypeParameterElement> typeParameters, List<DartType> typeArguments) {
-    if (typeArguments.length != typeParameters.length) {
-      throw new ArgumentError(
-          "typeArguments.length (${typeArguments.length}) != '"
-          "'typeParameters.length (${typeParameters.length})");
-    }
-    return new FunctionTypeImpl._(element, name, [], typeArguments,
-        typeParameters, _returnType, _parameters, true);
-  }
-
-  /**
    * Invokes [callback] for each parameter of [kind] with the parameter's [name]
    * and type after any type parameters have been applied.
    */
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 8d2ab0f..560a1e5 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -132,6 +132,22 @@
       correction: "Try removing all but one import of the library.");
 
   /**
+   * Duplicate hidden names.
+   */
+  static const HintCode DUPLICATE_HIDDEN_NAME =
+      const HintCode('DUPLICATE_HIDDEN_NAME', "Duplicate hidden name.",
+          correction: "Try removing the repeated name from the list of hidden "
+              "members.");
+
+  /**
+   * Duplicate shown names.
+   */
+  static const HintCode DUPLICATE_SHOWN_NAME =
+      const HintCode('DUPLICATE_SHOWN_NAME', "Duplicate shown name.",
+          correction: "Try removing the repeated name from the list of shown "
+              "members.");
+
+  /**
    * It is a bad practice for a source file in a package "lib" directory
    * hierarchy to traverse outside that directory hierarchy. For example, a
    * source file in the "lib" directory should not contain a directive such as
diff --git a/pkg/analyzer/lib/src/fasta/analyzer_expression_generator.dart b/pkg/analyzer/lib/src/fasta/analyzer_expression_generator.dart
new file mode 100644
index 0000000..f37feab
--- /dev/null
+++ b/pkg/analyzer/lib/src/fasta/analyzer_expression_generator.dart
@@ -0,0 +1,531 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/ast_factory.dart';
+import 'package:analyzer/src/fasta/ast_building_factory.dart';
+import 'package:front_end/src/fasta/kernel/expression_generator.dart' as fasta;
+import 'package:front_end/src/fasta/kernel/expression_generator_helper.dart';
+import 'package:front_end/src/fasta/kernel/forest.dart' as fasta;
+import 'package:front_end/src/scanner/token.dart';
+import 'package:kernel/ast.dart' as kernel
+    show DartType, Initializer, Member, Name, Procedure;
+
+class AnalyzerDeferredAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.DeferredAccessGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final fasta.PrefixBuilder builder;
+  final fasta.Generator<Expression, Statement, Arguments> generator;
+
+  AnalyzerDeferredAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.builder,
+      this.generator)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() => generator.buildSimpleRead();
+}
+
+abstract class AnalyzerExpressionGenerator
+    implements fasta.Generator<Expression, Statement, Arguments> {
+  final ExpressionGeneratorHelper<Expression, Statement, Arguments> helper;
+
+  final AstFactory astFactory;
+
+  AnalyzerExpressionGenerator(this.helper, this.astFactory);
+
+  fasta.Forest<Expression, Statement, Token, Arguments> get forest =>
+      helper.forest;
+
+  @override
+// TODO: implement isInitializer
+  bool get isInitializer => throw new UnimplementedError();
+
+  @override
+// TODO: implement isThisPropertyAccess
+  bool get isThisPropertyAccess => throw new UnimplementedError();
+
+  @override
+// TODO: implement plainNameForRead
+  String get plainNameForRead => throw new UnimplementedError();
+
+  @override
+// TODO: implement plainNameForWrite
+  String get plainNameForWrite => throw new UnimplementedError();
+
+  @override
+// TODO: implement uri
+  Uri get uri => throw new UnimplementedError();
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext}) {
+    // TODO(brianwilkerson) Figure out how to get the token for the operator.
+    return astFactory.assignmentExpression(buildSimpleRead(), null, value);
+  }
+
+  @override
+  Expression buildCompoundAssignment(
+      kernel.Name binaryOperator, Expression value,
+      {int offset,
+      bool voidContext,
+      kernel.Procedure interfaceTarget,
+      bool isPreIncDec}) {
+    // TODO(brianwilkerson) Figure out how to get the token for the operator.
+    return astFactory.assignmentExpression(buildSimpleRead(), null, value);
+  }
+
+  @override
+  kernel.Initializer buildFieldInitializer(Map<String, int> initializedFields) {
+    // TODO: implement buildFieldInitializer
+    throw new UnimplementedError();
+  }
+
+  /// For most accessors, the AST structure will be the same whether the result
+  /// is being used for access or modification.
+  Expression buildForEffect() => buildSimpleRead();
+
+  @override
+  Expression buildNullAwareAssignment(
+      Expression value, kernel.DartType type, int offset,
+      {bool voidContext}) {
+    // TODO(brianwilkerson) Figure out how to get the token for the operator.
+    // TODO(brianwilkerson) Capture the type information?
+    return astFactory.assignmentExpression(buildSimpleRead(), null, value);
+  }
+
+  @override
+  Expression buildPostfixIncrement(kernel.Name binaryOperator,
+      {int offset, bool voidContext, kernel.Procedure interfaceTarget}) {
+    // TODO(brianwilkerson) Figure out how to get the token for the operator.
+    return astFactory.postfixExpression(buildSimpleRead(), null);
+  }
+
+  @override
+  Expression buildPrefixIncrement(kernel.Name binaryOperator,
+      {int offset, bool voidContext, kernel.Procedure interfaceTarget}) {
+    // TODO(brianwilkerson) Figure out how to get the token for the operator.
+    return astFactory.prefixExpression(null, buildSimpleRead());
+  }
+
+  @override
+  buildPropertyAccess(fasta.IncompleteSendGenerator send, int operatorOffset,
+      bool isNullAware) {
+    // TODO: implement buildPropertyAccess
+//    return astFactory.propertyAccess(buildSimpleRead(), null, null);
+    throw new UnimplementedError();
+  }
+
+  @override
+  buildThrowNoSuchMethodError(Expression receiver, Arguments arguments,
+      {bool isSuper,
+      bool isGetter,
+      bool isSetter,
+      bool isStatic,
+      String name,
+      int offset,
+      /*LocatedMessage*/ argMessage}) {
+    // TODO: implement buildThrowNoSuchMethodError
+    throw new UnimplementedError();
+  }
+
+  @override
+  kernel.DartType buildTypeWithBuiltArguments(List<kernel.DartType> arguments,
+      {bool nonInstanceAccessIsError: false}) {
+    // TODO: implement buildTypeWithBuiltArguments
+    throw new UnimplementedError();
+  }
+
+  @override
+  doInvocation(int offset, Arguments arguments) {
+    // TODO: implement doInvocation
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression makeInvalidRead() {
+    // TODO: implement makeInvalidRead
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression makeInvalidWrite(Expression value) {
+    // TODO: implement makeInvalidWrite
+    throw new UnimplementedError();
+  }
+
+  @override
+  void printOn(StringSink sink) {
+    // TODO: implement printOn
+    throw new UnimplementedError();
+  }
+
+  @override
+  T storeOffset<T>(T node, int offset) {
+    // TODO: implement storeOffset
+    throw new UnimplementedError();
+  }
+}
+
+class AnalyzerIndexedAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.IndexedAccessGenerator<Expression, Statement, Arguments> {
+  /// The expression computing the object on which the index operation will be
+  /// invoked.
+  final Expression target;
+
+  /// The left bracket.
+  final Token leftBracket;
+
+  /// The expression computing the argument for the index operation.
+  final Expression index;
+
+  /// The right bracket.
+  final Token rightBracket;
+
+  /// Initialize a newly created generator to have the given helper.
+  AnalyzerIndexedAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.target,
+      this.leftBracket,
+      this.index,
+      this.rightBracket)
+      : super(helper, astFactory);
+
+  @override
+  Token get token => leftBracket;
+
+  @override
+  Expression buildSimpleRead() => astFactory.indexExpressionForTarget(
+      target, leftBracket, index, rightBracket);
+}
+
+class AnalyzerLargeIntAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.LargeIntAccessGenerator<Expression, Statement, Arguments> {
+  final Token token;
+
+  AnalyzerLargeIntAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() => astFactory.integerLiteral(token, null);
+}
+
+class AnalyzerLoadLibraryGenerator extends AnalyzerExpressionGenerator
+    with fasta.LoadLibraryGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final fasta.LoadLibraryBuilder builder;
+
+  AnalyzerLoadLibraryGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.builder)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() {
+    // TODO: implement buildSimpleRead
+    throw new UnimplementedError();
+  }
+}
+
+class AnalyzerNullAwarePropertyAccessGenerator
+    extends AnalyzerExpressionGenerator
+    with
+        fasta.NullAwarePropertyAccessGenerator<Expression, Statement,
+            Arguments> {
+  final Expression target;
+  final Token operator;
+  final SimpleIdentifier propertyName;
+
+  AnalyzerNullAwarePropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.target,
+      this.operator,
+      this.propertyName)
+      : super(helper, astFactory);
+
+  @override
+  Token get token => operator;
+
+  @override
+  Expression buildSimpleRead() =>
+      astFactory.propertyAccess(target, operator, propertyName);
+}
+
+class AnalyzerPropertyAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.PropertyAccessGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final Expression receiver;
+  final kernel.Name name;
+  final kernel.Member getter;
+  final kernel.Member setter;
+
+  AnalyzerPropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.receiver,
+      this.name,
+      this.getter,
+      this.setter)
+      : super(helper, astFactory);
+
+  @override
+  // TODO(brianwilkerson) Figure out how to get the property name token (or node).
+  Expression buildSimpleRead() =>
+      astFactory.propertyAccess(receiver, token, null);
+}
+
+class AnalyzerReadOnlyAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.ReadOnlyAccessGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final Expression expression;
+  final String plainNameForRead;
+
+  AnalyzerReadOnlyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.expression,
+      this.plainNameForRead)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() {
+    // TODO: implement buildSimpleRead
+    throw new UnimplementedError();
+  }
+}
+
+class AnalyzerStaticAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.StaticAccessGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final kernel.Member getter;
+  final kernel.Member setter;
+
+  AnalyzerStaticAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.getter,
+      this.setter)
+      : super(helper, astFactory);
+
+  @override
+  kernel.Member get readTarget {
+    // TODO: implement readTarget
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression buildSimpleRead() {
+    // TODO: implement buildSimpleRead
+    throw new UnimplementedError();
+  }
+}
+
+class AnalyzerSuperIndexedAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.SuperIndexedAccessGenerator<Expression, Statement, Arguments> {
+  /// The expression computing the object on which the index operation will be
+  /// invoked.
+  final Expression target;
+
+  /// The left bracket.
+  final Token leftBracket;
+
+  /// The expression computing the argument for the index operation.
+  final Expression index;
+
+  /// The right bracket.
+  final Token rightBracket;
+
+  /// Initialize a newly created generator to have the given helper.
+  AnalyzerSuperIndexedAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.target,
+      this.leftBracket,
+      this.index,
+      this.rightBracket)
+      : super(helper, astFactory);
+
+  @override
+  Token get token => leftBracket;
+
+  @override
+  Expression buildSimpleRead() => astFactory.indexExpressionForTarget(
+      target, leftBracket, index, rightBracket);
+}
+
+class AnalyzerSuperPropertyAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.SuperPropertyAccessGenerator<Expression, Statement, Arguments> {
+  /// The `super` keyword.
+  Token superKeyword;
+
+  /// The `.` or `?.` operator.
+  Token operator;
+
+  /// The name of the property being accessed,
+  SimpleIdentifier propertyName;
+
+  AnalyzerSuperPropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.superKeyword,
+      this.operator,
+      this.propertyName)
+      : super(helper, astFactory);
+
+  @override
+  Token get token => operator;
+
+  @override
+  Expression buildSimpleRead() => astFactory.propertyAccess(
+      astFactory.superExpression(superKeyword), operator, propertyName);
+}
+
+class AnalyzerThisIndexedAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.ThisIndexedAccessGenerator<Expression, Statement, Arguments> {
+  /// The expression computing the object on which the index operation will be
+  /// invoked.
+  final Expression target;
+
+  /// The left bracket.
+  final Token leftBracket;
+
+  /// The expression computing the argument for the index operation.
+  final Expression index;
+
+  /// The right bracket.
+  final Token rightBracket;
+
+  /// Initialize a newly created generator to have the given helper.
+  AnalyzerThisIndexedAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.target,
+      this.leftBracket,
+      this.index,
+      this.rightBracket)
+      : super(helper, astFactory);
+
+  @override
+  Token get token => leftBracket;
+
+  @override
+  Expression buildSimpleRead() => astFactory.indexExpressionForTarget(
+      target, leftBracket, index, rightBracket);
+}
+
+class AnalyzerThisPropertyAccessGenerator extends AnalyzerExpressionGenerator
+    with fasta.ThisPropertyAccessGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final kernel.Name name;
+  final kernel.Member getter;
+  final kernel.Member setter;
+
+  AnalyzerThisPropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.name,
+      this.getter,
+      this.setter)
+      : super(helper, astFactory);
+
+  @override
+  // TODO(brianwilkerson) Figure out how to get the token (or node) for `this`.
+  // TODO(brianwilkerson) Figure out how to get the property name token (or node).
+  Expression buildSimpleRead() => astFactory.propertyAccess(null, token, null);
+}
+
+class AnalyzerTypeUseGenerator extends AnalyzerExpressionGenerator
+    with fasta.TypeUseGenerator<Expression, Statement, Arguments> {
+  final Token token;
+  final fasta.PrefixBuilder prefix;
+  final int declarationReferenceOffset;
+  final fasta.TypeDeclarationBuilder declaration;
+  final String plainNameForRead;
+
+  AnalyzerTypeUseGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.token,
+      this.prefix,
+      this.declarationReferenceOffset,
+      this.declaration,
+      this.plainNameForRead)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() {
+    // TODO: implement buildSimpleRead
+    throw new UnimplementedError();
+  }
+}
+
+class AnalyzerUnlinkedNameGenerator extends AnalyzerExpressionGenerator
+    with fasta.UnlinkedGenerator<Expression, Statement, Arguments> {
+  @override
+  final Token token;
+
+  @override
+  final fasta.UnlinkedDeclaration declaration;
+
+  AnalyzerUnlinkedNameGenerator(
+      ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
+      AstFactory astFactory,
+      this.token,
+      this.declaration)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() => astFactory.simpleIdentifier(token);
+}
+
+class AnalyzerUnresolvedNameGenerator extends AnalyzerExpressionGenerator
+    with
+        fasta.ErroneousExpressionGenerator<Expression, Statement, Arguments>,
+        fasta.UnresolvedNameGenerator<Expression, Statement, Arguments> {
+  @override
+  final Token token;
+
+  @override
+  final kernel.Name name;
+
+  AnalyzerUnresolvedNameGenerator(
+      ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
+      AstFactory astFactory,
+      this.token,
+      this.name)
+      : super(helper, astFactory);
+
+  @override
+  Expression buildSimpleRead() => astFactory.simpleIdentifier(token);
+}
+
+class AnalyzerVariableUseGenerator extends AnalyzerExpressionGenerator
+    with fasta.VariableUseGenerator<Expression, Statement, Arguments> {
+  final Token nameToken;
+
+  AnalyzerVariableUseGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      AstFactory astFactory,
+      this.nameToken)
+      : super(helper, astFactory);
+
+  @override
+  Token get token => nameToken;
+
+  @override
+  Expression buildSimpleRead() => astFactory.simpleIdentifier(nameToken);
+}
diff --git a/pkg/analyzer/lib/src/fasta/ast_body_builder.dart b/pkg/analyzer/lib/src/fasta/ast_body_builder.dart
index e5e7442..f79a164 100644
--- a/pkg/analyzer/lib/src/fasta/ast_body_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_body_builder.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart' show Expression, Statement;
 import 'package:analyzer/src/fasta/ast_building_factory.dart'
-    show AstBuildingForest;
+    show Arguments, AstBuildingForest;
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:front_end/src/fasta/kernel/body_builder.dart' show BodyBuilder;
 import 'package:front_end/src/fasta/kernel/kernel_builder.dart'
@@ -14,7 +14,10 @@
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
 
-class AstBodyBuilder extends BodyBuilder<Expression, Statement, dynamic> {
+export 'package:front_end/src/fasta/kernel/unlinked_scope.dart'
+    show UnlinkedScope;
+
+class AstBodyBuilder extends BodyBuilder<Expression, Statement, Arguments> {
   @override
   final AstBuildingForest forest;
 
@@ -40,8 +43,7 @@
   }
 
   @override
-  void printEvent(String name) {
-    // TODO(scheglov): Call of super is commented out to prevent spamming.
-//    super.printEvent(name);
+  void logEvent(String name) {
+    throw "Parser event '$name' not implemented";
   }
 }
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index a706a0d..1d28718 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -48,22 +48,18 @@
         messageTypedefNotFunction,
         templateDuplicateLabelInSwitchStatement,
         templateExpectedType;
-import 'package:front_end/src/fasta/kernel/kernel_builder.dart'
-    show Builder, Scope;
 import 'package:front_end/src/fasta/quote.dart';
 import 'package:front_end/src/fasta/scanner/token_constants.dart';
-import 'package:front_end/src/fasta/source/scope_listener.dart'
-    show JumpTargetKind, NullValue, ScopeListener;
+import 'package:front_end/src/fasta/source/stack_listener.dart'
+    show NullValue, StackListener;
 import 'package:kernel/ast.dart' show AsyncMarker;
 
 /// A parser listener that builds the analyzer's AST structure.
-class AstBuilder extends ScopeListener {
+class AstBuilder extends StackListener {
   final AstFactory ast = standard.astFactory;
 
   final FastaErrorReporter errorReporter;
   final Uri fileUri;
-  final Builder member;
-
   ScriptTag scriptTag;
   final List<Directive> directives = <Directive>[];
   final List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
@@ -97,17 +93,12 @@
 
   StringLiteral nativeName;
 
-  AstBuilder(ErrorReporter errorReporter, this.fileUri, this.member,
-      Scope scope, this.isFullAst,
+  bool parseFunctionBodies = true;
+
+  AstBuilder(ErrorReporter errorReporter, this.fileUri, this.isFullAst,
       [Uri uri])
       : this.errorReporter = new FastaErrorReporter(errorReporter),
-        uri = uri ?? fileUri,
-        super(scope);
-
-  createJumpTarget(JumpTargetKind kind, int charOffset) {
-    // TODO(ahe): Implement jump targets.
-    return null;
-  }
+        uri = uri ?? fileUri;
 
   void beginLiteralString(Token literalString) {
     assert(identical(literalString.kind, STRING_TOKEN));
@@ -390,13 +381,16 @@
     debugEvent("BlockFunctionBody");
 
     List<Statement> statements = popTypedList(count);
-    if (leftBracket != null) {
-      exitLocalScope();
-    }
     Block block = ast.block(leftBracket, statements, rightBracket);
     Token star = pop();
     Token asyncKeyword = pop();
-    push(ast.blockFunctionBody(asyncKeyword, star, block));
+    if (parseFunctionBodies) {
+      push(ast.blockFunctionBody(asyncKeyword, star, block));
+    } else {
+      // TODO(danrubel): Skip the block rather than parsing it.
+      push(ast.emptyFunctionBody(
+          new SyntheticToken(TokenType.SEMICOLON, leftBracket.charOffset)));
+    }
   }
 
   void finishFunction(
@@ -512,8 +506,12 @@
     Token star = pop();
     Token asyncKeyword = pop();
     assert(star == null);
-    push(ast.expressionFunctionBody(
-        asyncKeyword, arrowToken, expression, semicolon));
+    if (parseFunctionBodies) {
+      push(ast.expressionFunctionBody(
+          asyncKeyword, arrowToken, expression, semicolon));
+    } else {
+      push(ast.emptyFunctionBody(semicolon));
+    }
   }
 
   void endReturnStatement(
@@ -633,8 +631,6 @@
 
     Statement body = pop();
     ParenthesizedExpression condition = pop();
-    exitContinueTarget();
-    exitBreakTarget();
     push(ast.whileStatement(whileKeyword, condition.leftParenthesis,
         condition.expression, condition.rightParenthesis, body));
   }
@@ -717,7 +713,6 @@
     debugEvent("Block");
 
     List<Statement> statements = popTypedList(count) ?? <Statement>[];
-    exitLocalScope();
     push(ast.block(leftBracket, statements, rightBracket));
   }
 
@@ -738,9 +733,6 @@
     List<Expression> updates = popTypedList(updateExpressionCount);
     Statement conditionStatement = pop();
     Object initializerPart = pop();
-    exitLocalScope();
-    exitContinueTarget();
-    exitBreakTarget();
 
     VariableDeclarationList variableList;
     Expression initializer;
@@ -1082,9 +1074,6 @@
     Statement body = pop();
     Expression iterator = pop();
     Object variableOrDeclaration = pop();
-    exitLocalScope();
-    exitContinueTarget();
-    exitBreakTarget();
     if (variableOrDeclaration is VariableDeclarationStatement) {
       VariableDeclarationList variableList = variableOrDeclaration.variables;
       push(ast.forEachStatementWithDeclaration(
@@ -1261,8 +1250,6 @@
     debugEvent("SwitchBlock");
 
     List<List<SwitchMember>> membersList = popTypedList(caseCount);
-    exitBreakTarget();
-    exitLocalScope();
     List<SwitchMember> members =
         membersList?.expand((members) => members)?.toList() ?? <SwitchMember>[];
 
@@ -1591,7 +1578,6 @@
     List<Configuration> configurations = pop();
     StringLiteral uri = pop();
     List<Annotation> metadata = pop();
-    assert(metadata == null); // TODO(paulberry): fix.
     Comment comment = _findComment(metadata, importKeyword);
 
     directives.add(ast.importDirective(
@@ -1642,7 +1628,6 @@
     List<Configuration> configurations = pop();
     StringLiteral uri = pop();
     List<Annotation> metadata = pop();
-    assert(metadata == null);
     Comment comment = _findComment(metadata, exportKeyword);
     directives.add(ast.exportDirective(comment, metadata, exportKeyword, uri,
         configurations, combinators, semicolon));
@@ -1667,8 +1652,6 @@
 
     ParenthesizedExpression condition = pop();
     Statement body = pop();
-    exitContinueTarget();
-    exitBreakTarget();
     push(ast.doStatement(
         doKeyword,
         body,
@@ -2143,6 +2126,7 @@
       pop(); // separator before constructor initializers
     }
     FormalParameterList parameters = pop();
+    checkFieldFormalParameters(parameters);
     SimpleIdentifier name = pop();
     TypeAnnotation returnType = pop();
     TypeParameterList typeParameters = pop();
@@ -2330,15 +2314,7 @@
         handleRecoverableError(
             messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
       }
-      if (parameters?.parameters != null) {
-        parameters.parameters.forEach((FormalParameter param) {
-          if (param is FieldFormalParameter) {
-            // This error is reported in the BodyBuilder.endFormalParameter.
-            handleRecoverableError(messageFieldInitializerOutsideConstructor,
-                param.thisKeyword, param.thisKeyword);
-          }
-        });
-      }
+      checkFieldFormalParameters(parameters);
       classDeclaration.members.add(ast.methodDeclaration(
           comment,
           metadata,
@@ -2370,6 +2346,18 @@
     }
   }
 
+  void checkFieldFormalParameters(FormalParameterList parameters) {
+    if (parameters?.parameters != null) {
+      parameters.parameters.forEach((FormalParameter param) {
+        if (param is FieldFormalParameter) {
+          // This error is reported in the BodyBuilder.endFormalParameter.
+          handleRecoverableError(messageFieldInitializerOutsideConstructor,
+              param.thisKeyword, param.thisKeyword);
+        }
+      });
+    }
+  }
+
   @override
   void handleInvalidMember(Token endToken) {
     debugEvent("InvalidMember");
@@ -2537,12 +2525,6 @@
     push(popTypedList<Annotation>(count) ?? NullValue.Metadata);
   }
 
-  @override
-  void printEvent(String name) {
-    // TODO(scheglov): Call of super is commented out to prevent spamming.
-//    super.printEvent(name);
-  }
-
   ParameterKind _toAnalyzerParameterKind(FormalParameterKind type) {
     if (type == FormalParameterKind.optionalPositional) {
       return ParameterKind.POSITIONAL;
@@ -2984,6 +2966,39 @@
 
     return tailList;
   }
+
+  @override
+  void exitLocalScope() {}
+
+  @override
+  void endDoWhileStatementBody(Token token) {
+    debugEvent("endDoWhileStatementBody");
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    debugEvent("endForStatementBody");
+  }
+
+  @override
+  void endForInBody(Token token) {
+    debugEvent("endForInBody");
+  }
+
+  @override
+  void endThenStatement(Token token) {
+    debugEvent("endThenStatement");
+  }
+
+  @override
+  void endWhileStatementBody(Token token) {
+    debugEvent("endWhileStatementBody");
+  }
+
+  @override
+  void endElseStatement(Token token) {
+    debugEvent("endElseStatement");
+  }
 }
 
 /// Data structure placed on the stack to represent a mixin application (a
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index 94cbe97..4534573 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -5,14 +5,22 @@
 import 'package:analyzer/dart/ast/ast.dart' hide Identifier;
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
+import 'package:analyzer/src/fasta/analyzer_expression_generator.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:front_end/src/fasta/kernel/body_builder.dart' show LabelTarget;
 import 'package:front_end/src/fasta/kernel/forest.dart';
 import 'package:kernel/ast.dart' as kernel;
 
+/// A data holder used to conform to the [Forest] API.
+class Arguments {
+  List<TypeAnnotation> typeArguments = <TypeAnnotation>[];
+  List<Expression> positionalArguments = <Expression>[];
+  List<Expression> namedArguments = <Expression>[];
+}
+
 /// An implementation of a [Forest] that can be used to build an AST structure.
 class AstBuildingForest
-    implements Forest<Expression, Statement, Token, _Arguments> {
+    implements Forest<Expression, Statement, Token, Arguments> {
   /// The type provider used to resolve the types of literal nodes, or `null` if
   /// type resolution is not being performed.
   final TypeProvider _typeProvider;
@@ -24,9 +32,9 @@
   AstBuildingForest(this._typeProvider);
 
   @override
-  _Arguments arguments(List<Expression> positional, Token location,
+  Arguments arguments(List<Expression> positional, Token location,
       {covariant List types, covariant List named}) {
-    _Arguments arguments = new _Arguments();
+    Arguments arguments = new Arguments();
     if (types != null) {
       arguments.typeArguments = types.cast<TypeAnnotation>();
     }
@@ -38,22 +46,22 @@
   }
 
   @override
-  _Arguments argumentsEmpty(Token location) => new _Arguments();
+  Arguments argumentsEmpty(Token location) => new Arguments();
 
   @override
-  List argumentsNamed(_Arguments arguments) => arguments.namedArguments;
+  List argumentsNamed(Arguments arguments) => arguments.namedArguments;
 
   @override
-  List<Expression> argumentsPositional(_Arguments arguments) =>
+  List<Expression> argumentsPositional(Arguments arguments) =>
       arguments.positionalArguments;
 
   @override
-  void argumentsSetTypeArguments(_Arguments arguments, covariant List types) {
+  void argumentsSetTypeArguments(Arguments arguments, covariant List types) {
     arguments.typeArguments = types.cast<TypeAnnotation>();
   }
 
   @override
-  List argumentsTypeArguments(_Arguments arguments) => arguments.typeArguments;
+  List argumentsTypeArguments(Arguments arguments) => arguments.typeArguments;
 
   @override
   Expression asExpression(Expression expression, type, Token location) =>
@@ -95,10 +103,12 @@
   Statement breakStatement(
           Token breakKeyword, Identifier label, Token semicolon) =>
       astFactory.breakStatement(
-          breakKeyword, astFactory.simpleIdentifier(label.token), semicolon);
+          breakKeyword,
+          label == null ? null : astFactory.simpleIdentifier(label.token),
+          semicolon);
 
   @override
-  kernel.Arguments castArguments(_Arguments arguments) {
+  kernel.Arguments castArguments(Arguments arguments) {
     // TODO(brianwilkerson) Implement this or remove it from the API.
     throw new UnimplementedError();
   }
@@ -161,16 +171,18 @@
   Statement continueStatement(
           Token continueKeyword, Identifier label, Token semicolon) =>
       astFactory.continueStatement(
-          continueKeyword, astFactory.simpleIdentifier(label.token), semicolon);
+          continueKeyword,
+          label == null ? null : astFactory.simpleIdentifier(label.token),
+          semicolon);
 
   @override
-  Generator<Expression, Statement, _Arguments> deferredAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> deferredAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       PrefixBuilder builder,
-      Generator<Expression, Statement, _Arguments> generator) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+      Generator<Expression, Statement, Arguments> generator) {
+    return new AnalyzerDeferredAccessGenerator(
+        helper, astFactory, token, builder, generator);
   }
 
   @override
@@ -248,6 +260,11 @@
       typeArguments.arguments.length;
 
   @override
+  String getVariableDeclarationName(VariableDeclaration declaration) {
+    return declaration.name.name;
+  }
+
+  @override
   Statement ifStatement(
           Token ifKeyword,
           ParenthesizedExpression condition,
@@ -264,15 +281,15 @@
           elseStatement);
 
   @override
-  Generator<Expression, Statement, _Arguments> indexedAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> indexedAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       Expression receiver,
       Expression index,
       kernel.Procedure getter,
       kernel.Procedure setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerIndexedAccessGenerator(
+        helper, astFactory, receiver, token, index, token.endGroup);
   }
 
   @override
@@ -313,11 +330,10 @@
       astFactory.labeledStatement(target.labels.cast<Label>(), statement);
 
   @override
-  Generator<Expression, Statement, _Arguments> largeIntAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> largeIntAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerLargeIntAccessGenerator(helper, astFactory, token);
   }
 
   @override
@@ -405,20 +421,24 @@
   }
 
   @override
-  Generator<Expression, Statement, _Arguments> loadLibraryGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> loadLibraryGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       LoadLibraryBuilder builder) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerLoadLibraryGenerator(helper, astFactory, token, builder);
   }
 
   @override
+  Expression logicalExpression(
+          Expression leftOperand, Token operator, Expression rightOperand) =>
+      astFactory.binaryExpression(leftOperand, operator, rightOperand);
+
+  @override
   Object mapEntry(Expression key, Token colon, Expression value) =>
       astFactory.mapLiteralEntry(key, colon, value);
 
   @override
-  List mapEntryList(int length) => <MapLiteralEntry>[];
+  List mapEntryList(int length) => new List<MapLiteralEntry>(length);
 
   @override
   Expression notExpression(Expression operand, Token operator) =>
@@ -426,16 +446,16 @@
         ..staticType = _typeProvider?.boolType;
 
   @override
-  Generator<Expression, Statement, _Arguments> nullAwarePropertyAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> nullAwarePropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       Expression receiverExpression,
       kernel.Name name,
       kernel.Member getter,
       kernel.Member setter,
       kernel.DartType type) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerNullAwarePropertyAccessGenerator(
+        helper, astFactory, receiverExpression, token, null /*name*/);
   }
 
   @override
@@ -445,28 +465,28 @@
           leftParenthesis, expression, rightParenthesis);
 
   @override
-  Generator<Expression, Statement, _Arguments> propertyAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> propertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       Expression receiver,
       kernel.Name name,
       kernel.Member getter,
       kernel.Member setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerPropertyAccessGenerator(
+        helper, astFactory, token, receiver, name, getter, setter);
   }
 
   @override
   int readOffset(AstNode node) => node.offset;
 
   @override
-  Generator<Expression, Statement, _Arguments> readOnlyAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> readOnlyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       Expression expression,
       String plainNameForRead) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerReadOnlyAccessGenerator(
+        helper, astFactory, token, expression, plainNameForRead);
   }
 
   @override
@@ -500,13 +520,13 @@
   }
 
   @override
-  Generator<Expression, Statement, _Arguments> staticAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> staticAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       kernel.Member getter,
       kernel.Member setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerStaticAccessGenerator(
+        helper, astFactory, token, getter, setter);
   }
 
   @override
@@ -515,25 +535,27 @@
       astFactory.adjacentStrings(strings.cast<StringLiteral>());
 
   @override
-  Generator<Expression, Statement, _Arguments> superIndexedAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> superIndexedAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       Expression index,
       kernel.Member getter,
       kernel.Member setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    // TODO(brianwilkerson) Figure out how to get the token for `super`.
+    return new AnalyzerIndexedAccessGenerator(
+        helper, astFactory, null, token, index, token.endGroup);
   }
 
   @override
-  Generator<Expression, Statement, _Arguments> superPropertyAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> superPropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       kernel.Name name,
       kernel.Member getter,
       kernel.Member setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    // TODO(brianwilkerson) Figure out how to get the token for the name.
+    return new AnalyzerSuperPropertyAccessGenerator(
+        helper, astFactory, null, null, null /*name*/);
   }
 
   @override
@@ -544,25 +566,27 @@
       astFactory.thisExpression(thisKeyword);
 
   @override
-  Generator<Expression, Statement, _Arguments> thisIndexedAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> thisIndexedAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       Expression index,
       kernel.Procedure getter,
       kernel.Procedure setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    // TODO(brianwilkerson) Figure out how to get the token for `this`.
+    return new AnalyzerIndexedAccessGenerator(
+        helper, astFactory, null, token, index, token.endGroup);
   }
 
   @override
-  Generator<Expression, Statement, _Arguments> thisPropertyAccessGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> thisPropertyAccessGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token location,
       kernel.Name name,
       kernel.Member getter,
       kernel.Member setter) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    // TODO(brianwilkerson) Figure out how to get the token for the name.
+    return new AnalyzerThisPropertyAccessGenerator(
+        helper, astFactory, location, name, getter, setter);
   }
 
   @override
@@ -580,15 +604,32 @@
           tryKeyword, body, catchClauses, finallyKeyword, finallyBlock);
 
   @override
-  Generator<Expression, Statement, _Arguments> typeUseGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> typeUseGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       PrefixBuilder prefix,
       int declarationReferenceOffset,
       TypeDeclarationBuilder declaration,
       String plainNameForRead) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerTypeUseGenerator(helper, astFactory, token, prefix,
+        declarationReferenceOffset, declaration, plainNameForRead);
+  }
+
+  @override
+  Generator<Expression, Statement, Arguments> unlinkedGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      UnlinkedDeclaration declaration) {
+    return new AnalyzerUnlinkedNameGenerator(
+        helper, astFactory, token, declaration);
+  }
+
+  @override
+  Generator<Expression, Statement, Arguments> unresolvedNameGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      kernel.Name name) {
+    return new AnalyzerUnresolvedNameGenerator(helper, astFactory, token, name);
   }
 
   @override
@@ -604,13 +645,12 @@
       variablesDeclaration.variables.variables;
 
   @override
-  Generator<Expression, Statement, _Arguments> variableUseGenerator(
-      ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+  Generator<Expression, Statement, Arguments> variableUseGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Token token,
       VariableDeclarationStatement variable,
       kernel.DartType promotedType) {
-    // TODO(brianwilkerson) Implement this.
-    throw new UnimplementedError();
+    return new AnalyzerVariableUseGenerator(helper, astFactory, token);
   }
 
   Statement whileStatement(Token whileKeyword,
@@ -626,10 +666,3 @@
           Expression expression, Token semicolon) =>
       astFactory.yieldStatement(yieldKeyword, star, expression, semicolon);
 }
-
-/// A data holder used to conform to the [Forest] API.
-class _Arguments {
-  List<TypeAnnotation> typeArguments = <TypeAnnotation>[];
-  List<Expression> positionalArguments = <Expression>[];
-  List<Expression> namedArguments = <Expression>[];
-}
diff --git a/pkg/analyzer/lib/src/fasta/mock_element.dart b/pkg/analyzer/lib/src/fasta/mock_element.dart
deleted file mode 100644
index 38c4cbe..0000000
--- a/pkg/analyzer/lib/src/fasta/mock_element.dart
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.analyzer.mock_element;
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/fasta/builder/builder.dart' show Builder;
-
-import 'package:front_end/src/fasta/problems.dart' show unsupported;
-
-abstract class MockElement extends Builder implements Element, LocalElement {
-  @override
-  final ElementKind kind;
-
-  MockElement(this.kind) : super(null, -1, null);
-
-  @override
-  get librarySource => unsupported("librarySource", charOffset, fileUri);
-
-  @override
-  get source => unsupported("source", charOffset, fileUri);
-
-  @override
-  get context => unsupported("context", charOffset, fileUri);
-
-  @override
-  String get displayName => unsupported("displayName", charOffset, fileUri);
-
-  @override
-  String get documentationComment =>
-      unsupported("documentationComment", charOffset, fileUri);
-
-  @override
-  Element get enclosingElement =>
-      unsupported("enclosingElement", charOffset, fileUri);
-
-  @override
-  int get id => unsupported("id", charOffset, fileUri);
-
-  @override
-  bool get isDeprecated => unsupported("isDeprecated", charOffset, fileUri);
-
-  @override
-  bool get isFactory => unsupported("isFactory", charOffset, fileUri);
-
-  @override
-  bool get isJS => unsupported("isJS", charOffset, fileUri);
-
-  @override
-  bool get isOverride => unsupported("isOverride", charOffset, fileUri);
-
-  @override
-  bool get isPrivate => unsupported("isPrivate", charOffset, fileUri);
-
-  @override
-  bool get isProtected => unsupported("isProtected", charOffset, fileUri);
-
-  @override
-  bool get isPublic => unsupported("isPublic", charOffset, fileUri);
-
-  @override
-  bool get isRequired => unsupported("isRequired", charOffset, fileUri);
-
-  @override
-  bool get isSynthetic => unsupported("isSynthetic", charOffset, fileUri);
-
-  @override
-  LibraryElement get library => unsupported("library", charOffset, fileUri);
-
-  @override
-  get location => unsupported("location", charOffset, fileUri);
-
-  @override
-  get metadata => unsupported("metadata", charOffset, fileUri);
-
-  @override
-  String get name => unsupported("name", charOffset, fileUri);
-
-  @override
-  String get fullNameForErrors => name;
-
-  @override
-  int get nameLength => unsupported("nameLength", charOffset, fileUri);
-
-  @override
-  int get nameOffset => -1;
-
-  @override
-  get unit => unsupported("unit", charOffset, fileUri);
-
-  @override
-  accept<T>(visitor) => unsupported("accept", charOffset, fileUri);
-
-  @override
-  String computeDocumentationComment() =>
-      unsupported("computeDocumentationComment", charOffset, fileUri);
-
-  @override
-  computeNode() => unsupported("computeNode", charOffset, fileUri);
-
-  @override
-  getAncestor<E extends Element>(predicate) =>
-      unsupported("getAncestor", charOffset, fileUri);
-
-  @override
-  String getExtendedDisplayName(String shortName) {
-    return unsupported("getExtendedDisplayName", charOffset, fileUri);
-  }
-
-  @override
-  bool isAccessibleIn(LibraryElement library) {
-    return unsupported("isAccessibleIn", charOffset, fileUri);
-  }
-
-  @override
-  void visitChildren(visitor) =>
-      unsupported("visitChildren", charOffset, fileUri);
-
-  String get uri => unsupported("uri", charOffset, fileUri);
-
-  int get uriEnd => unsupported("uriEnd", charOffset, fileUri);
-
-  int get uriOffset => unsupported("uriOffset", charOffset, fileUri);
-
-  List<ParameterElement> get parameters =>
-      unsupported("parameters", charOffset, fileUri);
-
-  List<FunctionElement> get functions =>
-      unsupported("functions", charOffset, fileUri);
-
-  bool get hasImplicitReturnType =>
-      unsupported("hasImplicitReturnType", charOffset, fileUri);
-
-  bool get isAbstract => unsupported("isAbstract", charOffset, fileUri);
-
-  bool get isAsynchronous => unsupported("isAsynchronous", charOffset, fileUri);
-
-  bool get isExternal => unsupported("isExternal", charOffset, fileUri);
-
-  bool get isGenerator => unsupported("isGenerator", charOffset, fileUri);
-
-  bool get isOperator => unsupported("isOperator", charOffset, fileUri);
-
-  @override
-  bool get isStatic => unsupported("isStatic", charOffset, fileUri);
-
-  bool get isSynchronous => unsupported("isSynchronous", charOffset, fileUri);
-
-  @override
-  get visibleRange => unsupported("visibleRange", charOffset, fileUri);
-
-  bool get hasImplicitType =>
-      unsupported("hasImplicitType", charOffset, fileUri);
-
-  FunctionElement get initializer =>
-      unsupported("initializer", charOffset, fileUri);
-
-  @override
-  bool get isConst => unsupported("isConst", charOffset, fileUri);
-
-  @override
-  bool get isFinal => unsupported("isFinal", charOffset, fileUri);
-
-  bool get isPotentiallyMutatedInClosure =>
-      unsupported("isPotentiallyMutatedInClosure", charOffset, fileUri);
-
-  bool get isPotentiallyMutatedInScope =>
-      unsupported("isPotentiallyMutatedInScope", charOffset, fileUri);
-}
-
-abstract class MockLibraryElement extends MockElement
-    implements LibraryElement {
-  MockLibraryElement() : super(ElementKind.LIBRARY);
-
-  @override
-  CompilationUnitElement get definingCompilationUnit {
-    return unsupported("definingCompilationUnit", charOffset, fileUri);
-  }
-
-  @override
-  FunctionElement get entryPoint =>
-      unsupported("entryPoint", charOffset, fileUri);
-
-  @override
-  List<LibraryElement> get exportedLibraries {
-    return unsupported("exportedLibraries", charOffset, fileUri);
-  }
-
-  @override
-  get exportNamespace => unsupported("exportNamespace", charOffset, fileUri);
-
-  @override
-  get exports => unsupported("exports", charOffset, fileUri);
-
-  @override
-  bool get hasExtUri => unsupported("hasExtUri", charOffset, fileUri);
-
-  @override
-  bool get hasLoadLibraryFunction =>
-      unsupported("hasLoadLibraryFunction", charOffset, fileUri);
-
-  @override
-  String get identifier => unsupported("identifier", charOffset, fileUri);
-
-  @override
-  List<LibraryElement> get importedLibraries {
-    return unsupported("importedLibraries", charOffset, fileUri);
-  }
-
-  @override
-  get imports => unsupported("imports", charOffset, fileUri);
-
-  @override
-  bool get isBrowserApplication =>
-      unsupported("isBrowserApplication", charOffset, fileUri);
-
-  @override
-  bool get isDartAsync => unsupported("isDartAsync", charOffset, fileUri);
-
-  @override
-  bool get isDartCore => unsupported("isDartCore", charOffset, fileUri);
-
-  @override
-  bool get isInSdk => unsupported("isInSdk", charOffset, fileUri);
-
-  @override
-  List<LibraryElement> get libraryCycle =>
-      unsupported("libraryCycle", charOffset, fileUri);
-
-  @override
-  FunctionElement get loadLibraryFunction =>
-      unsupported("loadLibraryFunction", charOffset, fileUri);
-
-  @override
-  List<CompilationUnitElement> get parts =>
-      unsupported("parts", charOffset, fileUri);
-
-  @override
-  List<PrefixElement> get prefixes =>
-      unsupported("prefixes", charOffset, fileUri);
-
-  @override
-  get publicNamespace => unsupported("publicNamespace", charOffset, fileUri);
-
-  @override
-  List<CompilationUnitElement> get units =>
-      unsupported("units", charOffset, fileUri);
-
-  @override
-  getImportsWithPrefix(PrefixElement prefix) {
-    return unsupported("getImportsWithPrefix", charOffset, fileUri);
-  }
-
-  @override
-  ClassElement getType(String className) =>
-      unsupported("getType", charOffset, fileUri);
-}
-
-abstract class MockCompilationUnitElement extends MockElement
-    implements CompilationUnitElement {
-  MockCompilationUnitElement() : super(ElementKind.COMPILATION_UNIT);
-
-  @override
-  List<PropertyAccessorElement> get accessors {
-    return unsupported("accessors", charOffset, fileUri);
-  }
-
-  @override
-  LibraryElement get enclosingElement =>
-      unsupported("enclosingElement", charOffset, fileUri);
-
-  @override
-  List<ClassElement> get enums => unsupported("enums", charOffset, fileUri);
-
-  @override
-  List<FunctionElement> get functions =>
-      unsupported("functions", charOffset, fileUri);
-
-  @override
-  List<FunctionTypeAliasElement> get functionTypeAliases {
-    return unsupported("functionTypeAliases", charOffset, fileUri);
-  }
-
-  @override
-  bool get hasLoadLibraryFunction =>
-      unsupported("hasLoadLibraryFunction", charOffset, fileUri);
-
-  @override
-  LineInfo get lineInfo => unsupported("lineInfo", charOffset, fileUri);
-
-  @override
-  List<TopLevelVariableElement> get topLevelVariables {
-    return unsupported("topLevelVariables", charOffset, fileUri);
-  }
-
-  @override
-  List<ClassElement> get types => unsupported("types", charOffset, fileUri);
-
-  @override
-  ClassElement getEnum(String name) =>
-      unsupported("getEnum", charOffset, fileUri);
-
-  @override
-  ClassElement getType(String name) =>
-      unsupported("getType", charOffset, fileUri);
-
-  @override
-  CompilationUnit computeNode() =>
-      unsupported("computeNode", charOffset, fileUri);
-}
-
-abstract class MockClassElement extends MockElement implements ClassElement {
-  MockClassElement() : super(ElementKind.CLASS);
-
-  List<PropertyAccessorElement> get accessors {
-    return unsupported("accessors", charOffset, fileUri);
-  }
-
-  @override
-  get allSupertypes => unsupported("allSupertypes", charOffset, fileUri);
-
-  @override
-  List<ConstructorElement> get constructors =>
-      unsupported("constructors", charOffset, fileUri);
-
-  @override
-  List<FieldElement> get fields => unsupported("fields", charOffset, fileUri);
-
-  @override
-  bool get hasNonFinalField =>
-      unsupported("hasNonFinalField", charOffset, fileUri);
-
-  @override
-  bool get hasReferenceToSuper =>
-      unsupported("hasReferenceToSuper", charOffset, fileUri);
-
-  @override
-  bool get hasStaticMember =>
-      unsupported("hasStaticMember", charOffset, fileUri);
-
-  @override
-  get interfaces => unsupported("interfaces", charOffset, fileUri);
-
-  @override
-  bool get isAbstract => unsupported("isAbstract", charOffset, fileUri);
-
-  @override
-  bool get isEnum => unsupported("isEnum", charOffset, fileUri);
-
-  @override
-  bool get isMixinApplication =>
-      unsupported("isMixinApplication", charOffset, fileUri);
-
-  @override
-  bool get isOrInheritsProxy =>
-      unsupported("isOrInheritsProxy", charOffset, fileUri);
-
-  @override
-  bool get isProxy => unsupported("isProxy", charOffset, fileUri);
-
-  @override
-  bool get isValidMixin => unsupported("isValidMixin", charOffset, fileUri);
-
-  @override
-  get typeParameters => unsupported("typeParameters", charOffset, fileUri);
-
-  @override
-  List<MethodElement> get methods =>
-      unsupported("methods", charOffset, fileUri);
-
-  @override
-  get mixins => unsupported("mixins", charOffset, fileUri);
-
-  @override
-  get supertype => unsupported("supertype", charOffset, fileUri);
-
-  @override
-  ConstructorElement get unnamedConstructor =>
-      unsupported("unnamedConstructor", charOffset, fileUri);
-
-  @override
-  FieldElement getField(String name) =>
-      unsupported("getField", charOffset, fileUri);
-
-  @override
-  PropertyAccessorElement getGetter(String name) {
-    return unsupported("getGetter", charOffset, fileUri);
-  }
-
-  @override
-  MethodElement getMethod(String name) =>
-      unsupported("getMethod", charOffset, fileUri);
-
-  @override
-  ConstructorElement getNamedConstructor(String name) {
-    return unsupported("getNamedConstructor", charOffset, fileUri);
-  }
-
-  @override
-  PropertyAccessorElement getSetter(String name) {
-    return unsupported("getSetter", charOffset, fileUri);
-  }
-
-  @override
-  bool isSuperConstructorAccessible(ConstructorElement constructor) {
-    return unsupported("isSuperConstructorAccessible", charOffset, fileUri);
-  }
-
-  @override
-  MethodElement lookUpConcreteMethod(
-      String methodName, LibraryElement library) {
-    return unsupported("lookUpConcreteMethod", charOffset, fileUri);
-  }
-
-  @override
-  PropertyAccessorElement lookUpGetter(
-      String getterName, LibraryElement library) {
-    return unsupported("lookUpGetter", charOffset, fileUri);
-  }
-
-  @override
-  PropertyAccessorElement lookUpInheritedConcreteGetter(
-      String getterName, LibraryElement library) {
-    return unsupported("lookUpInheritedConcreteGetter", charOffset, fileUri);
-  }
-
-  @override
-  MethodElement lookUpInheritedConcreteMethod(
-      String methodName, LibraryElement library) {
-    return unsupported("lookUpInheritedConcreteMethod", charOffset, fileUri);
-  }
-
-  @override
-  PropertyAccessorElement lookUpInheritedConcreteSetter(
-      String setterName, LibraryElement library) {
-    return unsupported("lookUpInheritedConcreteSetter", charOffset, fileUri);
-  }
-
-  @override
-  MethodElement lookUpInheritedMethod(
-      String methodName, LibraryElement library) {
-    return unsupported("lookUpInheritedMethod", charOffset, fileUri);
-  }
-
-  @override
-  MethodElement lookUpMethod(String methodName, LibraryElement library) {
-    return unsupported("lookUpMethod", charOffset, fileUri);
-  }
-
-  @override
-  PropertyAccessorElement lookUpSetter(
-      String setterName, LibraryElement library) {
-    return unsupported("lookUpSetter", charOffset, fileUri);
-  }
-
-  @override
-  NamedCompilationUnitMember computeNode() =>
-      unsupported("computeNode", charOffset, fileUri);
-
-  @override
-  InterfaceType get type => unsupported("type", charOffset, fileUri);
-}
-
-abstract class MockFunctionElement extends MockElement
-    implements FunctionElement {
-  MockFunctionElement() : super(ElementKind.FUNCTION);
-
-  @override
-  bool get isEntryPoint => unsupported("isEntryPoint", charOffset, fileUri);
-
-  @override
-  get typeParameters => unsupported("typeParameters", charOffset, fileUri);
-
-  @override
-  FunctionType get type => unsupported("type", charOffset, fileUri);
-
-  @override
-  DartType get returnType => unsupported("returnType", charOffset, fileUri);
-
-  @override
-  FunctionDeclaration computeNode() =>
-      unsupported("computeNode", charOffset, fileUri);
-}
-
-abstract class MockFunctionTypeAliasElement extends MockElement
-    implements FunctionTypeAliasElement {
-  MockFunctionTypeAliasElement() : super(ElementKind.FUNCTION_TYPE_ALIAS);
-
-  @override
-  CompilationUnitElement get enclosingElement {
-    return unsupported("enclosingElement", charOffset, fileUri);
-  }
-
-  @override
-  TypeAlias computeNode() => unsupported("computeNode", charOffset, fileUri);
-}
-
-abstract class MockParameterElement extends MockElement
-    implements ParameterElement {
-  MockParameterElement() : super(ElementKind.PARAMETER);
-
-  @override
-  String get defaultValueCode =>
-      unsupported("defaultValueCode", charOffset, fileUri);
-
-  @override
-  bool get isCovariant => unsupported("isCovariant", charOffset, fileUri);
-
-  @override
-  bool get isInitializingFormal =>
-      unsupported("isInitializingFormal", charOffset, fileUri);
-
-  @override
-  get parameterKind => unsupported("parameterKind", charOffset, fileUri);
-
-  @override
-  List<ParameterElement> get parameters =>
-      unsupported("parameters", charOffset, fileUri);
-
-  @override
-  get type => null;
-
-  @override
-  get typeParameters => unsupported("typeParameters", charOffset, fileUri);
-
-  @override
-  get constantValue => unsupported("constantValue", charOffset, fileUri);
-
-  @override
-  computeConstantValue() =>
-      unsupported("computeConstantValue", charOffset, fileUri);
-
-  @override
-  void appendToWithoutDelimiters(StringBuffer buffer) {
-    return unsupported("appendToWithoutDelimiters", charOffset, fileUri);
-  }
-
-  @override
-  FormalParameter computeNode() =>
-      unsupported("computeNode", charOffset, fileUri);
-}
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index a60c8ab..854fb69 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -24,7 +24,6 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:front_end/src/fasta/kernel/kernel_builder.dart';
 import 'package:front_end/src/fasta/parser/identifier_context.dart' as fasta;
 import 'package:front_end/src/fasta/parser/member_kind.dart' as fasta;
 import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart
index 3944ae3..69905bb 100644
--- a/pkg/analyzer/lib/src/generated/parser_fasta.dart
+++ b/pkg/analyzer/lib/src/generated/parser_fasta.dart
@@ -24,11 +24,9 @@
   final AstBuilder astBuilder;
 
   ParserAdapter(this.currentToken, ErrorReporter errorReporter, Uri fileUri,
-      Builder member, Scope scope,
       {bool allowNativeClause: false, bool enableGenericMethodComments: false})
       : fastaParser = new fasta.Parser(null),
-        astBuilder =
-            new AstBuilder(errorReporter, fileUri, member, scope, true) {
+        astBuilder = new AstBuilder(errorReporter, fileUri, true) {
     fastaParser.listener = astBuilder;
     astBuilder.parser = fastaParser;
     astBuilder.allowNativeClause = allowNativeClause;
@@ -48,7 +46,7 @@
 
   @override
   void set parseFunctionBodies(bool parseFunctionBodies) {
-    // ignored
+    astBuilder.parseFunctionBodies = parseFunctionBodies;
   }
 
   @override
@@ -309,26 +307,38 @@
 
   @override
   TypeParameter parseTypeParameter() {
-    currentToken = fastaParser
-        .parseTypeVariable(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop();
+    currentToken = new SyntheticBeginToken(TokenType.LT, 0)
+      ..endGroup = new SyntheticToken(TokenType.GT, 0)
+      ..setNext(currentToken);
+    appendToken(currentToken, currentToken.endGroup);
+    TypeParameterList typeParams = parseTypeParameterList();
+    return typeParams.typeParameters[0];
   }
 
   @override
   TypeParameterList parseTypeParameterList() {
-    currentToken = fastaParser
-        .parseTypeVariablesOpt(fastaParser.syntheticPreviousToken(currentToken))
+    Token token = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeTypeParamOrArg(token, true)
+        .parseVariables(token, fastaParser)
         .next;
     return astBuilder.pop();
   }
 
   @override
   Expression parseUnaryExpression() => parseExpression2();
-}
 
-class _Builder implements Builder {
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+  /// Append the given token to the end of the token stream,
+  /// and update the token's offset.
+  appendToken(Token token, Token newToken) {
+    while (!token.next.isEof) {
+      token = token.next;
+    }
+    newToken
+      ..offset = token.end
+      ..setNext(token.next);
+    token.setNext(newToken);
+  }
 }
 
 /**
@@ -349,15 +359,13 @@
   factory _Parser2(Source source, AnalysisErrorListener errorListener,
       {bool allowNativeClause: false}) {
     var errorReporter = new ErrorReporter(errorListener, source);
-    var member = new _Builder();
-    var scope = new Scope.top(isModifiable: true);
-    return new _Parser2._(source, errorReporter, source.uri, member, scope,
+    return new _Parser2._(source, errorReporter, source.uri,
         allowNativeClause: allowNativeClause);
   }
 
   _Parser2._(this._source, ErrorReporter errorReporter, Uri fileUri,
-      Builder member, Scope scope, {bool allowNativeClause: false})
-      : super(null, errorReporter, fileUri, member, scope,
+      {bool allowNativeClause: false})
+      : super(null, errorReporter, fileUri,
             allowNativeClause: allowNativeClause);
 
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 6fdac95..858e83f 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4076,6 +4076,20 @@
   final HashMap<ImportDirective, List<SimpleIdentifier>> _unusedShownNamesMap =
       new HashMap<ImportDirective, List<SimpleIdentifier>>();
 
+  /**
+   * A map of names that are hidden more than once.
+   */
+  final HashMap<NamespaceDirective, List<SimpleIdentifier>>
+      _duplicateHiddenNamesMap =
+      new HashMap<NamespaceDirective, List<SimpleIdentifier>>();
+
+  /**
+   * A map of names that are shown more than once.
+   */
+  final HashMap<NamespaceDirective, List<SimpleIdentifier>>
+      _duplicateShownNamesMap =
+      new HashMap<NamespaceDirective, List<SimpleIdentifier>>();
+
   void addImports(CompilationUnit node) {
     for (Directive directive in node.directives) {
       if (directive is ImportDirective) {
@@ -4105,6 +4119,9 @@
         }
         _addShownNames(directive);
       }
+      if (directive is NamespaceDirective) {
+        _addDuplicateShownHiddenNames(directive);
+      }
     }
     if (_unusedImports.length > 1) {
       // order the list of unusedImports to find duplicates in faster than
@@ -4200,6 +4217,37 @@
   }
 
   /**
+   * Report a [HintCode.DUPLICATE_SHOWN_HIDDEN_NAME] hint for each duplicate
+   * shown or hidden name.
+   *
+   * Only call this method after all of the compilation units have been visited
+   * by this visitor.
+   *
+   * @param errorReporter the error reporter used to report the set of
+   *          [HintCode.UNUSED_SHOWN_NAME] hints
+   */
+  void generateDuplicateShownHiddenNameHints(ErrorReporter reporter) {
+    _duplicateHiddenNamesMap.forEach(
+        (NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
+      int length = identifiers.length;
+      for (int i = 0; i < length; i++) {
+        Identifier identifier = identifiers[i];
+        reporter.reportErrorForNode(
+            HintCode.DUPLICATE_HIDDEN_NAME, identifier, [identifier.name]);
+      }
+    });
+    _duplicateShownNamesMap.forEach(
+        (NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
+      int length = identifiers.length;
+      for (int i = 0; i < length; i++) {
+        Identifier identifier = identifiers[i];
+        reporter.reportErrorForNode(
+            HintCode.DUPLICATE_SHOWN_NAME, identifier, [identifier.name]);
+      }
+    });
+  }
+
+  /**
    * Remove elements from [_unusedImports] using the given [usedElements].
    */
   void removeUsedElements(UsedImportedElements usedElements) {
@@ -4263,6 +4311,43 @@
   }
 
   /**
+   * Add duplicate shown and hidden names from [directive] into
+   * [_duplicateHiddenNamesMap] and [_duplicateShownNamesMap].
+   */
+  void _addDuplicateShownHiddenNames(NamespaceDirective directive) {
+    if (directive.combinators == null) {
+      return;
+    }
+    for (Combinator combinator in directive.combinators) {
+      // Use a Set to find duplicates in faster than O(n^2) time.
+      Set<Element> identifiers = new Set<Element>();
+      if (combinator is HideCombinator) {
+        for (SimpleIdentifier name in combinator.hiddenNames) {
+          if (name.staticElement != null) {
+            if (!identifiers.add(name.staticElement)) {
+              // [name] is a duplicate.
+              List<SimpleIdentifier> duplicateNames = _duplicateHiddenNamesMap
+                  .putIfAbsent(directive, () => new List<SimpleIdentifier>());
+              duplicateNames.add(name);
+            }
+          }
+        }
+      } else if (combinator is ShowCombinator) {
+        for (SimpleIdentifier name in combinator.shownNames) {
+          if (name.staticElement != null) {
+            if (!identifiers.add(name.staticElement)) {
+              // [name] is a duplicate.
+              List<SimpleIdentifier> duplicateNames = _duplicateShownNamesMap
+                  .putIfAbsent(directive, () => new List<SimpleIdentifier>());
+              duplicateNames.add(name);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
    * Lookup and return the [Namespace] from the [_namespaceMap].
    *
    * If the map does not have the computed namespace, compute it and cache it in the map. If
diff --git a/pkg/analyzer/lib/src/kernel/resynthesize.dart b/pkg/analyzer/lib/src/kernel/resynthesize.dart
index a66763e..43cb699 100644
--- a/pkg/analyzer/lib/src/kernel/resynthesize.dart
+++ b/pkg/analyzer/lib/src/kernel/resynthesize.dart
@@ -372,7 +372,7 @@
     }
 
     // Replace Analyzer type parameters with type arguments.
-    return rawType.substitute4(usedTypeParameters, usedTypeArguments);
+    throw new UnimplementedError('TODO(paulberry)');
   }
 
   /// Return the [TypeParameterElement] for the given [kernelTypeParameter].
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index fa604ed..3c6353c 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2913,8 +2913,8 @@
         return context.typeSystem
             .instantiateToBounds(new FunctionTypeImpl.forTypedef(this));
       } else {
-        return new FunctionTypeImpl.elementWithNameAndArgs(
-            this, name, typeArguments, true);
+        return new FunctionTypeImpl.forTypedef(this,
+            typeArguments: typeArguments);
       }
     } else {
       return _type ??= new FunctionTypeImpl.forTypedef(this);
@@ -2989,8 +2989,7 @@
 
   @override
   FunctionType get type {
-    return _type ??= new FunctionTypeImpl.elementWithNameAndArgs(
-        this, null, allEnclosingTypeParameterTypes, false);
+    return _type ??= new FunctionTypeImpl(this);
   }
 
   @override
@@ -3087,8 +3086,8 @@
         return context.typeSystem
             .instantiateToBounds(new FunctionTypeImpl.forTypedef(this));
       } else {
-        return new FunctionTypeImpl.elementWithNameAndArgs(
-            this, name, typeArguments, true);
+        return new FunctionTypeImpl.forTypedef(this,
+            typeArguments: typeArguments);
       }
     } else {
       return new FunctionTypeImpl.forTypedef(this);
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 2271c0c..170a534 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1075,8 +1075,8 @@
         } else {
           typeArguments = _dynamicTypeArguments;
         }
-        return new FunctionTypeImpl.elementWithNameAndArgs(
-            element, name, typeArguments, numTypeParameters != 0);
+        return new FunctionTypeImpl.forTypedef(element,
+            typeArguments: typeArguments);
       } else {
         FunctionTypedElementComputer computer;
         if (implicitFunctionTypeIndices.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index d83a9bc..a1c7232 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -2836,6 +2836,7 @@
       verifier.addImports(unit);
       usedImportedElementsList.forEach(verifier.removeUsedElements);
       verifier.generateDuplicateImportHints(errorReporter);
+      verifier.generateDuplicateShownHiddenNameHints(errorReporter);
       verifier.generateUnusedImportHints(errorReporter);
       verifier.generateUnusedShownNameHints(errorReporter);
     }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 2a7256e..819219b 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.32.1-alpha.0
+version: 0.32.1
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -11,10 +11,10 @@
   collection: ^1.10.1
   convert: ^2.0.0
   crypto: '>=1.1.1 <3.0.0'
-  front_end: 0.1.1-alpha.0
+  front_end: 0.1.1
   glob: ^1.0.3
   html: '>=0.12.0 <1.14.0'
-  kernel: 0.3.1-alpha.0
+  kernel: 0.3.1
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 9eac8d1..06b1454 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -628,7 +628,11 @@
   A(static this.x);
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [ParserErrorCode.EXTRANEOUS_MODIFIER]
+            : [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     verify([source]);
   }
 
@@ -637,7 +641,11 @@
 f(static x) {
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [ParserErrorCode.EXTRANEOUS_MODIFIER]
+            : [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     verify([source]);
   }
 
@@ -1350,14 +1358,28 @@
   A(const this.x) {}
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.CONST_FORMAL_PARAMETER,
+                ParserErrorCode.EXTRANEOUS_MODIFIER
+              ]
+            : [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
     verify([source]);
   }
 
   test_constFormalParameter_simpleFormalParameter() async {
     Source source = addSource("f(const x) {}");
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.CONST_FORMAL_PARAMETER,
+                ParserErrorCode.EXTRANEOUS_MODIFIER
+              ]
+            : [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
     verify([source]);
   }
 
@@ -1706,7 +1728,13 @@
     Source source = addSource("typedef F([x = 0]);");
     await computeAnalysisResult(source);
     assertErrors(
-        source, [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
+                ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+              ]
+            : [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
     verify([source]);
   }
 
@@ -1714,23 +1742,41 @@
     Source source = addSource("typedef F([x = 0]);");
     await computeAnalysisResult(source);
     assertErrors(
-        source, [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
+                ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+              ]
+            : [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
     verify([source]);
   }
 
   test_defaultValueInFunctionTypedParameter_named() async {
     Source source = addSource("f(g({p: null})) {}");
     await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
+                ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+              ]
+            : [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
     verify([source]);
   }
 
   test_defaultValueInFunctionTypedParameter_optional() async {
     Source source = addSource("f(g([p = null])) {}");
     await computeAnalysisResult(source);
-    assertErrors(source,
-        [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
+                ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
+              ]
+            : [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
     verify([source]);
   }
 
@@ -3589,7 +3635,16 @@
   set x(v) async {}
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
+    // TODO(danrubel): Investigate why error message is duplicated when
+    // using fasta parser.
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+              ]
+            : [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
@@ -3599,7 +3654,14 @@
   set x(v) async* {}
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+              ]
+            : [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
@@ -3609,28 +3671,56 @@
   set x(v) sync* {}
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+              ]
+            : [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
   test_invalidModifierOnSetter_topLevel_async() async {
     Source source = addSource("set x(v) async {}");
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+              ]
+            : [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
   test_invalidModifierOnSetter_topLevel_asyncStar() async {
     Source source = addSource("set x(v) async* {}");
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+              ]
+            : [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
   test_invalidModifierOnSetter_topLevel_syncStar() async {
     Source source = addSource("set x(v) sync* {}");
     await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
+    assertErrors(
+        source,
+        usingFastaParser
+            ? [
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
+                CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
+              ]
+            : [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index f93161b1..f37baf0 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1241,6 +1241,32 @@
     verify([source]);
   }
 
+  test_duplicateShownHiddenName_hidden() async {
+    Source source = addSource(r'''
+library L;
+export 'lib1.dart' hide A, B, A;''');
+    addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+class B {}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [HintCode.DUPLICATE_HIDDEN_NAME]);
+    verify([source]);
+  }
+
+  test_duplicateShownHiddenName_shown() async {
+    Source source = addSource(r'''
+library L;
+export 'lib1.dart' show A, B, A;''');
+    addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+class B {}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [HintCode.DUPLICATE_SHOWN_NAME]);
+    verify([source]);
+  }
+
   test_factory__expr_return_null_OK() async {
     Source source = addSource(r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/generated/package_build_test.dart b/pkg/analyzer/test/generated/package_build_test.dart
index a731844..96cecc3 100644
--- a/pkg/analyzer/test/generated/package_build_test.dart
+++ b/pkg/analyzer/test/generated/package_build_test.dart
@@ -465,7 +465,6 @@
     final packageMap = new Map.fromIterable(packageNames, value: ((_) => []));
     when(contextBuilder.createPackageMap(_p(root))).thenReturn(packages);
     when(contextBuilder.convertPackagesToMap(packages)).thenReturn(packageMap);
-    when(packages.asMap()).thenReturn(packageMap);
     return PackageBuildWorkspace.find(provider, _p(root), contextBuilder);
   }
 }
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 2ff080d..48992b4 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/string_source.dart';
-import 'package:front_end/src/fasta/kernel/kernel_builder.dart';
 import 'package:front_end/src/fasta/scanner/error_token.dart' show ErrorToken;
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
 import 'package:test/test.dart';
@@ -40,16 +39,6 @@
  */
 typedef analyzer.Token ParseFunction(analyzer.Token token);
 
-/**
- * Proxy implementation of [Builder] used by Fasta parser tests.
- *
- * All undeclared identifiers are presumed to resolve via an instance of this
- * class.
- */
-class BuilderProxy implements Builder {
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
 @reflectiveTest
 class ClassMemberParserTest_Fasta extends FastaParserTestCase
     with ClassMemberParserTestMixin {
@@ -1133,24 +1122,21 @@
       {bool allowNativeClause: false,
       bool enableGenericMethodComments: false,
       int expectedEndOffset}) {
-    var member = new BuilderProxy();
-    var scope = new ScopeProxy();
     TestSource source = new TestSource();
     var errorListener = new GatheringErrorListener(checkRanges: true);
     var errorReporter = new ErrorReporter(errorListener, source);
-    return new ParserProxy._(
-        firstToken, errorReporter, null, member, scope, errorListener,
+    return new ParserProxy._(firstToken, errorReporter, null, errorListener,
         allowNativeClause: allowNativeClause,
         enableGenericMethodComments: enableGenericMethodComments,
         expectedEndOffset: expectedEndOffset);
   }
 
   ParserProxy._(analyzer.Token firstToken, ErrorReporter errorReporter,
-      Uri fileUri, Builder member, Scope scope, this._errorListener,
+      Uri fileUri, this._errorListener,
       {bool allowNativeClause: false,
       bool enableGenericMethodComments: false,
       this.expectedEndOffset})
-      : super(firstToken, errorReporter, fileUri, member, scope,
+      : super(firstToken, errorReporter, fileUri,
             allowNativeClause: allowNativeClause,
             enableGenericMethodComments: enableGenericMethodComments) {
     _eventListener = new ForwardingTestListener(astBuilder);
@@ -1335,34 +1321,6 @@
   }
 }
 
-/**
- * Proxy implementation of [Scope] used by Fasta parser tests.
- *
- * Any name lookup request is satisfied by creating an instance of
- * [BuilderProxy].
- */
-class ScopeProxy implements Scope {
-  final _locals = <String, Builder>{};
-
-  @override
-  Scope createNestedScope(String debugName, {bool isModifiable: true}) {
-    return new Scope.nested(this, debugName, isModifiable: isModifiable);
-  }
-
-  @override
-  declare(String name, Builder builder, Uri fileUri) {
-    _locals[name] = builder;
-    return null;
-  }
-
-  @override
-  Builder lookup(String name, int charOffset, Uri fileUri,
-          {bool isInstanceScope: true}) =>
-      _locals.putIfAbsent(name, () => new BuilderProxy());
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
 @reflectiveTest
 class SimpleParserTest_Fasta extends FastaParserTestCase
     with SimpleParserTestMixin {
diff --git a/pkg/analyzer/test/generated/parser_forest_test.dart b/pkg/analyzer/test/generated/parser_forest_test.dart
index 5908df2..b1b4491 100644
--- a/pkg/analyzer/test/generated/parser_forest_test.dart
+++ b/pkg/analyzer/test/generated/parser_forest_test.dart
@@ -22,6 +22,11 @@
   });
 }
 
+void dart2Failure() {
+  fail(
+      'This passes under Dart 1, but fails under Dart 2 because of a cast exception');
+}
+
 @reflectiveTest
 class ClassMemberParserTest_Forest extends FastaBodyBuilderTestCase
     with ClassMemberParserTestMixin {
@@ -482,11 +487,13 @@
   @failingTest
   void test_assignmentExpression_compound() {
     super.test_assignmentExpression_compound();
+    dart2Failure();
   }
 
   @failingTest
   void test_assignmentExpression_indexExpression() {
     super.test_assignmentExpression_indexExpression();
+    dart2Failure();
   }
 
   @failingTest
@@ -627,6 +634,7 @@
   @failingTest
   void test_logicalAndExpression() {
     super.test_logicalAndExpression();
+    dart2Failure();
   }
 
   @failingTest
@@ -647,16 +655,19 @@
   @failingTest
   void test_logicalOrExpression() {
     super.test_logicalOrExpression();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalOrExpression_precedence_logicalAnd_left() {
     super.test_logicalOrExpression_precedence_logicalAnd_left();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalOrExpression_precedence_logicalAnd_right() {
     super.test_logicalOrExpression_precedence_logicalAnd_right();
+    dart2Failure();
   }
 
   @failingTest
@@ -675,11 +686,6 @@
   }
 
   @failingTest
-  void test_multipleLabels_statement() {
-    super.test_multipleLabels_statement();
-  }
-
-  @failingTest
   void test_multiplicativeExpression_normal() {
     super.test_multiplicativeExpression_normal();
   }
@@ -791,11 +797,6 @@
   }
 
   @failingTest
-  void test_breakOutsideOfLoop_breakInDoStatement() {
-    super.test_breakOutsideOfLoop_breakInDoStatement();
-  }
-
-  @failingTest
   void test_breakOutsideOfLoop_breakInForStatement() {
     super.test_breakOutsideOfLoop_breakInForStatement();
   }
@@ -811,11 +812,6 @@
   }
 
   @failingTest
-  void test_breakOutsideOfLoop_breakInWhileStatement() {
-    super.test_breakOutsideOfLoop_breakInWhileStatement();
-  }
-
-  @failingTest
   void test_breakOutsideOfLoop_functionExpression_inALoop() {
     super.test_breakOutsideOfLoop_functionExpression_inALoop();
   }
@@ -916,11 +912,6 @@
   }
 
   @failingTest
-  void test_continueOutsideOfLoop_continueInDoStatement() {
-    super.test_continueOutsideOfLoop_continueInDoStatement();
-  }
-
-  @failingTest
   void test_continueOutsideOfLoop_continueInForStatement() {
     super.test_continueOutsideOfLoop_continueInForStatement();
   }
@@ -936,11 +927,6 @@
   }
 
   @failingTest
-  void test_continueOutsideOfLoop_continueInWhileStatement() {
-    super.test_continueOutsideOfLoop_continueInWhileStatement();
-  }
-
-  @failingTest
   void test_continueOutsideOfLoop_functionExpression_inALoop() {
     super.test_continueOutsideOfLoop_functionExpression_inALoop();
   }
@@ -1769,6 +1755,7 @@
   @failingTest
   void test_missingAssignableSelector_identifiersAssigned() {
     super.test_missingAssignableSelector_identifiersAssigned();
+    dart2Failure();
   }
 
   @failingTest
@@ -1794,6 +1781,7 @@
   @failingTest
   void test_missingAssignableSelector_superPropertyAccessAssigned() {
     super.test_missingAssignableSelector_superPropertyAccessAssigned();
+    dart2Failure();
   }
 
   @failingTest
@@ -2582,6 +2570,7 @@
   @failingTest
   void test_parseAssignableExpression_expression_index() {
     super.test_parseAssignableExpression_expression_index();
+    dart2Failure();
   }
 
   @failingTest
@@ -2590,11 +2579,6 @@
   }
 
   @failingTest
-  void test_parseAssignableExpression_identifier() {
-    super.test_parseAssignableExpression_identifier();
-  }
-
-  @failingTest
   void test_parseAssignableExpression_identifier_args_dot() {
     super.test_parseAssignableExpression_identifier_args_dot();
   }
@@ -2617,11 +2601,6 @@
   }
 
   @failingTest
-  void test_parseAssignableExpression_identifier_index() {
-    super.test_parseAssignableExpression_identifier_index();
-  }
-
-  @failingTest
   void test_parseAssignableExpression_identifier_question_dot() {
     super.test_parseAssignableExpression_identifier_question_dot();
   }
@@ -2647,21 +2626,11 @@
   }
 
   @failingTest
-  void test_parseAssignableSelector_none() {
-    super.test_parseAssignableSelector_none();
-  }
-
-  @failingTest
   void test_parseAssignableSelector_question_dot() {
     super.test_parseAssignableSelector_question_dot();
   }
 
   @failingTest
-  void test_parseAwaitExpression() {
-    super.test_parseAwaitExpression();
-  }
-
-  @failingTest
   void test_parseBitwiseAndExpression_normal() {
     super.test_parseBitwiseAndExpression_normal();
   }
@@ -2819,6 +2788,7 @@
   @failingTest
   void test_parseConditionalExpression() {
     super.test_parseConditionalExpression();
+    dart2Failure();
   }
 
   @failingTest
@@ -3058,11 +3028,6 @@
   }
 
   @failingTest
-  void test_parseListOrMapLiteral_map_noType() {
-    super.test_parseListOrMapLiteral_map_noType();
-  }
-
-  @failingTest
   void test_parseListOrMapLiteral_map_type() {
     super.test_parseListOrMapLiteral_map_type();
   }
@@ -3070,11 +3035,13 @@
   @failingTest
   void test_parseLogicalAndExpression() {
     super.test_parseLogicalAndExpression();
+    dart2Failure();
   }
 
   @failingTest
   void test_parseLogicalOrExpression() {
     super.test_parseLogicalOrExpression();
+    dart2Failure();
   }
 
   @failingTest
@@ -3083,31 +3050,11 @@
   }
 
   @failingTest
-  void test_parseMapLiteral_multiple() {
-    super.test_parseMapLiteral_multiple();
-  }
-
-  @failingTest
-  void test_parseMapLiteral_single() {
-    super.test_parseMapLiteral_single();
-  }
-
-  @failingTest
   void test_parseMapLiteralEntry_complex() {
     super.test_parseMapLiteralEntry_complex();
   }
 
   @failingTest
-  void test_parseMapLiteralEntry_int() {
-    super.test_parseMapLiteralEntry_int();
-  }
-
-  @failingTest
-  void test_parseMapLiteralEntry_string() {
-    super.test_parseMapLiteralEntry_string();
-  }
-
-  @failingTest
   void test_parseMultiplicativeExpression_normal() {
     super.test_parseMultiplicativeExpression_normal();
   }
@@ -3133,11 +3080,6 @@
   }
 
   @failingTest
-  void test_parsePostfixExpression_none_indexExpression() {
-    super.test_parsePostfixExpression_none_indexExpression();
-  }
-
-  @failingTest
   void test_parsePostfixExpression_none_methodInvocation() {
     super.test_parsePostfixExpression_none_methodInvocation();
   }
@@ -3179,11 +3121,6 @@
   }
 
   @failingTest
-  void test_parsePrefixedIdentifier_noPrefix() {
-    super.test_parsePrefixedIdentifier_noPrefix();
-  }
-
-  @failingTest
   void test_parsePrefixedIdentifier_prefix() {
     super.test_parsePrefixedIdentifier_prefix();
   }
@@ -3191,8 +3128,7 @@
   @failingTest
   void test_parsePrimaryExpression_const() {
     super.test_parsePrimaryExpression_const();
-    fail(
-        'This passes under Dart 1, but fails under Dart 2 because of a cast exception');
+    dart2Failure();
   }
 
   @failingTest
@@ -3211,11 +3147,6 @@
   }
 
   @failingTest
-  void test_parsePrimaryExpression_identifier() {
-    super.test_parsePrimaryExpression_identifier();
-  }
-
-  @failingTest
   void test_parsePrimaryExpression_listLiteral_typed() {
     super.test_parsePrimaryExpression_listLiteral_typed();
   }
@@ -3321,16 +3252,6 @@
   }
 
   @failingTest
-  void test_parseSimpleIdentifier_builtInIdentifier() {
-    super.test_parseSimpleIdentifier_builtInIdentifier();
-  }
-
-  @failingTest
-  void test_parseSimpleIdentifier_normalIdentifier() {
-    super.test_parseSimpleIdentifier_normalIdentifier();
-  }
-
-  @failingTest
   void test_parseStringLiteral_endsWithInterpolation() {
     super.test_parseStringLiteral_endsWithInterpolation();
   }
@@ -3376,16 +3297,6 @@
   }
 
   @failingTest
-  void test_parseThrowExpression() {
-    super.test_parseThrowExpression();
-  }
-
-  @failingTest
-  void test_parseThrowExpressionWithoutCascade() {
-    super.test_parseThrowExpressionWithoutCascade();
-  }
-
-  @failingTest
   void test_parseUnaryExpression_decrement_normal() {
     super.test_parseUnaryExpression_decrement_normal();
   }
@@ -3431,11 +3342,6 @@
   }
 
   @failingTest
-  void test_parseUnaryExpression_not_normal() {
-    super.test_parseUnaryExpression_not_normal();
-  }
-
-  @failingTest
   void test_parseUnaryExpression_not_super() {
     super.test_parseUnaryExpression_not_super();
   }
@@ -3896,26 +3802,31 @@
   @failingTest
   void test_assignmentExpression_missing_compound1() {
     super.test_assignmentExpression_missing_compound1();
+    dart2Failure();
   }
 
   @failingTest
   void test_assignmentExpression_missing_compound2() {
     super.test_assignmentExpression_missing_compound2();
+    dart2Failure();
   }
 
   @failingTest
   void test_assignmentExpression_missing_compound3() {
     super.test_assignmentExpression_missing_compound3();
+    dart2Failure();
   }
 
   @failingTest
   void test_assignmentExpression_missing_LHS() {
     super.test_assignmentExpression_missing_LHS();
+    dart2Failure();
   }
 
   @failingTest
   void test_assignmentExpression_missing_RHS() {
     super.test_assignmentExpression_missing_RHS();
+    dart2Failure();
   }
 
   @failingTest
@@ -4041,11 +3952,13 @@
   @failingTest
   void test_conditionalExpression_missingElse() {
     super.test_conditionalExpression_missingElse();
+    dart2Failure();
   }
 
   @failingTest
   void test_conditionalExpression_missingThen() {
     super.test_conditionalExpression_missingThen();
+    dart2Failure();
   }
 
   @failingTest
@@ -4136,6 +4049,7 @@
   @failingTest
   void test_incomplete_conditionalExpression() {
     super.test_incomplete_conditionalExpression();
+    dart2Failure();
   }
 
   @failingTest
@@ -4316,16 +4230,19 @@
   @failingTest
   void test_logicalAndExpression_missing_LHS() {
     super.test_logicalAndExpression_missing_LHS();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalAndExpression_missing_LHS_RHS() {
     super.test_logicalAndExpression_missing_LHS_RHS();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalAndExpression_missing_RHS() {
     super.test_logicalAndExpression_missing_RHS();
+    dart2Failure();
   }
 
   @failingTest
@@ -4341,26 +4258,31 @@
   @failingTest
   void test_logicalOrExpression_missing_LHS() {
     super.test_logicalOrExpression_missing_LHS();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalOrExpression_missing_LHS_RHS() {
     super.test_logicalOrExpression_missing_LHS_RHS();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalOrExpression_missing_RHS() {
     super.test_logicalOrExpression_missing_RHS();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalOrExpression_precedence_logicalAnd_left() {
     super.test_logicalOrExpression_precedence_logicalAnd_left();
+    dart2Failure();
   }
 
   @failingTest
   void test_logicalOrExpression_precedence_logicalAnd_right() {
     super.test_logicalOrExpression_precedence_logicalAnd_right();
+    dart2Failure();
   }
 
   @failingTest
@@ -4825,11 +4747,6 @@
   }
 
   @failingTest
-  void test_parseReturnStatement_value() {
-    super.test_parseReturnStatement_value();
-  }
-
-  @failingTest
   void test_parseStatement_function_noReturnType() {
     super.test_parseStatement_function_noReturnType();
   }
@@ -5035,46 +4952,6 @@
   }
 
   @failingTest
-  void test_parseAssertStatement() {
-    super.test_parseAssertStatement();
-  }
-
-  @failingTest
-  void test_parseAssertStatement_messageLowPrecedence() {
-    super.test_parseAssertStatement_messageLowPrecedence();
-  }
-
-  @failingTest
-  void test_parseAssertStatement_messageString() {
-    super.test_parseAssertStatement_messageString();
-  }
-
-  @failingTest
-  void test_parseAssertStatement_trailingComma_message() {
-    super.test_parseAssertStatement_trailingComma_message();
-  }
-
-  @failingTest
-  void test_parseAssertStatement_trailingComma_noMessage() {
-    super.test_parseAssertStatement_trailingComma_noMessage();
-  }
-
-  @failingTest
-  void test_parseBreakStatement_noLabel() {
-    super.test_parseBreakStatement_noLabel();
-  }
-
-  @failingTest
-  void test_parseContinueStatement_noLabel() {
-    super.test_parseContinueStatement_noLabel();
-  }
-
-  @failingTest
-  void test_parseDoStatement() {
-    super.test_parseDoStatement();
-  }
-
-  @failingTest
   void test_parseForStatement_each_await() {
     super.test_parseForStatement_each_await();
   }
@@ -5175,38 +5052,16 @@
   }
 
   @failingTest
-  void test_parseIfStatement_else_block() {
-    super.test_parseIfStatement_else_block();
-  }
-
-  @failingTest
-  void test_parseIfStatement_else_emptyStatements() {
-    super.test_parseIfStatement_else_emptyStatements();
-    fail(
-        'This passes under Dart 1, but fails under Dart 2 because of a cast exception');
-  }
-
-  @failingTest
   void test_parseIfStatement_else_statement() {
     super.test_parseIfStatement_else_statement();
   }
 
   @failingTest
-  void test_parseIfStatement_noElse_block() {
-    super.test_parseIfStatement_noElse_block();
-  }
-
-  @failingTest
   void test_parseIfStatement_noElse_statement() {
     super.test_parseIfStatement_noElse_statement();
   }
 
   @failingTest
-  void test_parseNonLabeledStatement_const_map_nonEmpty() {
-    super.test_parseNonLabeledStatement_const_map_nonEmpty();
-  }
-
-  @failingTest
   void test_parseNonLabeledStatement_const_object() {
     super.test_parseNonLabeledStatement_const_object();
   }
@@ -5361,16 +5216,6 @@
   }
 
   @failingTest
-  void test_parseStatement_multipleLabels() {
-    super.test_parseStatement_multipleLabels();
-  }
-
-  @failingTest
-  void test_parseStatement_noLabels() {
-    super.test_parseStatement_noLabels();
-  }
-
-  @failingTest
   void test_parseStatement_singleLabel() {
     super.test_parseStatement_singleLabel();
   }
@@ -5526,11 +5371,6 @@
   }
 
   @failingTest
-  void test_parseWhileStatement() {
-    super.test_parseWhileStatement();
-  }
-
-  @failingTest
   void test_parseYieldStatement_each() {
     super.test_parseYieldStatement_each();
   }
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 35b6075..f92a657 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2403,36 +2403,6 @@
  */
 @reflectiveTest
 class ErrorParserTest extends ParserTestCase with ErrorParserTestMixin {
-  @failingTest
-  @override
-  void test_expectedListOrMapLiteral() {
-    super.test_expectedListOrMapLiteral();
-  }
-
-  @failingTest
-  @override
-  void test_invalidCommentReference__new_nonIdentifier() {
-    super.test_invalidCommentReference__new_nonIdentifier();
-  }
-
-  @failingTest
-  @override
-  void test_invalidCommentReference__new_tooMuch() {
-    super.test_invalidCommentReference__new_tooMuch();
-  }
-
-  @failingTest
-  @override
-  void test_invalidCommentReference__nonNew_nonIdentifier() {
-    super.test_invalidCommentReference__nonNew_nonIdentifier();
-  }
-
-  @failingTest
-  @override
-  void test_invalidCommentReference__nonNew_tooMuch() {
-    super.test_invalidCommentReference__nonNew_tooMuch();
-  }
-
   void test_missingIdentifier_number() {
     createParser('1');
     SimpleIdentifier expression = parser.parseSimpleIdentifier();
@@ -3249,6 +3219,7 @@
     expectNotNullIfNoErrors(literal);
   }
 
+  @failingTest
   void test_expectedListOrMapLiteral() {
     // It isn't clear that this test can ever pass. The parser is currently
     // create a synthetic list literal in this case, but isSynthetic() isn't
@@ -4032,6 +4003,7 @@
     expectNotNullIfNoErrors(literal);
   }
 
+  @failingTest
   void test_invalidCommentReference__new_nonIdentifier() {
     // This test fails because the method parseCommentReference returns null.
     createParser('');
@@ -4041,6 +4013,7 @@
         [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 6)]);
   }
 
+  @failingTest
   void test_invalidCommentReference__new_tooMuch() {
     createParser('');
     CommentReference reference = parser.parseCommentReference('new a.b.c.d', 0);
@@ -4049,6 +4022,7 @@
         [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 11)]);
   }
 
+  @failingTest
   void test_invalidCommentReference__nonNew_nonIdentifier() {
     // This test fails because the method parseCommentReference returns null.
     createParser('');
@@ -4058,6 +4032,7 @@
         [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 2)]);
   }
 
+  @failingTest
   void test_invalidCommentReference__nonNew_tooMuch() {
     createParser('');
     CommentReference reference = parser.parseCommentReference('a.b.c.d', 0);
@@ -15720,7 +15695,7 @@
   void test_parseTryStatement_catch_error_missingCatchTrace() {
     var statement = parseStatement('try {} catch (e,) {}') as TryStatement;
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 14, 1)]
+        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 16, 1)]
         : [
             expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
           ]);
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 3604aed..4ede46d 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -24,6 +24,11 @@
  */
 class EngineTestCase {
   /**
+   * Flag indicating whether the fasta parser is being used.
+   */
+  bool get usingFastaParser => Parser.useFasta;
+
+  /**
    * Assert that the given collection has the same number of elements as the number of specified
    * names, and that for each specified name, a corresponding element can be found in the given
    * collection with that name.
diff --git a/pkg/analyzer/test/parse_compilation_unit_test.dart b/pkg/analyzer/test/parse_compilation_unit_test.dart
index 87f441d..b7179ab 100644
--- a/pkg/analyzer/test/parse_compilation_unit_test.dart
+++ b/pkg/analyzer/test/parse_compilation_unit_test.dart
@@ -39,4 +39,10 @@
         parseFunctionBodies: false);
     expect(unit.toString(), equals("void main();"));
   });
+
+  test("allows you to specify whether or not to parse function bodies 2", () {
+    var unit = parseCompilationUnit("void main() { print('Hello, world!'); }",
+        parseFunctionBodies: false);
+    expect(unit.toString(), equals("void main();"));
+  });
 }
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index f95bd63..e49e2fb 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -451,7 +451,7 @@
 ];
 
 class MockSdk implements DartSdk {
-  static const Map<String, String> FULL_URI_MAP = const {
+  static const Map<String, String> _URI_MAP = const {
     "dart:core": "$sdkRoot/lib/core/core.dart",
     "dart:html": "$sdkRoot/lib/html/dartium/html_dartium.dart",
     "dart:async": "$sdkRoot/lib/async/async.dart",
@@ -465,13 +465,9 @@
     "dart:math": "$sdkRoot/lib/math/math.dart"
   };
 
-  static const Map<String, String> NO_ASYNC_URI_MAP = const {
-    "dart:core": "$sdkRoot/lib/core/core.dart",
-  };
-
   final resource.MemoryResourceProvider provider;
 
-  final Map<String, String> uriMap;
+  final Map<String, String> uriMap = {};
 
   /**
    * The [AnalysisContextImpl] which is used for all of the sources.
@@ -479,7 +475,7 @@
   AnalysisContextImpl _analysisContext;
 
   @override
-  final List<SdkLibrary> sdkLibraries;
+  final List<SdkLibrary> sdkLibraries = [];
 
   /**
    * The cached linked bundle of the SDK.
@@ -488,15 +484,21 @@
 
   MockSdk(
       {bool generateSummaryFiles: false,
-      bool dartAsync: true,
       resource.MemoryResourceProvider resourceProvider})
-      : provider = resourceProvider ?? new resource.MemoryResourceProvider(),
-        sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
-        uriMap = dartAsync ? FULL_URI_MAP : NO_ASYNC_URI_MAP {
+      : provider = resourceProvider ?? new resource.MemoryResourceProvider() {
+    _URI_MAP.forEach((uri, path) {
+      uriMap[uri] = provider.convertPath(path);
+    });
+
+    for (_MockSdkLibrary library in _LIBRARIES) {
+      var convertedLibrary = library._toProvider(provider);
+      sdkLibraries.add(convertedLibrary);
+    }
+
     for (_MockSdkLibrary library in sdkLibraries) {
-      provider.newFile(provider.convertPath(library.path), library.content);
+      provider.newFile(library.path, library.content);
       library.parts.forEach((String path, String content) {
-        provider.newFile(provider.convertPath(path), content);
+        provider.newFile(path, content);
       });
     }
     provider.newFile(
@@ -536,7 +538,7 @@
       return null;
     }
     for (SdkLibrary library in sdkLibraries) {
-      String libraryPath = provider.convertPath(library.path);
+      String libraryPath = library.path;
       if (filePath == libraryPath) {
         try {
           resource.File file = provider.getResource(filePath);
@@ -593,7 +595,7 @@
   Source mapDartUri(String dartUri) {
     String path = uriMap[dartUri];
     if (path != null) {
-      resource.File file = provider.getResource(provider.convertPath(path));
+      resource.File file = provider.getResource(path);
       Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5));
       return file.createSource(uri);
     }
@@ -603,20 +605,6 @@
   }
 
   /**
-   * This method is used to apply patches to [MockSdk].  It may be called only
-   * before analysis, i.e. before the analysis context was created.
-   */
-  void updateUriFile(String uri, String updateContent(String content)) {
-    assert(_analysisContext == null);
-    String path = FULL_URI_MAP[uri];
-    assert(path != null);
-    path = provider.convertPath(path);
-    String content = provider.getFile(path).readAsStringSync();
-    String newContent = updateContent(content);
-    provider.updateFile(path, newContent);
-  }
-
-  /**
    * Compute the bytes of the linked bundle associated with this SDK.
    */
   List<int> _computeLinkedBundleBytes() {
@@ -658,6 +646,18 @@
 
   @override
   bool get isVmLibrary => throw new UnimplementedError();
+
+  _MockSdkLibrary _toProvider(resource.MemoryResourceProvider provider) {
+    return new _MockSdkLibrary(
+      shortName,
+      provider.convertPath(path),
+      content,
+      parts.map((path, content) {
+        var convertedPath = provider.convertPath(path);
+        return new MapEntry(convertedPath, content);
+      }),
+    );
+  }
 }
 
 /**
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index cb583d2..3804ff6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -570,7 +570,8 @@
 
     // Simulate a change that happens during reading the cached errors.
     bool asyncWorkExecuted = false;
-    driver.test.workToWaitAfterComputingResult = (path) {
+    driver.test.workToWaitAfterComputingResult = (path) async {
+      await new Future.value(); // the rest will be executed asynchronously
       provider.updateFile(path, 'class B');
       driver.changeFile(path);
       asyncWorkExecuted = true;
@@ -1107,6 +1108,53 @@
     expect(session2, isNot(session1));
   }
 
+  test_discoverAvailableFiles_packages() async {
+    var t = _p('/test/lib/test.dart');
+    var a1 = _p('/aaa/lib/a1.dart');
+    var a2 = _p('/aaa/lib/src/a2.dart');
+    var a3 = _p('/aaa/lib/a3.txt');
+    var b = _p('/bbb/lib/b.dart');
+    var c = _p('/ccc/lib/c.dart');
+
+    provider.newFile(t, 'class T {}');
+    provider.newFile(a1, 'class A1 {}');
+    provider.newFile(a2, 'class A2 {}');
+    provider.newFile(a3, 'text');
+    provider.newFile(b, 'class B {}');
+    provider.newFile(c, 'class C {}');
+
+    driver.addFile(t);
+    // Don't add a1.dart, a2.dart, or b.dart - they should be discovered.
+    // And c.dart is not in .packages, so should not be discovered.
+
+    await driver.discoverAvailableFiles();
+
+    expect(driver.knownFiles, contains(t));
+    expect(driver.knownFiles, contains(a1));
+    expect(driver.knownFiles, contains(a2));
+    expect(driver.knownFiles, isNot(contains(a3)));
+    expect(driver.knownFiles, contains(b));
+    expect(driver.knownFiles, isNot(contains(c)));
+
+    // We call wait for discovery more than once.
+    await driver.discoverAvailableFiles();
+  }
+
+  test_discoverAvailableFiles_sdk() async {
+    await driver.discoverAvailableFiles();
+
+    void assertHasDartUri(String uri) {
+      var file = sdk.mapDartUri(uri).fullName;
+      expect(driver.knownFiles, contains(file));
+    }
+
+    assertHasDartUri('dart:async');
+    assertHasDartUri('dart:collection');
+    assertHasDartUri('dart:convert');
+    assertHasDartUri('dart:core');
+    assertHasDartUri('dart:math');
+  }
+
   test_errors_uriDoesNotExist_export() async {
     addTestFile(r'''
 export 'foo.dart';
@@ -1374,6 +1422,26 @@
     expect(files2, unorderedEquals([b, c]));
   }
 
+  test_getFilesReferencingName_discover() async {
+    var t = _p('/test/lib/test.dart');
+    var a = _p('/aaa/lib/a.dart');
+    var b = _p('/bbb/lib/b.dart');
+    var c = _p('/ccc/lib/c.dart');
+
+    provider.newFile(t, 'int t;');
+    provider.newFile(a, 'int a;');
+    provider.newFile(b, 'int b;');
+    provider.newFile(c, 'int c;');
+
+    driver.addFile(t);
+
+    List<String> files = await driver.getFilesReferencingName('int');
+    expect(files, contains(t));
+    expect(files, contains(a));
+    expect(files, contains(b));
+    expect(files, isNot(contains(c)));
+  }
+
   test_getIndex() async {
     String content = r'''
 foo(int p) {}
@@ -1987,7 +2055,7 @@
         await driver.getTopLevelNameDeclarations('X'), [], []);
   }
 
-  test_getTopLevelNameDeclarations_discoverAvailable() async {
+  test_getTopLevelNameDeclarations_discover() async {
     var t = _p('/test/lib/test.dart');
     var a1 = _p('/aaa/lib/a1.dart');
     var a2 = _p('/aaa/lib/src/a2.dart');
@@ -2240,7 +2308,8 @@
   }
 
   test_missingDartLibrary_async() async {
-    provider.getFile(_p(MockSdk.FULL_URI_MAP['dart:async'])).delete();
+    var asyncPath = sdk.mapDartUri('dart:async').fullName;
+    provider.getFile(asyncPath).delete();
     addTestFile('class C {}');
 
     ErrorsResult result = await driver.getErrors(testFile);
@@ -2251,7 +2320,8 @@
   }
 
   test_missingDartLibrary_core() async {
-    provider.getFile(_p(MockSdk.FULL_URI_MAP['dart:core'])).delete();
+    var corePath = sdk.mapDartUri('dart:core').fullName;
+    provider.getFile(corePath).delete();
     addTestFile('class C {}');
 
     ErrorsResult result = await driver.getErrors(testFile);
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 52cadae..ac55908 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart' hide Declaration;
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
@@ -109,7 +110,7 @@
   void m() {}
 }
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files);
     _assertHasDeclaration(declarations, 'C', DeclarationKind.CLASS,
@@ -128,13 +129,52 @@
         offset: 83, codeOffset: 78, codeLength: 11, className: 'C');
   }
 
+  test_declarations_discover() async {
+    var t = _p('/test/lib/t.dart');
+    var a = _p('/aaa/lib/a.dart');
+    var b = _p('/bbb/lib/b.dart');
+    var c = _p('/ccc/lib/c.dart');
+
+    provider.newFile(t, 'class T {}');
+    provider.newFile(a, 'class A {}');
+    provider.newFile(b, 'class B {}');
+    provider.newFile(c, 'class C {}');
+
+    driver.addFile(t);
+
+    var files = new LinkedHashSet<String>();
+    var declarations = await driver.search.declarations(null, null, files);
+    _assertHasDeclaration(declarations, 'T', DeclarationKind.CLASS);
+    _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS);
+    _assertHasDeclaration(declarations, 'B', DeclarationKind.CLASS);
+    _assertNoDeclaration(declarations, 'C');
+  }
+
+  test_declarations_duplicateFile() async {
+    var a = _p('/test/lib/a.dart');
+    var b = _p('/test/lib/b.dart');
+
+    provider.newFile(a, 'class A {}');
+    provider.newFile(b, 'class B {}');
+
+    driver.addFile(a);
+    driver.addFile(b);
+
+    var files = new LinkedHashSet<String>();
+    files.add(b);
+
+    var declarations = await driver.search.declarations(null, null, files);
+    _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS);
+    _assertNoDeclaration(declarations, 'B');
+  }
+
   test_declarations_enum() async {
     await _resolveTestUnit('''
 enum E {
   a, bb, ccc
 }
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files);
     _assertHasDeclaration(declarations, 'E', DeclarationKind.ENUM,
@@ -153,7 +193,7 @@
 class B {}
 class C {}
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, 2, files);
     expect(declarations, hasLength(2));
@@ -168,7 +208,7 @@
     driver.addFile(a);
     driver.addFile(b);
 
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files, onlyForFile: b);
 
@@ -188,7 +228,7 @@
 typedef F(int a);
 typedef T F2<T, U>(U a);
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files);
 
@@ -228,7 +268,7 @@
 void f3(bool Function(int a, String b) c) {}
 void f4(bool Function(int, String) a) {}
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files);
 
@@ -259,7 +299,7 @@
   void m3<U1, U2>(Map<Map<T2, U2>, Map<U1, T>> a) {}
 }
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files);
 
@@ -288,7 +328,7 @@
 class C {}
 class D {}
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(new RegExp(r'[A-C]'), null, files);
     _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS);
@@ -306,7 +346,7 @@
 typedef void tf1();
 typedef tf2<T> = int Function<S>(T tp, S sp);
 ''');
-    var files = <String>[];
+    var files = new LinkedHashSet<String>();
     List<Declaration> declarations =
         await driver.search.declarations(null, null, files);
     _assertHasDeclaration(declarations, 'g', DeclarationKind.GETTER,
@@ -339,6 +379,75 @@
     _assertNoDeclaration(declarations, 'sp');
   }
 
+  test_references_discover() async {
+    var t = _p('/test/lib/t.dart');
+    var a = _p('/aaa/lib/a.dart');
+    var b = _p('/bbb/lib/b.dart');
+    var c = _p('/ccc/lib/c.dart');
+
+    provider.newFile(t, 'List t;');
+    provider.newFile(a, 'List a;');
+    provider.newFile(b, 'List b;');
+    provider.newFile(c, 'List c;');
+
+    driver.addFile(t);
+
+    LibraryElement coreLib = await driver.getLibraryByUri('dart:core');
+    ClassElement listElement = coreLib.getType('List');
+
+    var searchedFiles = new SearchedFiles();
+    var results = await driver.search.references(listElement, searchedFiles);
+
+    void assertHasResult(String path, String name, {bool not: false}) {
+      var matcher = contains(predicate((SearchResult r) {
+        var element = r.enclosingElement;
+        return element.name == name && element.source.fullName == path;
+      }));
+      expect(results, not ? isNot(matcher) : matcher);
+    }
+
+    assertHasResult(t, 't');
+    assertHasResult(a, 'a');
+    assertHasResult(b, 'b');
+    assertHasResult(c, 'c', not: true);
+  }
+
+  test_references_discover_onlyOwned() async {
+    var t = _p('/test/lib/t.dart');
+    var a = _p('/aaa/lib/a.dart');
+    var b = _p('/bbb/lib/b.dart');
+
+    provider.newFile(t, 'List t;');
+    provider.newFile(a, 'List a;');
+    provider.newFile(b, 'List b;');
+
+    driver.addFile(t);
+    driver.addFile(a);
+
+    LibraryElement coreLib = await driver.getLibraryByUri('dart:core');
+    ClassElement listElement = coreLib.getType('List');
+
+    var searchedFiles = new SearchedFiles();
+
+    // Make b.dart owned by a different driver.
+    var driver2 = createAnalysisDriver();
+    searchedFiles.add(b, driver2.search);
+
+    var results = await driver.search.references(listElement, searchedFiles);
+
+    void assertHasResult(String path, String name, {bool not: false}) {
+      var matcher = contains(predicate((SearchResult r) {
+        var element = r.enclosingElement;
+        return element.name == name && element.source.fullName == path;
+      }));
+      expect(results, not ? isNot(matcher) : matcher);
+    }
+
+    assertHasResult(t, 't');
+    assertHasResult(a, 'a');
+    assertHasResult(b, 'b', not: true);
+  }
+
   test_searchMemberReferences_qualified_resolved() async {
     await _resolveTestUnit('''
 class C {
@@ -1398,6 +1507,39 @@
     }
   }
 
+  test_subTypes_discover() async {
+    var t = _p('/test/lib/t.dart');
+    var a = _p('/aaa/lib/a.dart');
+    var b = _p('/bbb/lib/b.dart');
+    var c = _p('/ccc/lib/c.dart');
+
+    provider.newFile(t, 'class T implements List {}');
+    provider.newFile(a, 'class A implements List {}');
+    provider.newFile(b, 'class B implements List {}');
+    provider.newFile(c, 'class C implements List {}');
+
+    driver.addFile(t);
+
+    LibraryElement coreLib = await driver.getLibraryByUri('dart:core');
+    ClassElement listElement = coreLib.getType('List');
+
+    var searchedFiles = new SearchedFiles();
+    var results = await driver.search.subTypes(listElement, searchedFiles);
+
+    void assertHasResult(String path, String name, {bool not: false}) {
+      var matcher = contains(predicate((SearchResult r) {
+        var element = r.enclosingElement;
+        return element.name == name && element.source.fullName == path;
+      }));
+      expect(results, not ? isNot(matcher) : matcher);
+    }
+
+    assertHasResult(t, 'T');
+    assertHasResult(a, 'A');
+    assertHasResult(b, 'B');
+    assertHasResult(c, 'C', not: true);
+  }
+
   test_subtypes_files() async {
     String pathB = _p('$testProject/b.dart');
     String pathC = _p('$testProject/c.dart');
@@ -1542,15 +1684,17 @@
 
   Future<Null> _verifyNameReferences(
       String name, List<ExpectedResult> expectedMatches) async {
+    var searchedFiles = new SearchedFiles();
     List<SearchResult> results =
-        await driver.search.unresolvedMemberReferences(name);
+        await driver.search.unresolvedMemberReferences(name, searchedFiles);
     _assertResults(results, expectedMatches);
     expect(results, hasLength(expectedMatches.length));
   }
 
   Future _verifyReferences(
       Element element, List<ExpectedResult> expectedMatches) async {
-    List<SearchResult> results = await driver.search.references(element);
+    var searchedFiles = new SearchedFiles();
+    var results = await driver.search.references(element, searchedFiles);
     _assertResults(results, expectedMatches);
     expect(results, hasLength(expectedMatches.length));
   }
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
new file mode 100644
index 0000000..8c1e001
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -0,0 +1,997 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FunctionTypeTest);
+  });
+}
+
+DynamicTypeImpl get dynamicType => DynamicTypeImpl.instance;
+
+VoidTypeImpl get voidType => VoidTypeImpl.instance;
+
+Element getBaseElement(Element e) {
+  if (e is Member) {
+    return e.baseElement;
+  } else {
+    return e;
+  }
+}
+
+@reflectiveTest
+class FunctionTypeTest {
+  static const bug_33294_fixed = false;
+  static const bug_33300_fixed = false;
+  static const bug_33301_fixed = false;
+  static const bug_33302_fixed = false;
+
+  final objectType = new InterfaceTypeImpl(new MockClassElement('Object'));
+
+  final mapType = _makeMapType();
+
+  final listType = _makeListType();
+
+  void basicChecks(FunctionType f,
+      {element,
+      displayName: '() → dynamic',
+      returnType,
+      namedParameterTypes: isEmpty,
+      normalParameterNames: isEmpty,
+      normalParameterTypes: isEmpty,
+      optionalParameterNames: isEmpty,
+      optionalParameterTypes: isEmpty,
+      parameters: isEmpty,
+      typeFormals: isEmpty,
+      typeArguments: isEmpty,
+      typeParameters: isEmpty,
+      name: isNull}) {
+    // DartType properties
+    expect(f.displayName, displayName, reason: 'displayName');
+    expect(f.element, element);
+    expect(f.name, name, reason: 'name');
+    // ParameterizedType properties
+    expect(f.typeArguments, typeArguments, reason: 'typeArguments');
+    expect(f.typeParameters, typeParameters, reason: 'typeParameters');
+    // FunctionType properties
+    expect(f.namedParameterTypes, namedParameterTypes);
+    expect(f.normalParameterNames, normalParameterNames,
+        reason: 'normalParameterNames');
+    expect(f.normalParameterTypes, normalParameterTypes);
+    expect(f.optionalParameterNames, optionalParameterNames);
+    expect(f.optionalParameterTypes, optionalParameterTypes);
+    expect(f.parameters, parameters);
+    expect(f.returnType, returnType ?? same(dynamicType), reason: 'returnType');
+    expect(f.typeFormals, typeFormals, reason: 'typeFormals');
+  }
+
+  DartType listOf(DartType elementType) => listType.instantiate([elementType]);
+
+  DartType mapOf(DartType keyType, DartType valueType) =>
+      mapType.instantiate([keyType, valueType]);
+
+  test_unnamedConstructor_nonTypedef_noTypeArguments() {
+    var e = new MockFunctionTypedElement();
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f, element: same(e));
+  }
+
+  test_unnamedConstructor_nonTypedef_withTypeArguments() {
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var e = new MockMethodElement(c, returnType: t.type);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        typeArguments: [same(t.type)],
+        typeParameters: [same(t)],
+        displayName: '() → T',
+        returnType: same(t.type));
+  }
+
+  test_forInstantiatedTypedef_bothTypeParameters() {
+    var t = new MockTypeParameterElement('T');
+    var u = new MockTypeParameterElement('U');
+    var e = new MockGenericTypeAliasElement('F',
+        typeParameters: [t],
+        innerTypeParameters: [u],
+        returnType: mapOf(t.type, u.type));
+    FunctionType f =
+        new FunctionTypeImpl.forTypedef(e, typeArguments: [objectType]);
+    basicChecks(f,
+        element: same(e),
+        displayName: 'F<Object>',
+        name: 'F',
+        typeArguments: [same(objectType)],
+        typeParameters: [same(t)],
+        returnType: mapOf(objectType, u.type));
+  }
+
+  test_forInstantiatedTypedef_innerTypeParameter() {
+    var t = new MockTypeParameterElement('T');
+    var e = new MockGenericTypeAliasElement('F',
+        innerTypeParameters: [t], returnType: t.type);
+    FunctionType f = new FunctionTypeImpl.forTypedef(e, typeArguments: []);
+    basicChecks(f,
+        element: same(e),
+        displayName: 'F',
+        name: 'F',
+        returnType: same(t.type));
+  }
+
+  test_forInstantiatedTypedef_noTypeParameters() {
+    var e = new MockGenericTypeAliasElement('F');
+    FunctionType f = new FunctionTypeImpl.forTypedef(e, typeArguments: []);
+    basicChecks(f, element: same(e), displayName: 'F', name: 'F');
+  }
+
+  test_forInstantiatedTypedef_outerTypeParameters() {
+    var t = new MockTypeParameterElement('T');
+    var e = new MockGenericTypeAliasElement('F',
+        typeParameters: [t], returnType: t.type);
+    FunctionType f =
+        new FunctionTypeImpl.forTypedef(e, typeArguments: [objectType]);
+    basicChecks(f,
+        element: same(e),
+        displayName: 'F<Object>',
+        name: 'F',
+        typeArguments: [same(objectType)],
+        typeParameters: [same(t)],
+        returnType: same(objectType));
+  }
+
+  test_forTypedef() {
+    var e = new MockGenericTypeAliasElement('F');
+    basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
+    basicChecks(e.function.type,
+        element: same(e.function), displayName: '() → dynamic');
+  }
+
+  test_forTypedef_innerAndOuterTypeParameter() {
+    // typedef F<T> = T Function<U>(U p);
+    var t = new MockTypeParameterElement('T');
+    var u = new MockTypeParameterElement('U');
+    var p = new MockParameterElement('p', type: u.type);
+    var e = new MockGenericTypeAliasElement('F',
+        typeParameters: [t],
+        innerTypeParameters: [u],
+        returnType: t.type,
+        parameters: [p]);
+    basicChecks(e.type,
+        element: same(e),
+        displayName: 'F',
+        name: 'F',
+        returnType: same(t.type),
+        normalParameterTypes: [same(u.type)],
+        normalParameterNames: ['p'],
+        parameters: [same(p)],
+        typeFormals: [same(t)]);
+    basicChecks(e.function.type,
+        element: same(e.function),
+        displayName: '<U>(U) → T',
+        returnType: same(t.type),
+        typeArguments: [same(t.type)],
+        typeParameters: [same(t)],
+        typeFormals: [same(u)],
+        normalParameterTypes: [same(u.type)],
+        normalParameterNames: ['p'],
+        parameters: [same(p)]);
+  }
+
+  test_forTypedef_innerAndOuterTypeParameter_instantiate() {
+    // typedef F<T> = T Function<U>(U p);
+    var t = new MockTypeParameterElement('T');
+    var u = new MockTypeParameterElement('U');
+    var p = new MockParameterElement('p', type: u.type);
+    var e = new MockGenericTypeAliasElement('F',
+        typeParameters: [t],
+        innerTypeParameters: [u],
+        returnType: t.type,
+        parameters: [p]);
+    var instantiated = e.type.instantiate([objectType]);
+    basicChecks(instantiated,
+        element: same(e),
+        displayName: 'F<Object>',
+        name: 'F',
+        returnType: same(objectType),
+        normalParameterTypes: [same(u.type)],
+        normalParameterNames: ['p'],
+        parameters: [same(p)],
+        typeFormals: isNotNull,
+        typeArguments: [same(objectType)],
+        typeParameters: [same(t)]);
+    if (bug_33294_fixed) {
+      expect(instantiated.typeFormals, [same(u)]);
+    } else {
+      expect(instantiated.typeFormals, isEmpty);
+    }
+  }
+
+  test_forTypedef_innerTypeParameter() {
+    // typedef F = T Function<T>();
+    var t = new MockTypeParameterElement('T');
+    var e = new MockGenericTypeAliasElement('F',
+        innerTypeParameters: [t], returnType: t.type);
+    basicChecks(e.type,
+        element: same(e),
+        displayName: 'F',
+        name: 'F',
+        returnType: same(t.type));
+    basicChecks(e.function.type,
+        element: same(e.function),
+        displayName: '<T>() → T',
+        returnType: same(t.type),
+        typeFormals: [same(t)]);
+  }
+
+  test_forTypedef_normalParameter() {
+    var p = new MockParameterElement('p');
+    var e = new MockGenericTypeAliasElement('F', parameters: [p]);
+    basicChecks(e.type,
+        element: same(e),
+        displayName: 'F',
+        name: 'F',
+        normalParameterNames: ['p'],
+        normalParameterTypes: [same(dynamicType)],
+        parameters: [same(p)]);
+    basicChecks(e.function.type,
+        element: same(e.function),
+        displayName: '(dynamic) → dynamic',
+        normalParameterNames: ['p'],
+        normalParameterTypes: [same(dynamicType)],
+        parameters: [same(p)]);
+  }
+
+  test_forTypedef_recursive_via_interfaceTypes() {
+    // typedef F = List<G> Function();
+    // typedef G = List<F> Function();
+    var f = new MockGenericTypeAliasElement('F');
+    var g = new MockGenericTypeAliasElement('G');
+    f.returnType = listOf(g.function.type);
+    g.returnType = listOf(f.function.type);
+    basicChecks(f.type,
+        element: same(f), displayName: 'F', name: 'F', returnType: isNotNull);
+    var fReturn = f.type.returnType;
+    expect(fReturn.element, same(listType.element));
+    if (bug_33302_fixed) {
+      expect(fReturn.displayName, 'List<G>');
+    } else {
+      expect(fReturn.displayName, 'List<() → List<...>>');
+    }
+    var fReturnArg = (fReturn as InterfaceType).typeArguments[0];
+    expect(fReturnArg.element, same(g.function));
+    var fReturnArgReturn = (fReturnArg as FunctionType).returnType;
+    expect(fReturnArgReturn.element, same(listType.element));
+    expect((fReturnArgReturn as InterfaceType).typeArguments[0],
+        new isInstanceOf<CircularFunctionTypeImpl>());
+    basicChecks(f.function.type,
+        element: same(f.function), displayName: isNotNull, returnType: fReturn);
+    if (bug_33302_fixed) {
+      expect(f.function.type.displayName, '() → List<G>');
+    } else {
+      expect(f.function.type.displayName, '() → List<() → List<...>>');
+    }
+    basicChecks(g.type,
+        element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
+    var gReturn = g.type.returnType;
+    expect(gReturn.element, same(listType.element));
+    if (bug_33302_fixed) {
+      expect(gReturn.displayName, 'List<F>');
+    } else {
+      expect(gReturn.displayName, 'List<() → List<...>>');
+    }
+    var gReturnArg = (gReturn as InterfaceType).typeArguments[0];
+    expect(gReturnArg.element, same(f.function));
+    var gReturnArgReturn = (gReturnArg as FunctionType).returnType;
+    expect(gReturnArgReturn.element, same(listType.element));
+    expect((gReturnArgReturn as InterfaceType).typeArguments[0],
+        new isInstanceOf<CircularFunctionTypeImpl>());
+    basicChecks(g.function.type,
+        element: same(g.function), displayName: isNotNull, returnType: gReturn);
+    if (bug_33302_fixed) {
+      expect(g.function.type.displayName, '() → F');
+    } else {
+      expect(g.function.type.displayName, '() → List<() → List<...>>');
+    }
+  }
+
+  test_forTypedef_recursive_via_parameterTypes() {
+    // typedef F = void Function(G g);
+    // typedef G = void Function(F f);
+    var f = new MockGenericTypeAliasElement('F', returnType: voidType);
+    var g = new MockGenericTypeAliasElement('G', returnType: voidType);
+    f.parameters = [new MockParameterElement('g', type: g.function.type)];
+    g.parameters = [new MockParameterElement('f', type: f.function.type)];
+    basicChecks(f.type,
+        element: same(f),
+        displayName: 'F',
+        name: 'F',
+        parameters: hasLength(1),
+        normalParameterTypes: hasLength(1),
+        normalParameterNames: ['g'],
+        returnType: same(voidType));
+    var fParamType = f.type.normalParameterTypes[0];
+    expect(fParamType.element, same(g.function));
+    expect((fParamType as FunctionType).normalParameterTypes[0],
+        new isInstanceOf<CircularFunctionTypeImpl>());
+    basicChecks(f.function.type,
+        element: same(f.function),
+        displayName: isNotNull,
+        parameters: hasLength(1),
+        normalParameterTypes: [fParamType],
+        normalParameterNames: ['g'],
+        returnType: same(voidType));
+    if (bug_33302_fixed) {
+      expect(f.function.type.displayName, '(G) → void');
+    } else {
+      expect(f.function.type.displayName, '((...) → void) → void');
+    }
+    basicChecks(g.type,
+        element: same(g),
+        displayName: 'G',
+        name: 'G',
+        parameters: hasLength(1),
+        normalParameterTypes: hasLength(1),
+        normalParameterNames: ['f'],
+        returnType: same(voidType));
+    var gParamType = g.type.normalParameterTypes[0];
+    expect(gParamType.element, same(f.function));
+    expect((gParamType as FunctionType).normalParameterTypes[0],
+        new isInstanceOf<CircularFunctionTypeImpl>());
+    basicChecks(g.function.type,
+        element: same(g.function),
+        displayName: isNotNull,
+        parameters: hasLength(1),
+        normalParameterTypes: [gParamType],
+        normalParameterNames: ['f'],
+        returnType: same(voidType));
+    if (bug_33302_fixed) {
+      expect(g.function.type.displayName, '(F) → void');
+    } else {
+      expect(g.function.type.displayName, '((...) → void) → void');
+    }
+  }
+
+  test_forTypedef_recursive_via_returnTypes() {
+    // typedef F = G Function();
+    // typedef G = F Function();
+    var f = new MockGenericTypeAliasElement('F');
+    var g = new MockGenericTypeAliasElement('G');
+    f.returnType = g.function.type;
+    g.returnType = f.function.type;
+    basicChecks(f.type,
+        element: same(f), displayName: 'F', name: 'F', returnType: isNotNull);
+    var fReturn = f.type.returnType;
+    expect(fReturn.element, same(g.function));
+    expect((fReturn as FunctionType).returnType,
+        new isInstanceOf<CircularFunctionTypeImpl>());
+    basicChecks(f.function.type,
+        element: same(f.function), displayName: isNotNull, returnType: fReturn);
+    if (bug_33302_fixed) {
+      expect(f.function.type.displayName, '() → G');
+    } else {
+      expect(f.function.type.displayName, '() → () → ...');
+    }
+    basicChecks(g.type,
+        element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
+    var gReturn = g.type.returnType;
+    expect(gReturn.element, same(f.function));
+    expect((gReturn as FunctionType).returnType,
+        new isInstanceOf<CircularFunctionTypeImpl>());
+    basicChecks(g.function.type,
+        element: same(g.function), displayName: isNotNull, returnType: gReturn);
+    if (bug_33302_fixed) {
+      expect(g.function.type.displayName, '() → F');
+    } else {
+      expect(g.function.type.displayName, '() → () → ...');
+    }
+  }
+
+  test_forTypedef_returnType() {
+    var e = new MockGenericTypeAliasElement('F', returnType: objectType);
+    basicChecks(e.type,
+        element: same(e), displayName: 'F', name: 'F', returnType: objectType);
+    basicChecks(e.function.type,
+        element: same(e.function),
+        displayName: '() → Object',
+        returnType: objectType);
+  }
+
+  test_forTypedef_returnType_null() {
+    var e = new MockGenericTypeAliasElement.withNullReturn('F');
+    basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
+    basicChecks(e.function.type,
+        element: same(e.function), displayName: '() → dynamic');
+  }
+
+  test_forTypedef_typeParameter() {
+    // typedef F<T> = T Function();
+    var t = new MockTypeParameterElement('T');
+    var e = new MockGenericTypeAliasElement('F',
+        typeParameters: [t], returnType: t.type);
+    basicChecks(e.type,
+        element: same(e),
+        displayName: 'F',
+        name: 'F',
+        returnType: same(t.type),
+        typeFormals: [same(t)]);
+    basicChecks(e.function.type,
+        element: same(e.function),
+        displayName: '() → T',
+        returnType: same(t.type),
+        typeArguments: [same(t.type)],
+        typeParameters: [same(t)]);
+  }
+
+  test_unnamedConstructor() {
+    var e = new MockFunctionTypedElement();
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f, element: same(e));
+  }
+
+  test_unnamedConstructor_instantiate_noop() {
+    var t = new MockTypeParameterElement('T');
+    var p = new MockParameterElement('x', type: t.type);
+    var e = new MockFunctionTypedElement(typeParameters: [t], parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    var instantiated = f.instantiate([t.type]);
+    basicChecks(instantiated,
+        element: same(e),
+        displayName: '(T) → dynamic',
+        typeArguments: hasLength(1),
+        typeParameters: [same(t)],
+        normalParameterNames: ['x'],
+        normalParameterTypes: [same(t.type)],
+        parameters: [same(p)]);
+    expect(instantiated.typeArguments[0], same(t.type));
+    // TODO(paulberry): test instantiate length mismatch
+  }
+
+  test_unnamedConstructor_instantiate_noTypeParameters() {
+    var e = new MockFunctionTypedElement();
+    FunctionType f = new FunctionTypeImpl(e);
+    expect(f.instantiate([]), same(f));
+  }
+
+  test_unnamedConstructor_instantiate_parameterType_simple() {
+    var t = new MockTypeParameterElement('T');
+    var p = new MockParameterElement('x', type: t.type);
+    var e = new MockFunctionTypedElement(typeParameters: [t], parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    var instantiated = f.instantiate([objectType]);
+    basicChecks(instantiated,
+        element: same(e),
+        displayName: '(Object) → dynamic',
+        typeArguments: hasLength(1),
+        typeParameters: [same(t)],
+        normalParameterNames: ['x'],
+        normalParameterTypes: [same(objectType)],
+        parameters: hasLength(1));
+    expect(instantiated.typeArguments[0], same(objectType));
+    expect(instantiated.parameters[0].name, 'x');
+    expect(instantiated.parameters[0].type, same(objectType));
+  }
+
+  test_unnamedConstructor_instantiate_returnType_simple() {
+    var t = new MockTypeParameterElement('T');
+    var e =
+        new MockFunctionTypedElement(typeParameters: [t], returnType: t.type);
+    FunctionType f = new FunctionTypeImpl(e);
+    var instantiated = f.instantiate([objectType]);
+    basicChecks(instantiated,
+        element: same(e),
+        displayName: '() → Object',
+        typeArguments: hasLength(1),
+        typeParameters: [same(t)],
+        returnType: same(objectType));
+    expect(instantiated.typeArguments[0], same(objectType));
+  }
+
+  test_unnamedConstructor_namedParameter() {
+    var p = new MockParameterElement('x', parameterKind: ParameterKind.NAMED);
+    var e = new MockFunctionTypedElement(parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '({x: dynamic}) → dynamic',
+        namedParameterTypes: {'x': same(dynamicType)},
+        parameters: [same(p)]);
+  }
+
+  test_unnamedConstructor_namedParameter_object() {
+    var p = new MockParameterElement('x',
+        parameterKind: ParameterKind.NAMED, type: objectType);
+    var e = new MockFunctionTypedElement(parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '({x: Object}) → dynamic',
+        namedParameterTypes: {'x': same(objectType)},
+        parameters: [same(p)]);
+  }
+
+  test_unnamedConstructor_normalParameter() {
+    var p = new MockParameterElement('x');
+    var e = new MockFunctionTypedElement(parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '(dynamic) → dynamic',
+        normalParameterNames: ['x'],
+        normalParameterTypes: [same(dynamicType)],
+        parameters: [same(p)]);
+  }
+
+  test_unnamedConstructor_normalParameter_object() {
+    var p = new MockParameterElement('x', type: objectType);
+    var e = new MockFunctionTypedElement(parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '(Object) → dynamic',
+        normalParameterNames: ['x'],
+        normalParameterTypes: [same(objectType)],
+        parameters: [same(p)]);
+  }
+
+  test_unnamedConstructor_optionalParameter() {
+    var p =
+        new MockParameterElement('x', parameterKind: ParameterKind.POSITIONAL);
+    var e = new MockFunctionTypedElement(parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '([dynamic]) → dynamic',
+        optionalParameterNames: ['x'],
+        optionalParameterTypes: [same(dynamicType)],
+        parameters: [same(p)]);
+  }
+
+  test_unnamedConstructor_optionalParameter_object() {
+    var p = new MockParameterElement('x',
+        parameterKind: ParameterKind.POSITIONAL, type: objectType);
+    var e = new MockFunctionTypedElement(parameters: [p]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '([Object]) → dynamic',
+        optionalParameterNames: ['x'],
+        optionalParameterTypes: [same(objectType)],
+        parameters: [same(p)]);
+  }
+
+  test_unnamedConstructor_returnType() {
+    var e = new MockFunctionTypedElement(returnType: objectType);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        returnType: same(objectType),
+        displayName: '() → Object');
+  }
+
+  test_unnamedConstructor_returnType_null() {
+    var e = new MockFunctionTypedElement.withNullReturn();
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        returnType: same(dynamicType),
+        displayName: '() → dynamic');
+  }
+
+  test_unnamedConstructor_staticMethod_ignores_enclosing_type_params() {
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var e = new MockMethodElement(c, isStatic: true);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f, element: same(e));
+  }
+
+  test_unnamedConstructor_substitute_bound_recursive() {
+    // abstract class C<T> {
+    //   Map<S, V> f<S extends T, T extends U, V extends T>();
+    // }
+    var s = new MockTypeParameterElement('S');
+    var t = new MockTypeParameterElement('T');
+    var u = new MockTypeParameterElement('U');
+    var v = new MockTypeParameterElement('V');
+    s.bound = t.type;
+    t.bound = u.type;
+    v.bound = t.type;
+    var c = new MockClassElement('C', typeParameters: [u]);
+    var e = new MockFunctionTypedElement(
+        returnType: mapOf(s.type, v.type),
+        typeParameters: [s, t, v],
+        enclosingElement: c);
+    FunctionType f = new FunctionTypeImpl(e);
+    var substituted = f.substitute2([objectType], [u.type]);
+    basicChecks(substituted,
+        element: same(e),
+        displayName: isNotNull,
+        returnType: isNotNull,
+        typeFormals: hasLength(3),
+        typeParameters: [same(u)],
+        typeArguments: [same(objectType)]);
+    if (bug_33300_fixed) {
+      expect(substituted.displayName,
+          '<S extends T,T extends Object,V extends T>() → Map<S, V>');
+    } else {
+      expect(substituted.displayName,
+          '<S extends T extends Object,T extends Object,V extends T>() → Map<S, V>');
+    }
+    var s2 = substituted.typeFormals[0];
+    var t2 = substituted.typeFormals[1];
+    var v2 = substituted.typeFormals[2];
+    expect(s2.name, 'S');
+    expect(t2.name, 'T');
+    expect(v2.name, 'V');
+    expect(s2.bound, t2.type);
+    expect(t2.bound, same(objectType));
+    expect(v2.bound, t2.type);
+    if (bug_33301_fixed) {
+      expect(substituted.returnType, mapOf(s2.type, v2.type));
+    } else {
+      expect(substituted.returnType, mapOf(s.type, v.type));
+    }
+  }
+
+  test_unnamedConstructor_substitute_bound_simple() {
+    // abstract class C<T> {
+    //   U f<U extends T>();
+    // }
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var u = new MockTypeParameterElement('U', bound: t.type);
+    var e = new MockFunctionTypedElement(
+        typeParameters: [u], returnType: u.type, enclosingElement: c);
+    FunctionType f = new FunctionTypeImpl(e);
+    var substituted = f.substitute2([objectType], [t.type]);
+    basicChecks(substituted,
+        element: same(e),
+        displayName: '<U extends Object>() → U',
+        typeArguments: [same(objectType)],
+        typeParameters: [same(t)],
+        returnType: isNotNull,
+        typeFormals: hasLength(1));
+    expect(substituted.typeFormals[0].name, 'U');
+    expect(substituted.typeFormals[0].bound, same(objectType));
+    expect((substituted.returnType as TypeParameterTypeImpl).element,
+        same(getBaseElement(substituted.typeFormals[0])));
+  }
+
+  test_unnamedConstructor_substitute_noop() {
+    var t = new MockTypeParameterElement('T');
+    var e = new MockFunctionTypedElement(returnType: t.type);
+    FunctionType f = new FunctionTypeImpl(e);
+    var substituted = f.substitute2([t.type], [t.type]);
+    basicChecks(substituted,
+        element: same(e), displayName: '() → T', returnType: same(t.type));
+    // TODO(paulberry): test substitute length mismatch
+  }
+
+  test_unnamedConstructor_substitute_parameterType_simple() {
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var p = new MockParameterElement('x', type: t.type);
+    var e = new MockFunctionTypedElement(parameters: [p], enclosingElement: c);
+    FunctionType f = new FunctionTypeImpl(e);
+    var substituted = f.substitute2([objectType], [t.type]);
+    basicChecks(substituted,
+        element: same(e),
+        displayName: '(Object) → dynamic',
+        normalParameterNames: ['x'],
+        normalParameterTypes: [same(objectType)],
+        parameters: hasLength(1),
+        typeArguments: [same(objectType)],
+        typeParameters: [same(t)]);
+    expect(substituted.parameters[0].name, 'x');
+    expect(substituted.parameters[0].type, same(objectType));
+  }
+
+  test_unnamedConstructor_substitute_returnType_simple() {
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var e =
+        new MockFunctionTypedElement(returnType: t.type, enclosingElement: c);
+    FunctionType f = new FunctionTypeImpl(e);
+    var substituted = f.substitute2([objectType], [t.type]);
+    basicChecks(substituted,
+        element: same(e),
+        displayName: '() → Object',
+        returnType: same(objectType),
+        typeArguments: [same(objectType)],
+        typeParameters: [same(t)]);
+  }
+
+  test_unnamedConstructor_typeParameter() {
+    var t = new MockTypeParameterElement('T');
+    var e = new MockFunctionTypedElement(typeParameters: [t]);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '<T>() → dynamic',
+        typeFormals: [same(t)]);
+    // TODO(paulberry): test pruning of bounds
+  }
+
+  test_unnamedConstructor_typeParameter_with_bound() {
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var u = new MockTypeParameterElement('U', bound: t.type);
+    var e = new MockFunctionTypedElement(
+        typeParameters: [u], returnType: u.type, enclosingElement: c);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '<U extends T>() → U',
+        typeArguments: [same(t.type)],
+        typeParameters: [same(t)],
+        returnType: same(u.type),
+        typeFormals: hasLength(1));
+    expect(f.typeFormals[0].name, 'U');
+    expect(f.typeFormals[0].bound, same(t.type));
+  }
+
+  test_unnamedConstructor_with_enclosing_type_parameters() {
+    // Test a weird behavior: substitutions are recorded in typeArguments and
+    // typeParameters.
+    var t = new MockTypeParameterElement('T');
+    var c = new MockClassElement('C', typeParameters: [t]);
+    var e =
+        new MockFunctionTypedElement(returnType: t.type, enclosingElement: c);
+    FunctionType f = new FunctionTypeImpl(e);
+    basicChecks(f,
+        element: same(e),
+        displayName: '() → T',
+        returnType: same(t.type),
+        typeArguments: [same(t.type)],
+        typeParameters: [same(t)]);
+  }
+
+  static InterfaceTypeImpl _makeListType() {
+    var e = new MockTypeParameterElement('E');
+    return new InterfaceTypeImpl.elementWithNameAndArgs(
+        new MockClassElement('List', typeParameters: [e]),
+        'List',
+        () => [e.type]);
+  }
+
+  static InterfaceTypeImpl _makeMapType() {
+    var k = new MockTypeParameterElement('K');
+    var v = new MockTypeParameterElement('V');
+    return new InterfaceTypeImpl.elementWithNameAndArgs(
+        new MockClassElement('Map', typeParameters: [k, v]),
+        'Map',
+        () => [k.type, v.type]);
+  }
+}
+
+class MockClassElement implements ClassElement {
+  @override
+  final List<TypeParameterElement> typeParameters;
+
+  @override
+  final String displayName;
+
+  MockClassElement(this.displayName, {this.typeParameters: const []});
+
+  @override
+  get enclosingElement => const MockCompilationUnitElement();
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockCompilationUnitElement implements CompilationUnitElement {
+  const MockCompilationUnitElement();
+
+  @override
+  get enclosingElement => const MockLibraryElement();
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockElementLocation implements ElementLocation {
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockFunctionTypedElement implements FunctionTypedElement {
+  @override
+  final List<ParameterElement> parameters;
+
+  @override
+  final DartType returnType;
+
+  @override
+  final List<TypeParameterElement> typeParameters;
+
+  @override
+  final Element enclosingElement;
+
+  MockFunctionTypedElement(
+      {this.parameters: const [],
+      DartType returnType,
+      this.typeParameters: const [],
+      this.enclosingElement: const MockCompilationUnitElement()})
+      : returnType = returnType ?? dynamicType;
+
+  MockFunctionTypedElement.withNullReturn(
+      {this.parameters: const [],
+      this.typeParameters: const [],
+      this.enclosingElement: const MockCompilationUnitElement()})
+      : returnType = null;
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockGenericFunctionTypeElementImpl
+    implements GenericFunctionTypeElementImpl {
+  @override
+  final MockGenericTypeAliasElement enclosingElement;
+
+  FunctionTypeImpl _type;
+
+  MockGenericFunctionTypeElementImpl(this.enclosingElement);
+
+  @override
+  get parameters => enclosingElement.parameters;
+
+  @override
+  get returnType => enclosingElement.returnType;
+
+  @override
+  get type => _type ??= new FunctionTypeImpl(this);
+
+  @override
+  get typeParameters => enclosingElement.innerTypeParameters;
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockGenericTypeAliasElement implements GenericTypeAliasElement {
+  @override
+  final String name;
+
+  @override
+  List<ParameterElement> parameters;
+
+  @override
+  final List<TypeParameterElement> typeParameters;
+
+  @override
+  DartType returnType;
+
+  FunctionType _type;
+
+  MockGenericFunctionTypeElementImpl _function;
+
+  final List<TypeParameterElement> innerTypeParameters;
+
+  MockGenericTypeAliasElement(this.name,
+      {this.parameters: const [],
+      DartType returnType,
+      this.typeParameters: const [],
+      this.innerTypeParameters: const []})
+      : returnType = returnType ?? dynamicType;
+
+  MockGenericTypeAliasElement.withNullReturn(this.name,
+      {this.parameters: const [],
+      this.typeParameters: const [],
+      this.innerTypeParameters: const []})
+      : returnType = null;
+
+  @override
+  get enclosingElement => const MockCompilationUnitElement();
+
+  @override
+  get function => _function ??= new MockGenericFunctionTypeElementImpl(this);
+
+  @override
+  get isSynthetic => false;
+
+  @override
+  get type => _type ??= new FunctionTypeImpl.forTypedef(this);
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockLibraryElement implements LibraryElement {
+  const MockLibraryElement();
+
+  @override
+  get enclosingElement => null;
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockMethodElement extends MockFunctionTypedElement
+    implements MethodElement {
+  @override
+  final bool isStatic;
+
+  MockMethodElement(MockClassElement enclosingElement,
+      {this.isStatic: false, DartType returnType})
+      : super(enclosingElement: enclosingElement, returnType: returnType);
+
+  @override
+  ClassElement get enclosingElement => super.enclosingElement;
+}
+
+class MockParameterElement implements ParameterElement {
+  @override
+  final String name;
+
+  @override
+  final ParameterKind parameterKind;
+
+  @override
+  final DartType type;
+
+  MockParameterElement(this.name,
+      {this.parameterKind: ParameterKind.REQUIRED, this.type});
+
+  @override
+  get displayName => name;
+
+  @override
+  bool get isNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
+  bool get isNotOptional => parameterKind == ParameterKind.REQUIRED;
+
+  @override
+  bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class MockTypeParameterElement implements TypeParameterElement {
+  @override
+  final String name;
+
+  TypeParameterTypeImpl _type;
+
+  MockElementLocation _location;
+
+  @override
+  DartType bound;
+
+  MockTypeParameterElement(this.name, {this.bound});
+
+  @override
+  get kind => ElementKind.TYPE_PARAMETER;
+
+  @override
+  get location => _location ??= new MockElementLocation();
+
+  @override
+  get type => _type ??= new TypeParameterTypeImpl(this);
+
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index 2577db8..b2a1b2e 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -7,10 +7,12 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'element_test.dart' as element;
+import 'function_type_test.dart' as function_type;
 
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
     element.main();
+    function_type.main();
   }, name: 'element');
 }
diff --git a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
index 74c0314..fc243e5 100644
--- a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
+++ b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
@@ -173,8 +173,16 @@
       bool inAsync: false,
       bool inCatchBlock: false}) {
     // TODO(brianwilkerson) Check error codes.
-    return _parse(source, (parser, token) => parser.parseExpression(token),
+    Object result = _parse(
+        source, (parser, token) => parser.parseExpression(token),
         inAsync: inAsync, inCatchBlock: inCatchBlock);
+    if (result is Generator) {
+      result = (result as Generator).buildForEffect();
+    }
+    if (result is! Expression) {
+      throw new StateError('Expected Expression, found ${result.runtimeType}');
+    }
+    return result;
   }
 
   @override
@@ -516,8 +524,8 @@
       AstBodyBuilder builder = new AstBodyBuilder(
         library,
         procedureBuilder,
-        library.scope,
-        procedureBuilder.computeFormalParameterScope(library.scope),
+        new UnlinkedScope(),
+        null,
         kernelTarget.loader.hierarchy,
         kernelTarget.loader.coreTypes,
         null /* classBuilder */,
diff --git a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
index b8145d1..fdd1f54 100644
--- a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
@@ -57,29 +57,17 @@
   void test_typeParameters_gtEq() {
     testRecovery('''
 f<T>=() => null;
-''', [
-      ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
-      ParserErrorCode.MISSING_FUNCTION_BODY
-    ], '''
-f<T> = () => null;
-''', expectedErrorsInValidCode: [
-      ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
-      ParserErrorCode.MISSING_FUNCTION_BODY
-    ]);
+''', [ParserErrorCode.UNEXPECTED_TOKEN], '''
+f<T>() => null;
+''');
   }
 
   void test_typeParameters_gtGtEq() {
     testRecovery('''
 f<T extends List<int>>=() => null;
-''', [
-      ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
-      ParserErrorCode.MISSING_FUNCTION_BODY
-    ], '''
-f<T extends List<int>> = () => null;
-''', expectedErrorsInValidCode: [
-      ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
-      ParserErrorCode.MISSING_FUNCTION_BODY
-    ]);
+''', [ParserErrorCode.UNEXPECTED_TOKEN], '''
+f<T extends List<int>>() => null;
+''');
   }
 
   @failingTest
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
index 589b4c2..dde0479 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
@@ -65,19 +65,10 @@
               [
                 ScannerErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e) {}",
-              failing: [
-                'eof',
-                'block',
-                'labeled',
-                'localFunctionNonVoid',
-                'localFunctionVoid',
-                'localVariable'
-              ]),
+              failing: ['block', 'labeled', 'localFunctionNonVoid']),
           new TestDescriptor(
               'catch_identifier',
               'try {} catch (e',
@@ -87,25 +78,17 @@
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e) {}",
-              failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
+              failing: ['eof', 'block']),
           new TestDescriptor(
               'catch_identifierComma',
               'try {} catch (e, ',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e, _s_) {}",
-              failing: [
-                'eof',
-                'block',
-                'labeled',
-                'localFunctionNonVoid',
-                'localFunctionVoid',
-                'localVariable'
-              ]),
+              failing: ['block', 'labeled', 'localFunctionNonVoid']),
           new TestDescriptor(
               'catch_identifierCommaIdentifier',
               'try {} catch (e, s',
@@ -115,7 +98,7 @@
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e, s) {}",
-              failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
+              failing: ['eof', 'block']),
           new TestDescriptor('catch_rightParen', 'try {} catch (e, s)',
               [ParserErrorCode.EXPECTED_TOKEN], "try {} catch (e, s) {}",
               failing: ['block']),
@@ -133,20 +116,11 @@
               'try {} on A catch (',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e) {}",
-              failing: [
-                'eof',
-                'block',
-                'labeled',
-                'localFunctionNonVoid',
-                'localFunctionVoid',
-                'localVariable'
-              ]),
+              failing: ['block', 'labeled', 'localFunctionNonVoid']),
           new TestDescriptor(
               'on_catch_identifier',
               'try {} on A catch (e',
@@ -156,25 +130,17 @@
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e) {}",
-              failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
+              failing: ['eof', 'block']),
           new TestDescriptor(
               'on_catch_identifierComma',
               'try {} on A catch (e, ',
               [
-                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.CATCH_SYNTAX,
                 ParserErrorCode.EXPECTED_TOKEN,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e, _s_) {}",
-              failing: [
-                'eof',
-                'block',
-                'labeled',
-                'localFunctionVoid',
-                'localFunctionNonVoid',
-                'localVariable'
-              ]),
+              failing: ['block', 'labeled', 'localFunctionNonVoid']),
           new TestDescriptor(
               'on_catch_identifierCommaIdentifier',
               'try {} on A catch (e, s',
@@ -184,7 +150,7 @@
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e, s) {}",
-              failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
+              failing: ['eof', 'block']),
           new TestDescriptor('on_catch_rightParen', 'try {} on A catch (e, s)',
               [ParserErrorCode.EXPECTED_TOKEN], "try {} on A catch (e, s) {}",
               failing: ['block']),
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 73af369..44e1444 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -385,6 +385,7 @@
     expect(v.initializer.type.toString(), '() → () → Null');
   }
 
+  @failingTest
   test_circularReference_viaClosures() async {
     var mainUnit = await checkFileElement('''
 var x = /*info:INFERRED_TYPE_CLOSURE*/() => /*error:TOP_LEVEL_CYCLE*/y;
@@ -398,6 +399,7 @@
     expect(y.type.toString(), 'dynamic');
   }
 
+  @failingTest
   test_circularReference_viaClosures_initializerTypes() async {
     var mainUnit = await checkFileElement('''
 var x = /*info:INFERRED_TYPE_CLOSURE*/() => /*error:TOP_LEVEL_CYCLE*/y;
@@ -3602,6 +3604,7 @@
 ''');
   }
 
+  @failingTest
   test_instantiateToBounds_typeName_OK_hasBound_definedAfter() async {
     var unit = await checkFileElement(r'''
 class B<T extends A> {}
@@ -4146,6 +4149,7 @@
     expect(v.type.toString(), 'List<dynamic>');
   }
 
+  @failingTest
   test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() async {
     // Note: (f<dynamic>) is not properly resulting in an instantiated
     // function type due to dartbug.com/25824.
@@ -4178,6 +4182,7 @@
     expect(v.type.toString(), 'List<int>');
   }
 
+  @failingTest
   test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() async {
     // TODO(paulberry): for some reason (f<int>) is not properly resulting
     // in an instantiated function type.
@@ -4414,40 +4419,6 @@
     CompilationUnit unit = await checkFile(content);
     return unit.element;
   }
-
-  @failingTest
-  @override
-  void test_circularReference_viaClosures() {
-    super.test_circularReference_viaClosures();
-  }
-
-  @failingTest
-  @override
-  void test_circularReference_viaClosures_initializerTypes() {
-    super.test_circularReference_viaClosures_initializerTypes();
-  }
-
-  @failingTest
-  @override
-  void test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
-    super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
-  }
-
-  @failingTest
-  @override
-  void
-      test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
-    super
-        .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
-  }
-
-  @failingTest
-  @override
-  void
-      test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
-    super
-        .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
-  }
 }
 
 @reflectiveTest
@@ -4458,19 +4429,6 @@
   @override
   bool get hasExtraTaskModelPass => false;
 
-  @failingTest
-  @override
-  void test_circularReference_viaClosures() {
-    super.test_circularReference_viaClosures();
-  }
-
-  @failingTest
-  @override
-  test_circularReference_viaClosures_initializerTypes() async {
-    await super.test_circularReference_viaClosures_initializerTypes();
-  }
-
-  @failingTest
   @override
   test_instantiateToBounds_typeName_OK_hasBound_definedAfter() async {
     await super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
@@ -4490,16 +4448,18 @@
   }
 
   @override
+  test_circularReference_viaClosures() async {
+    await super.test_circularReference_viaClosures();
+  }
+
+  @override
   test_unsafeBlockClosureInference_closureCall() async {
     await super.test_unsafeBlockClosureInference_closureCall();
   }
 
-  @failingTest
   @override
-  void
-      test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
-    super
-        .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
+  test_circularReference_viaClosures_initializerTypes() async {
+    await super.test_circularReference_viaClosures_initializerTypes();
   }
 
   @failingTest
@@ -4511,14 +4471,6 @@
 
   @failingTest
   @override
-  void
-      test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
-    super
-        .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
-  }
-
-  @failingTest
-  @override
   test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2() async {
     await super
         .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2();
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 9fdfd1a..b05015a 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
 name: analyzer_plugin
 description: A framework for building plugins for the analysis server.
-version: 0.0.1-alpha.2
+version: 0.0.1-alpha.3
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
 
@@ -8,7 +8,7 @@
   sdk: '>=1.8.0 <2.0.0'
 
 dependencies:
-  analyzer: '^0.31.2-alpha.1'
+  analyzer: '>=0.31.2-alpha.1 <0.33.0'
   charcode: '^1.1.0'
   html: '^0.13.1'
   meta: ^1.0.2
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 6eb3847..4fcea9f 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -18,7 +18,6 @@
 import 'compiler.dart';
 import 'diagnostics/messages.dart' show Message;
 import 'environment.dart';
-import 'io/source_file.dart';
 import 'options.dart' show CompilerOptions;
 import 'platform_configuration.dart' as platform_configuration;
 import 'resolved_uri_translator.dart';
@@ -95,9 +94,9 @@
       // and we can't depend on 'dart:io' classes.
       packages = new NonFilePackagesDirectoryPackages(options.packageRoot);
     } else if (options.packageConfig != null) {
-      Future<Binary> future =
+      Future<api.Input<List<int>>> future =
           callUserProvider(options.packageConfig, api.InputKind.binary);
-      return future.then((Binary binary) {
+      return future.then((api.Input<List<int>> binary) {
         packages =
             new MapPackages(pkgs.parse(binary.data, options.packageConfig));
       }).catchError((error) {
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index 642cbf4..0e29978 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -22,8 +22,8 @@
 /// Strategy pattern that defines the element model used in type inference
 /// and code generation.
 abstract class BackendStrategy {
-  /// Create the [ClosedWorldRefiner] for [closedWorld].
-  ClosedWorldRefiner createClosedWorldRefiner(ClosedWorld closedWorld);
+  /// Create the [JClosedWorld] from [closedWorld].
+  JClosedWorld createJClosedWorld(KClosedWorld closedWorld);
 
   /// Converts [data] to use backend entities instead of frontend entities.
   OutputUnitData convertOutputUnitData(OutputUnitData data);
@@ -38,11 +38,11 @@
   /// Creates the [CodegenWorldBuilder] used by the codegen enqueuer.
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
-      ClosedWorld closedWorld,
+      JClosedWorld closedWorld,
       SelectorConstraintsStrategy selectorConstraintsStrategy);
 
   /// Creates the [WorkItemBuilder] used by the codegen enqueuer.
-  WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld);
+  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld);
 
   /// Creates the [SsaBuilder] used for the element model.
   SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
@@ -55,6 +55,6 @@
   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement);
 
   /// Creates the [TypesInferrer] used by this strategy.
-  TypesInferrer createTypesInferrer(ClosedWorldRefiner closedWorldRefiner,
+  TypesInferrer createTypesInferrer(JClosedWorld closedWorld,
       {bool disableTypeInference: false});
 }
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index a4ad683..18cfdc3 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -6,17 +6,12 @@
 import 'common.dart';
 import 'elements/entities.dart';
 import 'elements/types.dart';
-import 'world.dart' show ClosedWorldRefiner;
 
 // TODO(johnniwinther,efortuna): Split [ClosureConversionTask] from
 // [ClosureDataLookup].
 abstract class ClosureConversionTask<T> extends CompilerTask
     implements ClosureDataLookup<T> {
   ClosureConversionTask(Measurer measurer) : super(measurer);
-
-  //void analyzeClosures();
-  void convertClosures(Iterable<MemberEntity> processedEntities,
-      ClosedWorldRefiner closedWorldRefiner);
 }
 
 /// Class that provides information for how closures are rewritten/represented
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 884aadb..c4419b5 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -7,6 +7,7 @@
 
 import 'common.dart';
 import 'common/names.dart' show Identifiers, Uris;
+import 'constants/expressions.dart' show ConstantExpression;
 import 'constants/values.dart';
 import 'elements/entities.dart';
 import 'elements/names.dart' show PublicName;
@@ -14,12 +15,10 @@
 import 'js_backend/backend.dart' show JavaScriptBackend;
 import 'js_backend/constant_system_javascript.dart';
 import 'js_backend/native_data.dart' show NativeBasicData;
-import 'constants/expressions.dart' show ConstantExpression;
+import 'types/abstract_value_domain.dart';
 import 'universe/call_structure.dart' show CallStructure;
 import 'universe/selector.dart' show Selector;
 import 'universe/call_structure.dart';
-import 'universe/world_builder.dart';
-import 'world.dart';
 
 /// The common elements and types in Dart.
 class CommonElements {
@@ -748,8 +747,8 @@
   /// in the given [world].
   ///
   /// Returns `false` if `JSString.split` is not available.
-  bool appliesToJsStringSplit(
-      Selector selector, ReceiverConstraint receiver, World world) {
+  bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
+      AbstractValueDomain abstractValueDomain) {
     if (_jsStringSplit == null) {
       ClassEntity cls =
           _findClass(interceptorsLibrary, 'JSString', required: false);
@@ -758,7 +757,8 @@
       if (_jsStringSplit == null) return false;
     }
     return selector.applies(_jsStringSplit) &&
-        (receiver == null || receiver.canHit(jsStringSplit, selector, world));
+        (receiver == null ||
+            abstractValueDomain.canHit(receiver, jsStringSplit, selector));
   }
 
   FunctionEntity _jsStringSplit;
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index ca5e4ab..4a8bc14 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -6,6 +6,8 @@
 
 import 'dart:async' show Future;
 
+import 'package:front_end/src/fasta/scanner.dart' show StringToken;
+
 import '../compiler_new.dart' as api;
 import 'backend_strategy.dart';
 import 'common/names.dart' show Selectors;
@@ -24,6 +26,7 @@
 import 'enqueue.dart' show Enqueuer, EnqueueTask, ResolutionEnqueuer;
 import 'environment.dart';
 import 'frontend_strategy.dart';
+import 'inferrer/typemasks/masks.dart' show TypeMaskStrategy;
 import 'io/source_information.dart' show SourceInformation;
 import 'js_backend/backend.dart' show JavaScriptBackend;
 import 'kernel/kernel_backend_strategy.dart';
@@ -32,7 +35,7 @@
 import 'null_compiler_output.dart' show NullCompilerOutput, NullSink;
 import 'options.dart' show CompilerOptions, DiagnosticOptions;
 import 'ssa/nodes.dart' show HInstruction;
-import 'package:front_end/src/fasta/scanner.dart' show StringToken;
+import 'types/abstract_value_domain.dart' show AbstractValueStrategy;
 import 'types/types.dart' show GlobalTypeInferenceTask;
 import 'universe/selector.dart' show Selector;
 import 'universe/world_builder.dart'
@@ -40,7 +43,7 @@
 import 'universe/use.dart' show StaticUse, TypeUse;
 import 'universe/world_impact.dart'
     show ImpactStrategy, WorldImpact, WorldImpactBuilderImpl;
-import 'world.dart' show ClosedWorld, ClosedWorldRefiner;
+import 'world.dart' show JClosedWorld, KClosedWorld;
 
 typedef CompilerDiagnosticReporter MakeReporterFunction(
     Compiler compiler, CompilerOptions options);
@@ -76,7 +79,7 @@
 
   Uri mainLibraryUri;
 
-  ClosedWorld backendClosedWorldForTesting;
+  JClosedWorld backendClosedWorldForTesting;
 
   DiagnosticReporter get reporter => _reporter;
   Map<Entity, WorldImpact> get impactCache => _impactCache;
@@ -102,6 +105,8 @@
   JavaScriptBackend backend;
   CodegenWorldBuilder _codegenWorldBuilder;
 
+  AbstractValueStrategy abstractValueStrategy = const TypeMaskStrategy();
+
   GenericTask selfTask;
 
   /// The constant environment for the frontend interpretation of compile-time
@@ -366,15 +371,13 @@
         if (options.analyzeOnly) return;
         assert(mainFunction != null);
 
-        ClosedWorldRefiner closedWorldRefiner = closeResolution(mainFunction);
-        ClosedWorld closedWorld = closedWorldRefiner.closedWorld;
+        JClosedWorld closedWorld = closeResolution(mainFunction);
         backendClosedWorldForTesting = closedWorld;
         mainFunction = closedWorld.elementEnvironment.mainFunction;
 
         reporter.log('Inferring types...');
-        globalInference.runGlobalTypeInference(
-            mainFunction, closedWorld, closedWorldRefiner);
-        closedWorldRefiner.computeSideEffects();
+        globalInference.runGlobalTypeInference(mainFunction, closedWorld);
+        closedWorld.computeSideEffects();
 
         if (stopAfterTypeInference) return;
 
@@ -404,7 +407,7 @@
         checkQueues(resolutionEnqueuer, codegenEnqueuer);
       });
 
-  Enqueuer startCodegen(ClosedWorld closedWorld) {
+  Enqueuer startCodegen(JClosedWorld closedWorld) {
     Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(closedWorld);
     _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
     codegenEnqueuer.applyImpact(backend.onCodegenStart(
@@ -413,23 +416,19 @@
   }
 
   /// Perform the steps needed to fully end the resolution phase.
-  ClosedWorldRefiner closeResolution(FunctionEntity mainFunction) {
+  JClosedWorld closeResolution(FunctionEntity mainFunction) {
     phase = PHASE_DONE_RESOLVING;
 
-    ClosedWorld closedWorld = resolutionWorldBuilder.closeWorld();
+    KClosedWorld closedWorld = resolutionWorldBuilder.closeWorld();
     OutputUnitData result = deferredLoadTask.run(mainFunction, closedWorld);
-    ClosedWorldRefiner closedWorldRefiner =
-        backendStrategy.createClosedWorldRefiner(closedWorld);
+    JClosedWorld closedWorldRefiner =
+        backendStrategy.createJClosedWorld(closedWorld);
     // Compute whole-program-knowledge that the backend needs. (This might
     // require the information computed in [world.closeWorld].)
-    backend.onResolutionClosedWorld(closedWorld, closedWorldRefiner);
+    backend.onResolutionClosedWorld(closedWorldRefiner);
 
     backend.onDeferredLoadComplete(result);
 
-    // TODO(johnniwinther): Move this after rti computation but before
-    // reflection members computation, and (re-)close the world afterwards.
-    backendStrategy.closureDataLookup.convertClosures(
-        enqueuer.resolution.processedEntities, closedWorldRefiner);
     return closedWorldRefiner;
   }
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 7418a1a..467d61b 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -24,7 +24,7 @@
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
 import 'util/uri_extras.dart' as uri_extras;
 import 'util/util.dart' show makeUnique;
-import 'world.dart' show ClosedWorld;
+import 'world.dart' show KClosedWorld;
 
 /// A "hunk" of the program that will be loaded whenever one of its [imports]
 /// are loaded.
@@ -483,6 +483,23 @@
     }
   }
 
+  void _updateLocalFunction(
+      Local localFunction, ImportSet oldSet, ImportSet newSet) {
+    ImportSet currentSet = _localFunctionToSet[localFunction];
+    if (currentSet == newSet) return;
+
+    // Elements in the main output unit always remain there.
+    if (currentSet == importSets.mainSet) return;
+
+    if (currentSet == oldSet) {
+      _localFunctionToSet[localFunction] = newSet;
+    } else {
+      _localFunctionToSet[localFunction] = importSets.union(currentSet, newSet);
+    }
+    // Note: local functions are not updated recursively because the
+    // dependencies are already visited as dependencies of the enclosing member.
+  }
+
   void _processDependencies(LibraryEntity library, Dependencies dependencies,
       ImportSet oldSet, ImportSet newSet, WorkQueue queue) {
     for (ClassEntity cls in dependencies.classes) {
@@ -520,10 +537,7 @@
     }
 
     for (Local localFunction in dependencies.localFunctions) {
-      // Local function are not updated recursively because the dependencies are
-      // already visited as dependencies of the enclosing member, so we just
-      // assign the [newSet] to each local function.
-      _localFunctionToSet[localFunction] = newSet;
+      _updateLocalFunction(localFunction, oldSet, newSet);
     }
 
     for (ConstantValue dependency in dependencies.constants) {
@@ -699,7 +713,7 @@
   /// TODO(sigmund): investigate different heuristics for how to select the next
   /// work item (e.g. we might converge faster if we pick first the update that
   /// contains a bigger delta.)
-  OutputUnitData run(FunctionEntity main, ClosedWorld closedWorld) {
+  OutputUnitData run(FunctionEntity main, KClosedWorld closedWorld) {
     if (!isProgramSplit || main == null || disableProgramSplit) {
       return _buildResult();
     }
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index a723729..15950a1 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -20,18 +20,17 @@
 import 'elements/entities.dart';
 import 'js/js.dart' as jsAst;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
-import 'types/masks.dart';
+import 'types/abstract_value_domain.dart';
 import 'types/types.dart'
     show GlobalTypeInferenceElementResult, GlobalTypeInferenceMemberResult;
-import 'universe/world_builder.dart'
-    show CodegenWorldBuilder, ReceiverConstraint;
+import 'universe/world_builder.dart' show CodegenWorldBuilder;
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
-import 'world.dart' show ClosedWorld;
+import 'world.dart' show JClosedWorld;
 
 class ElementInfoCollector {
   final Compiler compiler;
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
 
   ElementEnvironment get environment => closedWorld.elementEnvironment;
   CodegenWorldBuilder get codegenWorldBuilder => compiler.codegenWorldBuilder;
@@ -119,9 +118,12 @@
     if (!isInInstantiatedClass && !_hasBeenResolved(field)) {
       return null;
     }
-    TypeMask inferredType = _resultOfMember(field).type;
+    AbstractValue inferredType = _resultOfMember(field).type;
     // If a field has an empty inferred type it is never used.
-    if (inferredType == null || inferredType.isEmpty) return null;
+    if (inferredType == null ||
+        closedWorld.abstractValueDomain.isEmpty(inferredType)) {
+      return null;
+    }
 
     int size = compiler.dumpInfoTask.sizeOf(field);
     String code = compiler.dumpInfoTask.codeOf(field);
@@ -376,8 +378,8 @@
 
 class Selection {
   final Entity selectedEntity;
-  final ReceiverConstraint mask;
-  Selection(this.selectedEntity, this.mask);
+  final Object receiverConstraint;
+  Selection(this.selectedEntity, this.receiverConstraint);
 }
 
 /// Interface used to record information from different parts of the compiler so
@@ -453,7 +455,7 @@
   /// Returns an iterable of [Selection]s that are used by [entity]. Each
   /// [Selection] contains an entity that is used and the selector that
   /// selected the entity.
-  Iterable<Selection> getRetaining(Entity entity, ClosedWorld closedWorld) {
+  Iterable<Selection> getRetaining(Entity entity, JClosedWorld closedWorld) {
     WorldImpact impact = impacts[entity];
     if (impact == null) return const <Selection>[];
 
@@ -462,12 +464,12 @@
         entity,
         impact,
         new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) {
-          TypeMask mask = dynamicUse.mask;
+          AbstractValue mask = dynamicUse.receiverConstraint;
           selections.addAll(closedWorld
               // TODO(het): Handle `call` on `Closure` through
               // `world.includesClosureCall`.
               .locateMembers(dynamicUse.selector, mask)
-              .map((MemberEntity e) => new Selection(e, dynamicUse.mask)));
+              .map((MemberEntity e) => new Selection(e, mask)));
         }, visitStaticUse: (staticUse) {
           selections.add(new Selection(staticUse.element, null));
         }),
@@ -538,7 +540,7 @@
     return sb.toString();
   }
 
-  void dumpInfo(ClosedWorld closedWorld) {
+  void dumpInfo(JClosedWorld closedWorld) {
     measure(() {
       infoCollector = new ElementInfoCollector(compiler, closedWorld)..run();
       StringBuffer jsonBuffer = new StringBuffer();
@@ -552,7 +554,7 @@
     });
   }
 
-  void dumpInfoJson(StringSink buffer, ClosedWorld closedWorld) {
+  void dumpInfoJson(StringSink buffer, JClosedWorld closedWorld) {
     JsonEncoder encoder = const JsonEncoder.withIndent('  ');
     Stopwatch stopwatch = new Stopwatch();
     stopwatch.start();
@@ -570,7 +572,8 @@
         // Don't register dart2js builtin functions that are not recorded.
         Info useInfo = infoCollector._entityToInfo[selection.selectedEntity];
         if (useInfo == null) continue;
-        info.uses.add(new DependencyInfo(useInfo, '${selection.mask}'));
+        info.uses.add(
+            new DependencyInfo(useInfo, '${selection.receiverConstraint}'));
       }
     }
 
@@ -584,7 +587,8 @@
       for (Selection selection in uses) {
         Info useInfo = infoCollector._entityToInfo[selection.selectedEntity];
         if (useInfo == null) continue;
-        info.uses.add(new DependencyInfo(useInfo, '${selection.mask}'));
+        info.uses.add(
+            new DependencyInfo(useInfo, '${selection.receiverConstraint}'));
       }
     }
 
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index decc885..c4b5b90c 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -29,7 +29,7 @@
     show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
 import 'util/enumset.dart';
 import 'util/util.dart' show Setlet;
-import 'world.dart' show ClosedWorld;
+import 'world.dart' show JClosedWorld;
 
 class EnqueueTask extends CompilerTask {
   ResolutionEnqueuer _resolution;
@@ -60,7 +60,7 @@
           ..onEmptyForTesting = compiler.onResolutionQueueEmptyForTesting;
   }
 
-  Enqueuer createCodegenEnqueuer(ClosedWorld closedWorld) {
+  Enqueuer createCodegenEnqueuer(JClosedWorld closedWorld) {
     return codegenEnqueuerForTesting = compiler.backend
         .createCodegenEnqueuer(this, compiler, closedWorld)
           ..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
diff --git a/pkg/compiler/lib/src/hash/sha1.dart b/pkg/compiler/lib/src/hash/sha1.dart
index 7b04aed..814cd43 100644
--- a/pkg/compiler/lib/src/hash/sha1.dart
+++ b/pkg/compiler/lib/src/hash/sha1.dart
@@ -129,7 +129,7 @@
 
   // Compute the final result as a list of bytes from the hash words.
   List<int> _resultAsBytes() {
-    var result = [];
+    var result = <int>[];
     for (var i = 0; i < _h.length; i++) {
       result.addAll(_wordToBytes(_h[i]));
     }
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index bb5ebdb..d8c13d6 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -17,8 +17,7 @@
 import '../kernel/element_map.dart';
 import '../native/behavior.dart';
 import '../options.dart';
-import '../types/constants.dart';
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/selector.dart';
 import '../universe/side_effects.dart';
@@ -37,7 +36,7 @@
 /// is doing.
 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
   final CompilerOptions _options;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final ClosureDataLookup<ir.Node> _closureDataLookup;
   final InferrerEngine<ir.Node> _inferrer;
   final TypeSystem<ir.Node> _types;
@@ -82,8 +81,7 @@
         // TODO(johnniwinther): Should side effects also be tracked for field
         // initializers?
         this._sideEffectsBuilder = _analyzedMember is FunctionEntity
-            ? _inferrer.closedWorldRefiner
-                .getSideEffectsBuilder(_analyzedMember)
+            ? _inferrer.closedWorld.getSideEffectsBuilder(_analyzedMember)
             : new SideEffectsBuilder.free(_analyzedMember),
         this._inGenerativeConstructor = _analyzedNode is ir.Constructor {
     if (_locals != null) return;
@@ -125,7 +123,7 @@
   /// If an instance field matched with a [selector] that is _not_ a setter, the
   /// field is considered to have been read before initialization and the field
   /// is assumed to be potentially `null`.
-  void _checkIfExposesThis(Selector selector, TypeMask mask) {
+  void _checkIfExposesThis(Selector selector, AbstractValue mask) {
     if (_isThisExposed) {
       // We already consider `this` to have been exposed.
       return;
@@ -296,7 +294,7 @@
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = new Selector(SelectorKind.CALL, constructor.memberName,
         _elementMap.getCallStructure(node.arguments));
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     handleConstructorInvoke(
         node, node.arguments, selector, mask, constructor, arguments);
 
@@ -312,7 +310,7 @@
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = new Selector(SelectorKind.CALL, constructor.memberName,
         _elementMap.getCallStructure(node.arguments));
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     handleConstructorInvoke(
         node, node.arguments, selector, mask, constructor, arguments);
 
@@ -615,8 +613,9 @@
     ConstantSystem constantSystem = _closedWorld.constantSystem;
     // The JavaScript backend may turn this literal into a double at
     // runtime.
-    return _types.getConcreteTypeFor(computeTypeMask(
-        _closedWorld, constantSystem.createIntFromInt(node.value)));
+    return _types.getConcreteTypeFor(_closedWorld.abstractValueDomain
+        .computeAbstractValueForConstant(
+            constantSystem.createIntFromInt(node.value)));
   }
 
   @override
@@ -624,8 +623,9 @@
     ConstantSystem constantSystem = _closedWorld.constantSystem;
     // The JavaScript backend may turn this literal into an integer at
     // runtime.
-    return _types.getConcreteTypeFor(
-        computeTypeMask(_closedWorld, constantSystem.createDouble(node.value)));
+    return _types.getConcreteTypeFor(_closedWorld.abstractValueDomain
+        .computeAbstractValueForConstant(
+            constantSystem.createDouble(node.value)));
   }
 
   @override
@@ -725,7 +725,7 @@
   @override
   TypeInformation visitMethodInvocation(ir.MethodInvocation node) {
     Selector selector = _elementMap.getSelector(node);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
 
     ir.TreeNode receiver = node.receiver;
     if (receiver is ir.VariableGet &&
@@ -767,7 +767,7 @@
       CallType callType,
       ir.Node node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       TypeInformation receiverType,
       ArgumentsTypes arguments) {
     assert(receiverType != null);
@@ -811,13 +811,17 @@
   }
 
   TypeInformation handleDynamicGet(ir.Node node, Selector selector,
-      TypeMask mask, TypeInformation receiverType) {
+      AbstractValue mask, TypeInformation receiverType) {
     return _handleDynamic(
         CallType.access, node, selector, mask, receiverType, null);
   }
 
-  TypeInformation handleDynamicSet(ir.Node node, Selector selector,
-      TypeMask mask, TypeInformation receiverType, TypeInformation rhsType) {
+  TypeInformation handleDynamicSet(
+      ir.Node node,
+      Selector selector,
+      AbstractValue mask,
+      TypeInformation receiverType,
+      TypeInformation rhsType) {
     ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
     return _handleDynamic(
         CallType.access, node, selector, mask, receiverType, arguments);
@@ -827,7 +831,7 @@
       CallType callType,
       ir.Node node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       TypeInformation receiverType,
       ArgumentsTypes arguments) {
     return _handleDynamic(
@@ -896,8 +900,8 @@
       _markThisAsExposed();
     }
 
-    TypeMask currentMask;
-    TypeMask moveNextMask;
+    AbstractValue currentMask;
+    AbstractValue moveNextMask;
     TypeInformation iteratorType;
     if (node.isAsync) {
       TypeInformation expressionType = visit(node.iterable);
@@ -914,7 +918,7 @@
     } else {
       TypeInformation expressionType = visit(node.iterable);
       Selector iteratorSelector = Selectors.iterator;
-      TypeMask iteratorMask = _memberData.typeOfIterator(node);
+      AbstractValue iteratorMask = _memberData.typeOfIterator(node);
       currentMask = _memberData.typeOfIteratorCurrent(node);
       moveNextMask = _memberData.typeOfIteratorMoveNext(node);
 
@@ -998,7 +1002,7 @@
     ConstructorEntity constructor = _elementMap.getConstructor(node.target);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = _elementMap.getSelector(node);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     return handleConstructorInvoke(
         node, node.arguments, selector, mask, constructor, arguments);
   }
@@ -1038,7 +1042,7 @@
       ir.Node node,
       ir.Arguments arguments,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       ConstructorEntity constructor,
       ArgumentsTypes argumentsTypes) {
     TypeInformation returnType =
@@ -1089,13 +1093,13 @@
   }
 
   TypeInformation handleStaticInvoke(ir.Node node, Selector selector,
-      TypeMask mask, MemberEntity element, ArgumentsTypes arguments) {
+      AbstractValue mask, MemberEntity element, ArgumentsTypes arguments) {
     return _inferrer.registerCalledMember(node, selector, mask, _analyzedMember,
         element, arguments, _sideEffectsBuilder, inLoop);
   }
 
   TypeInformation handleClosureCall(ir.Node node, Selector selector,
-      TypeMask mask, MemberEntity member, ArgumentsTypes arguments) {
+      AbstractValue mask, MemberEntity member, ArgumentsTypes arguments) {
     return _inferrer.registerCalledClosure(
         node,
         selector,
@@ -1112,7 +1116,7 @@
       FunctionEntity function,
       ArgumentsTypes arguments,
       Selector selector,
-      TypeMask mask) {
+      AbstractValue mask) {
     String name = function.name;
     handleStaticInvoke(node, selector, mask, function, arguments);
     if (name == JavaScriptBackend.JS) {
@@ -1143,7 +1147,7 @@
     MemberEntity member = _elementMap.getMember(node.target);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = _elementMap.getSelector(node);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     if (_closedWorld.commonElements.isForeign(member)) {
       return handleForeignInvoke(node, member, arguments, selector, mask);
     } else if (member.isConstructor) {
@@ -1165,7 +1169,7 @@
   @override
   TypeInformation visitStaticGet(ir.StaticGet node) {
     MemberEntity member = _elementMap.getMember(node.target);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     return handleStaticInvoke(
         node, new Selector.getter(member.memberName), mask, member, null);
   }
@@ -1177,7 +1181,7 @@
       _markThisAsExposed();
     }
     MemberEntity member = _elementMap.getMember(node.target);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     handleStaticInvoke(node, new Selector.setter(member.memberName), mask,
         member, new ArgumentsTypes([rhsType], null));
     return rhsType;
@@ -1187,7 +1191,7 @@
   TypeInformation visitPropertyGet(ir.PropertyGet node) {
     TypeInformation receiverType = visit(node.receiver);
     Selector selector = _elementMap.getSelector(node);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     // TODO(johnniwinther): Use `node.interfaceTarget` to narrow the receiver
     // type for --trust-type-annotations/strong-mode.
     if (node.receiver is ir.ThisExpression) {
@@ -1201,7 +1205,7 @@
   TypeInformation visitDirectPropertyGet(ir.DirectPropertyGet node) {
     TypeInformation receiverType = thisType;
     MemberEntity member = _elementMap.getMember(node.target);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     // TODO(johnniwinther): Use `node.target` to narrow the receiver type.
     Selector selector = new Selector.getter(member.memberName);
     _checkIfExposesThis(selector, _types.newTypedSelector(receiverType, mask));
@@ -1212,7 +1216,7 @@
   TypeInformation visitPropertySet(ir.PropertySet node) {
     TypeInformation receiverType = visit(node.receiver);
     Selector selector = _elementMap.getSelector(node);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
 
     TypeInformation rhsType = visit(node.value);
     if (node.value is ir.ThisExpression) {
@@ -1220,7 +1224,7 @@
     }
 
     if (_inGenerativeConstructor && node.receiver is ir.ThisExpression) {
-      TypeMask typedMask = _types.newTypedSelector(receiverType, mask);
+      AbstractValue typedMask = _types.newTypedSelector(receiverType, mask);
       if (!_closedWorld.includesClosureCall(selector, typedMask)) {
         Iterable<MemberEntity> targets =
             _closedWorld.locateMembers(selector, typedMask);
@@ -1608,7 +1612,7 @@
   }
 
   TypeInformation handleSuperNoSuchMethod(ir.Node node, Selector selector,
-      TypeMask mask, ArgumentsTypes arguments) {
+      AbstractValue mask, ArgumentsTypes arguments) {
     // Ensure we create a node, to make explicit the call to the
     // `noSuchMethod` handler.
     FunctionEntity noSuchMethod =
@@ -1624,7 +1628,7 @@
 
     MemberEntity member = _elementMap.getSuperMember(
         _analyzedMember, node.name, node.interfaceTarget);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     Selector selector = new Selector.getter(_elementMap.getName(node.name));
     if (member == null) {
       return handleSuperNoSuchMethod(node, selector, mask, null);
@@ -1643,7 +1647,7 @@
     MemberEntity member = _elementMap.getSuperMember(
         _analyzedMember, node.name, node.interfaceTarget,
         setter: true);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     Selector selector = new Selector.setter(_elementMap.getName(node.name));
     ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
     if (member == null) {
@@ -1664,7 +1668,7 @@
         _analyzedMember, node.name, node.interfaceTarget);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = _elementMap.getSelector(node);
-    TypeMask mask = _memberData.typeOfSend(node);
+    AbstractValue mask = _memberData.typeOfSend(node);
     if (member == null) {
       return handleSuperNoSuchMethod(node, selector, mask, arguments);
     } else if (member.isFunction) {
@@ -1720,7 +1724,7 @@
 
 class Refinement {
   final Selector selector;
-  final TypeMask mask;
+  final AbstractValue mask;
 
   Refinement(this.selector, this.mask);
 }
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index 8f785fb..ce86148 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -7,7 +7,7 @@
 import '../common/names.dart' show Names;
 import '../elements/entities.dart';
 import '../js_backend/backend.dart' show JavaScriptBackend;
-import '../types/masks.dart' show TypeMask;
+import '../types/abstract_value_domain.dart';
 import '../universe/selector.dart' show Selector;
 import 'debug.dart' as debug;
 import 'inferrer_engine.dart';
@@ -56,7 +56,7 @@
 
   void _analyzeCall(CallSiteTypeInformation info) {
     Selector selector = info.selector;
-    TypeMask mask = info.mask;
+    AbstractValue mask = info.mask;
     tracedElements.forEach((FunctionEntity functionElement) {
       if (!selector.callStructure
           .signatureApplies(functionElement.parameterStructure)) {
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 9a5fdc1..77622dd 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -18,8 +18,6 @@
 import '../native/behavior.dart' as native;
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/constants.dart';
-import '../types/masks.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
@@ -55,8 +53,7 @@
   ]);
 
   CompilerOptions get options;
-  ClosedWorld get closedWorld;
-  ClosedWorldRefiner get closedWorldRefiner;
+  JClosedWorld get closedWorld;
   DiagnosticReporter get reporter;
   AbstractValueDomain get abstractValueDomain =>
       closedWorld.abstractValueDomain;
@@ -87,7 +84,7 @@
   /// Applies [f] to all elements in the universe that match [selector] and
   /// [mask]. If [f] returns false, aborts the iteration.
   void forEachElementMatching(
-      Selector selector, TypeMask mask, bool f(MemberEntity element));
+      Selector selector, AbstractValue mask, bool f(MemberEntity element));
 
   /// Returns the [TypeInformation] node for the default value of a parameter.
   /// If this is queried before it is set by [setDefaultTypeOfParameter], a
@@ -147,7 +144,7 @@
   TypeInformation registerCalledClosure(
       T node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       TypeInformation closure,
       MemberEntity caller,
       ArgumentsTypes arguments,
@@ -165,7 +162,7 @@
   TypeInformation registerCalledMember(
       Object node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       MemberEntity caller,
       MemberEntity callee,
       ArgumentsTypes arguments,
@@ -183,7 +180,7 @@
       CallType callType,
       T node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       TypeInformation receiverType,
       MemberEntity caller,
       ArgumentsTypes arguments,
@@ -195,11 +192,11 @@
   /// assignments must be added or removed. If [init] is false, parameters are
   /// added to the work queue.
   void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
-      ArgumentsTypes arguments, Selector selector, TypeMask mask,
+      ArgumentsTypes arguments, Selector selector, AbstractValue mask,
       {bool remove, bool addToQueue: true});
 
   void updateSelectorInMember(MemberEntity owner, CallType callType, T node,
-      Selector selector, TypeMask mask);
+      Selector selector, AbstractValue mask);
 
   /// Returns the return type of [element].
   TypeInformation returnTypeOfMember(MemberEntity element);
@@ -218,9 +215,9 @@
   /// [native.NativeBehavior].
   TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior);
 
-  bool returnsListElementType(Selector selector, TypeMask mask);
+  bool returnsListElementType(Selector selector, AbstractValue mask);
 
-  bool returnsMapValueType(Selector selector, TypeMask mask);
+  bool returnsMapValueType(Selector selector, AbstractValue mask);
 
   void clear();
 
@@ -269,10 +266,9 @@
   final DiagnosticReporter reporter;
   final CompilerOutput _compilerOutput;
 
-  /// The [ClosedWorld] on which inference reasoning is based.
-  final ClosedWorld closedWorld;
+  /// The [JClosedWorld] on which inference reasoning is based.
+  final JClosedWorld closedWorld;
 
-  final ClosedWorldRefiner closedWorldRefiner;
   final TypeSystem<T> types;
   final Map<T, TypeInformation> concreteTypes = new Map<T, TypeInformation>();
 
@@ -296,7 +292,6 @@
       this.reporter,
       this._compilerOutput,
       this.closedWorld,
-      this.closedWorldRefiner,
       this.noSuchMethodRegistry,
       this.mainElement,
       this.sorter,
@@ -304,7 +299,7 @@
       : this.types = new TypeSystem<T>(closedWorld, typeSystemStrategy);
 
   void forEachElementMatching(
-      Selector selector, TypeMask mask, bool f(MemberEntity element)) {
+      Selector selector, AbstractValue mask, bool f(MemberEntity element)) {
     Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask);
     for (MemberEntity e in elements) {
       if (!f(e)) return;
@@ -347,8 +342,7 @@
     } else if (callee.isGetter && !selector.isGetter) {
       sideEffectsBuilder.setAllSideEffectsAndDependsOnSomething();
     } else {
-      sideEffectsBuilder
-          .addInput(closedWorldRefiner.getSideEffectsBuilder(callee));
+      sideEffectsBuilder.addInput(closedWorld.getSideEffectsBuilder(callee));
     }
   }
 
@@ -391,7 +385,7 @@
   }
 
   void updateSelectorInMember(MemberEntity owner, CallType callType, T node,
-      Selector selector, TypeMask mask) {
+      Selector selector, AbstractValue mask) {
     GlobalTypeInferenceElementData data = dataOfMember(owner);
     assert(validCallType(callType, node));
     switch (callType) {
@@ -421,14 +415,14 @@
     }
   }
 
-  bool returnsListElementType(Selector selector, TypeMask mask) {
+  bool returnsListElementType(Selector selector, AbstractValue mask) {
     return mask != null &&
-        mask.isContainer &&
+        abstractValueDomain.isContainer(mask) &&
         returnsListElementTypeSet.contains(selector);
   }
 
-  bool returnsMapValueType(Selector selector, TypeMask mask) {
-    return mask != null && mask.isMap && selector.isIndex;
+  bool returnsMapValueType(Selector selector, AbstractValue mask) {
+    return mask != null && abstractValueDomain.isMap(mask) && selector.isIndex;
   }
 
   void analyzeListAndEnqueue(ListTypeInformation info) {
@@ -441,8 +435,8 @@
 
     info.bailedOut = false;
     info.elementType.inferred = true;
-    TypeMask fixedListType = abstractValueDomain.fixedListType;
-    if (info.originalType.forwardTo == fixedListType) {
+    if (abstractValueDomain.isSpecializationOf(
+        info.originalType, abstractValueDomain.fixedListType)) {
       info.checksGrowable = tracer.callsGrowableMethod;
     }
     tracer.assignments.forEach(info.elementType.addAssignment);
@@ -461,12 +455,12 @@
 
     info.bailedOut = false;
     for (int i = 0; i < tracer.keyAssignments.length; ++i) {
-      TypeInformation newType = info.addEntryAssignment(
+      TypeInformation newType = info.addEntryAssignment(abstractValueDomain,
           tracer.keyAssignments[i], tracer.valueAssignments[i]);
       if (newType != null) workQueue.add(newType);
     }
     for (TypeInformation map in tracer.mapAssignments) {
-      workQueue.addAll(info.addMapAssignment(map));
+      workQueue.addAll(info.addMapAssignment(abstractValueDomain, map));
     }
 
     info.markAsInferred();
@@ -508,7 +502,7 @@
         tracer.run();
         if (!tracer.continueAnalyzing) {
           elements.forEach((FunctionEntity element) {
-            closedWorldRefiner.registerMightBePassedToApply(element);
+            closedWorld.registerMightBePassedToApply(element);
             if (debug.VERBOSE) {
               print("traced closure $element as ${true} (bail)");
             }
@@ -531,11 +525,11 @@
             workQueue.add(info);
           });
           if (tracer.tracedType.mightBePassedToFunctionApply) {
-            closedWorldRefiner.registerMightBePassedToApply(element);
+            closedWorld.registerMightBePassedToApply(element);
           }
           if (debug.VERBOSE) {
             print("traced closure $element as "
-                "${closedWorldRefiner
+                "${closedWorld
                 .getCurrentlyKnownMightBePassedToApply(element)}");
           }
         });
@@ -597,15 +591,15 @@
       types.allocatedLists.values.forEach((_info) {
         ListTypeInformation info = _info;
         print('${info.type} '
-            'for ${info.originalType.allocationNode} '
-            'at ${info.originalType.allocationElement} '
+            'for ${abstractValueDomain.getAllocationNode(info.originalType)} '
+            'at ${abstractValueDomain.getAllocationElement(info.originalType)}'
             'after ${info.refineCount}');
       });
       types.allocatedMaps.values.forEach((_info) {
         MapTypeInformation info = _info;
         print('${info.type} '
-            'for ${info.originalType.allocationNode} '
-            'at ${info.originalType.allocationElement} '
+            'for ${abstractValueDomain.getAllocationNode(info.originalType)} '
+            'at ${abstractValueDomain.getAllocationElement(info.originalType)}'
             'after ${info.refineCount}');
       });
       types.allocatedClosures.forEach((TypeInformation info) {
@@ -711,9 +705,10 @@
                 // Although we might find a better type, we have to keep
                 // the old type around to ensure that we get a complete view
                 // of the type graph and do not drop any flow edges.
-                TypeMask refinedType = computeTypeMask(closedWorld, value);
-                assert(TypeMask.assertIsNormalized(refinedType, closedWorld));
-                type = new NarrowTypeInformation(type, refinedType);
+                AbstractValue refinedType =
+                    abstractValueDomain.computeAbstractValueForConstant(value);
+                type = new NarrowTypeInformation(
+                    abstractValueDomain, type, refinedType);
                 types.allocatedTypes.add(type);
               }
             }
@@ -767,14 +762,15 @@
       }
       if (info is StaticCallSiteTypeInformation) {
         MemberEntity member = info.calledElement;
-        closedWorldRefiner.addFunctionCalledInLoop(member);
-      } else if (info.mask != null && !info.mask.containsAll(closedWorld)) {
+        closedWorld.addFunctionCalledInLoop(member);
+      } else if (info.mask != null &&
+          !abstractValueDomain.containsAll(info.mask)) {
         // For instance methods, we only register a selector called in a
         // loop if it is a typed selector, to avoid marking too many
         // methods as being called from within a loop. This cuts down
         // on the code bloat.
         info.callees.forEach((MemberEntity element) {
-          closedWorldRefiner.addFunctionCalledInLoop(element);
+          closedWorld.addFunctionCalledInLoop(element);
         });
       }
     });
@@ -784,8 +780,8 @@
     while (!workQueue.isEmpty) {
       progress.showProgress('Inferred ', overallRefineCount, ' types.');
       TypeInformation info = workQueue.remove();
-      TypeMask oldType = info.type;
-      TypeMask newType = info.refine(this);
+      AbstractValue oldType = info.type;
+      AbstractValue newType = info.refine(this);
       // Check that refinement has not accidentally changed the type.
       assert(oldType == info.type);
       if (info.abandonInferencing) info.doNotEnqueue = true;
@@ -816,7 +812,7 @@
   }
 
   void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
-      ArgumentsTypes arguments, Selector selector, TypeMask mask,
+      ArgumentsTypes arguments, Selector selector, AbstractValue mask,
       {bool remove, bool addToQueue: true}) {
     if (callee.name == Identifiers.noSuchMethod_) return;
     if (callee.isField) {
@@ -908,7 +904,8 @@
 
   TypeInformation getDefaultTypeOfParameter(Local parameter) {
     return defaultTypeOfParameter.putIfAbsent(parameter, () {
-      return new PlaceholderTypeInformation(types.currentMember);
+      return new PlaceholderTypeInformation(
+          abstractValueDomain, types.currentMember);
     });
   }
 
@@ -962,13 +959,14 @@
   TypeInformation registerCalledMember(
       Object node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       MemberEntity caller,
       MemberEntity callee,
       ArgumentsTypes arguments,
       SideEffectsBuilder sideEffectsBuilder,
       bool inLoop) {
     CallSiteTypeInformation info = new StaticCallSiteTypeInformation(
+        abstractValueDomain,
         types.currentMember,
         node,
         caller,
@@ -1001,7 +999,7 @@
       CallType callType,
       T node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       TypeInformation receiverType,
       MemberEntity caller,
       ArgumentsTypes arguments,
@@ -1022,6 +1020,7 @@
     });
 
     CallSiteTypeInformation info = new DynamicCallSiteTypeInformation(
+        abstractValueDomain,
         types.currentMember,
         callType,
         node,
@@ -1039,16 +1038,16 @@
   }
 
   TypeInformation registerAwait(T node, TypeInformation argument) {
-    AwaitTypeInformation info =
-        new AwaitTypeInformation<T>(types.currentMember, node);
+    AwaitTypeInformation info = new AwaitTypeInformation<T>(
+        abstractValueDomain, types.currentMember, node);
     info.addAssignment(argument);
     types.allocatedTypes.add(info);
     return info;
   }
 
   TypeInformation registerYield(T node, TypeInformation argument) {
-    YieldTypeInformation info =
-        new YieldTypeInformation<T>(types.currentMember, node);
+    YieldTypeInformation info = new YieldTypeInformation<T>(
+        abstractValueDomain, types.currentMember, node);
     info.addAssignment(argument);
     types.allocatedTypes.add(info);
     return info;
@@ -1057,7 +1056,7 @@
   TypeInformation registerCalledClosure(
       T node,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       TypeInformation closure,
       MemberEntity caller,
       ArgumentsTypes arguments,
@@ -1065,6 +1064,7 @@
       {bool inLoop}) {
     sideEffectsBuilder.setAllSideEffectsAndDependsOnSomething();
     CallSiteTypeInformation info = new ClosureCallSiteTypeInformation(
+        abstractValueDomain,
         types.currentMember,
         node,
         caller,
diff --git a/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart
index 7b49435..ef1f1bc 100644
--- a/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart
@@ -33,16 +33,10 @@
   final GlobalLocalsMap _globalLocalsMap;
   final ClosureDataLookup<ir.Node> _closureDataLookup;
 
-  KernelTypeGraphInferrer(
-      this._compiler,
-      this._elementMap,
-      this._globalLocalsMap,
-      this._closureDataLookup,
-      ClosedWorld closedWorld,
-      ClosedWorldRefiner closedWorldRefiner,
+  KernelTypeGraphInferrer(this._compiler, this._elementMap,
+      this._globalLocalsMap, this._closureDataLookup, JClosedWorld closedWorld,
       {bool disableTypeInference: false})
-      : super(closedWorld, closedWorldRefiner,
-            disableTypeInference: disableTypeInference);
+      : super(closedWorld, disableTypeInference: disableTypeInference);
 
   @override
   InferrerEngine<ir.Node> createInferrerEngineFor(FunctionEntity main) {
@@ -55,7 +49,6 @@
         _globalLocalsMap,
         _closureDataLookup,
         closedWorld,
-        closedWorldRefiner,
         _compiler.backend.noSuchMethodRegistry,
         main,
         _compiler.backendStrategy.sorter);
@@ -70,7 +63,7 @@
 class KernelGlobalTypeInferenceResults
     extends GlobalTypeInferenceResults<ir.Node> {
   KernelGlobalTypeInferenceResults(
-      TypesInferrer<ir.Node> inferrer, ClosedWorld closedWorld)
+      TypesInferrer<ir.Node> inferrer, JClosedWorld closedWorld)
       : super(inferrer, closedWorld);
 
   GlobalTypeInferenceMemberResult<ir.Node> createMemberResult(
@@ -105,8 +98,7 @@
       this._elementMap,
       this._globalLocalsMap,
       this._closureDataLookup,
-      ClosedWorld closedWorld,
-      ClosedWorldRefiner closedWorldRefiner,
+      JClosedWorld closedWorld,
       NoSuchMethodRegistry noSuchMethodRegistry,
       FunctionEntity mainElement,
       Sorter sorter)
@@ -116,7 +108,6 @@
             reporter,
             compilerOutput,
             closedWorld,
-            closedWorldRefiner,
             noSuchMethodRegistry,
             mainElement,
             sorter,
@@ -268,7 +259,9 @@
 
   @override
   ParameterTypeInformation createParameterTypeInformation(
-      covariant JLocal parameter, TypeSystem<ir.Node> types) {
+      AbstractValueDomain abstractValueDomain,
+      covariant JLocal parameter,
+      TypeSystem<ir.Node> types) {
     MemberEntity context = parameter.memberContext;
     KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(context);
     ir.FunctionNode functionNode =
@@ -289,40 +282,48 @@
         types.getInferredTypeOfMember(member);
     if (isClosure) {
       return new ParameterTypeInformation.localFunction(
-          memberTypeInformation, parameter, type, member);
+          abstractValueDomain, memberTypeInformation, parameter, type, member);
     } else if (member.isInstanceMember) {
-      return new ParameterTypeInformation.instanceMember(memberTypeInformation,
-          parameter, type, member, new ParameterAssignments());
+      return new ParameterTypeInformation.instanceMember(
+          abstractValueDomain,
+          memberTypeInformation,
+          parameter,
+          type,
+          member,
+          new ParameterAssignments());
     } else {
       return new ParameterTypeInformation.static(
-          memberTypeInformation, parameter, type, member);
+          abstractValueDomain, memberTypeInformation, parameter, type, member);
     }
   }
 
   @override
-  MemberTypeInformation createMemberTypeInformation(MemberEntity member) {
+  MemberTypeInformation createMemberTypeInformation(
+      AbstractValueDomain abstractValueDomain, MemberEntity member) {
     if (member.isField) {
       FieldEntity field = member;
       DartType type = _elementEnvironment.getFieldType(field);
-      return new FieldTypeInformation(field, type);
+      return new FieldTypeInformation(abstractValueDomain, field, type);
     } else if (member.isGetter) {
       FunctionEntity getter = member;
       DartType type = _elementEnvironment.getFunctionType(getter);
-      return new GetterTypeInformation(getter, type);
+      return new GetterTypeInformation(abstractValueDomain, getter, type);
     } else if (member.isSetter) {
       FunctionEntity setter = member;
-      return new SetterTypeInformation(setter);
+      return new SetterTypeInformation(abstractValueDomain, setter);
     } else if (member.isFunction) {
       FunctionEntity method = member;
       DartType type = _elementEnvironment.getFunctionType(method);
-      return new MethodTypeInformation(method, type);
+      return new MethodTypeInformation(abstractValueDomain, method, type);
     } else {
       ConstructorEntity constructor = member;
       if (constructor.isFactoryConstructor) {
         DartType type = _elementEnvironment.getFunctionType(constructor);
-        return new FactoryConstructorTypeInformation(constructor, type);
+        return new FactoryConstructorTypeInformation(
+            abstractValueDomain, constructor, type);
       } else {
-        return new GenerativeConstructorTypeInformation(constructor);
+        return new GenerativeConstructorTypeInformation(
+            abstractValueDomain, constructor);
       }
     }
   }
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 032b254..b09dfcc 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -6,7 +6,7 @@
 
 import '../common/names.dart' show Identifiers;
 import '../elements/entities.dart';
-import '../types/masks.dart' show ContainerTypeMask, MapTypeMask;
+import '../types/abstract_value_domain.dart';
 import '../util/util.dart' show Setlet;
 import 'debug.dart' as debug;
 import 'inferrer_engine.dart';
@@ -306,31 +306,33 @@
 
   void visitDynamicCallSiteTypeInformation(
       DynamicCallSiteTypeInformation info) {
-    void addsToContainer(ContainerTypeMask mask) {
-      if (mask.allocationNode != null) {
+    void addsToContainer(AbstractValue mask) {
+      Object allocationNode =
+          inferrer.abstractValueDomain.getAllocationNode(mask);
+      if (allocationNode != null) {
         ListTypeInformation list =
-            inferrer.types.allocatedLists[mask.allocationNode];
+            inferrer.types.allocatedLists[allocationNode];
         listsToAnalyze.add(list);
       } else {
-        // The [ContainerTypeMask] is a union of two containers, and we lose
-        // track of where these containers have been allocated at this point.
+        // The [mask] is a union of two containers, and we lose track of where
+        // these containers have been allocated at this point.
         bailout('Stored in too many containers');
       }
     }
 
-    void addsToMapValue(MapTypeMask mask) {
-      if (mask.allocationNode != null) {
-        MapTypeInformation map =
-            inferrer.types.allocatedMaps[mask.allocationNode];
+    void addsToMapValue(AbstractValue mask) {
+      Object allocationNode =
+          inferrer.abstractValueDomain.getAllocationNode(mask);
+      if (allocationNode != null) {
+        MapTypeInformation map = inferrer.types.allocatedMaps[allocationNode];
         mapsToAnalyze.add(map);
       } else {
-        // The [MapTypeMask] is a union. See comment for [ContainerTypeMask]
-        // above.
+        // The [mask] is a union. See comment for [mask] above.
         bailout('Stored in too many maps');
       }
     }
 
-    void addsToMapKey(MapTypeMask mask) {
+    void addsToMapKey(AbstractValue mask) {
       // We do not track the use of keys from a map, so we have to bail.
       bailout('Used as key in Map');
     }
@@ -338,9 +340,9 @@
     // "a[...] = x" could be a list (container) or map assignemnt.
     if (isIndexSetValue(info)) {
       var receiverType = info.receiver.type;
-      if (receiverType is ContainerTypeMask) {
+      if (inferrer.abstractValueDomain.isContainer(receiverType)) {
         addsToContainer(receiverType);
-      } else if (receiverType is MapTypeMask) {
+      } else if (inferrer.abstractValueDomain.isMap(receiverType)) {
         addsToMapValue(receiverType);
       } else {
         // Not a container or map, so the targets could be any methods. There
@@ -363,7 +365,7 @@
     // Could be:  m[x] = ...;
     if (isIndexSetKey(info)) {
       var receiverType = info.receiver.type;
-      if (receiverType is MapTypeMask) {
+      if (inferrer.abstractValueDomain.isMap(receiverType)) {
         addsToMapKey(receiverType);
       } else {
         bailoutIfReaches(isParameterOfListAddingMethod);
@@ -373,7 +375,7 @@
 
     if (mightAddToContainer(info)) {
       var receiverType = info.receiver.type;
-      if (receiverType is ContainerTypeMask) {
+      if (inferrer.abstractValueDomain.isContainer(receiverType)) {
         addsToContainer(receiverType);
       } else {
         // Not a container, see note above.
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index d8242e9..52ff120 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -6,7 +6,7 @@
 import '../../compiler_new.dart';
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import 'inferrer_engine.dart';
 import 'type_graph_nodes.dart';
 import 'debug.dart';
@@ -80,7 +80,8 @@
         String name = filenameFromElement(element);
         output = compilerOutput.createOutputSink(
             '$outputDir/$name', 'dot', OutputType.debug);
-        _GraphGenerator visitor = new _GraphGenerator(this, element, output);
+        _GraphGenerator visitor = new _GraphGenerator(
+            this, element, output, inferrer.abstractValueDomain.getCompactText);
         for (TypeInformation node in nodes[element]) {
           visitor.visit(node);
         }
@@ -137,12 +138,13 @@
   final Set<TypeInformation> seen = new Set<TypeInformation>();
   final List<TypeInformation> worklist = new List<TypeInformation>();
   final Map<TypeInformation, int> nodeId = <TypeInformation, int>{};
+  final String Function(AbstractValue) formatType;
   int usedIds = 0;
   final OutputSink output;
   final MemberEntity element;
   TypeInformation returnValue;
 
-  _GraphGenerator(this.global, this.element, this.output) {
+  _GraphGenerator(this.global, this.element, this.output, this.formatType) {
     returnValue = global.inferrer.types.getInferredTypeOfMember(element);
     getNode(returnValue); // Ensure return value is part of graph.
     append('digraph {');
@@ -413,41 +415,3 @@
     addNode(info, 'Yield\n$text');
   }
 }
-
-/// Convert the given TypeMask to a compact string format.
-///
-/// The default format is too verbose for the graph format since long strings
-/// create oblong nodes that obstruct the graph layout.
-String formatType(TypeMask type) {
-  if (type is FlatTypeMask) {
-    // TODO(asgerf): Disambiguate classes whose name is not unique. Using the
-    //     library name for all classes is not a good idea, since library names
-    //     can be really long and mess up the layout.
-    // Capitalize Null to emphasize that it's the null type mask and not
-    // a null value we accidentally printed out.
-    if (type.isEmptyOrNull) return type.isNullable ? 'Null' : 'Empty';
-    String nullFlag = type.isNullable ? '?' : '';
-    String subFlag = type.isExact ? '' : type.isSubclass ? '+' : '*';
-    return '${type.base.name}$nullFlag$subFlag';
-  }
-  if (type is UnionTypeMask) {
-    return type.disjointMasks.map(formatType).join(' | ');
-  }
-  if (type is ContainerTypeMask) {
-    String container = formatType(type.forwardTo);
-    String member = formatType(type.elementType);
-    return '$container<$member>';
-  }
-  if (type is MapTypeMask) {
-    String container = formatType(type.forwardTo);
-    String key = formatType(type.keyType);
-    String value = formatType(type.valueType);
-    return '$container<$key,$value>';
-  }
-  if (type is ValueTypeMask) {
-    String baseType = formatType(type.forwardTo);
-    String value = type.value.toStructuredText();
-    return '$baseType=$value';
-  }
-  return '$type'; // Fall back on toString if not supported here.
-}
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index d6482a3..e07ddc6 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -10,7 +10,7 @@
 import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClosedWorld, ClosedWorldRefiner;
+import '../world.dart' show JClosedWorld;
 import 'inferrer_engine.dart';
 import 'type_graph_nodes.dart';
 
@@ -48,11 +48,9 @@
 abstract class TypeGraphInferrer<T> implements TypesInferrer<T> {
   InferrerEngine<T> inferrer;
   final bool _disableTypeInference;
-  final ClosedWorld closedWorld;
-  final ClosedWorldRefiner closedWorldRefiner;
+  final JClosedWorld closedWorld;
 
-  TypeGraphInferrer(this.closedWorld, this.closedWorldRefiner,
-      {bool disableTypeInference: false})
+  TypeGraphInferrer(this.closedWorld, {bool disableTypeInference: false})
       : this._disableTypeInference = disableTypeInference;
 
   String get name => 'Graph inferrer';
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index cb9971a..ce1cc11 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -12,17 +12,10 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
-import '../types/masks.dart'
-    show
-        CommonMasks,
-        ContainerTypeMask,
-        DictionaryTypeMask,
-        MapTypeMask,
-        TypeMask,
-        ValueTypeMask;
+import '../types/abstract_value_domain.dart';
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart' show ImmutableEmptySet, Setlet;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'debug.dart' as debug;
 import 'locals_handler.dart' show ArgumentsTypes;
 import 'inferrer_engine.dart';
@@ -50,7 +43,7 @@
 
   /// The type the inferrer has found for this [TypeInformation].
   /// Initially empty.
-  TypeMask type = const TypeMask.nonNullEmpty();
+  AbstractValue type;
 
   /// The graph node of the member this [TypeInformation] node belongs to.
   final MemberTypeInformation context;
@@ -92,20 +85,20 @@
 
   bool get isConcrete => false;
 
-  TypeInformation(this.context)
+  TypeInformation(this.type, this.context)
       : _assignments = <TypeInformation>[],
         users = new Setlet<TypeInformation>();
 
-  TypeInformation.noAssignments(this.context)
+  TypeInformation.noAssignments(this.type, this.context)
       : _assignments = const <TypeInformation>[],
         users = new Setlet<TypeInformation>();
 
-  TypeInformation.untracked()
+  TypeInformation.untracked(this.type)
       : _assignments = const <TypeInformation>[],
         users = const ImmutableEmptySet(),
         context = null;
 
-  TypeInformation.withAssignments(this.context, this._assignments)
+  TypeInformation.withAssignments(this.type, this.context, this._assignments)
       : users = new Setlet<TypeInformation>();
 
   void addUser(TypeInformation user) {
@@ -152,7 +145,7 @@
     }
   }
 
-  TypeMask refine(InferrerEngine inferrer) {
+  AbstractValue refine(InferrerEngine inferrer) {
     return abandonInferencing ? safeType(inferrer) : computeType(inferrer);
   }
 
@@ -160,13 +153,13 @@
    * Computes a new type for this [TypeInformation] node depending on its
    * potentially updated inputs.
    */
-  TypeMask computeType(InferrerEngine inferrer);
+  AbstractValue computeType(InferrerEngine inferrer);
 
   /**
    * Returns an approximation for this [TypeInformation] node that is always
    * safe to use. Used when abandoning inference on a node.
    */
-  TypeMask safeType(InferrerEngine inferrer) {
+  AbstractValue safeType(InferrerEngine inferrer) {
     return inferrer.types.dynamicType.type;
   }
 
@@ -189,7 +182,7 @@
 
   bool reset(InferrerEngine inferrer) {
     if (abandonInferencing) return false;
-    type = const TypeMask.nonNullEmpty();
+    type = inferrer.abstractValueDomain.emptyType;
     refineCount = 0;
     return true;
   }
@@ -259,13 +252,15 @@
  * [getDefaultTypeOfParameter] and [setDefaultTypeOfParameter] for details.
  */
 class PlaceholderTypeInformation extends TypeInformation {
-  PlaceholderTypeInformation(MemberTypeInformation context) : super(context);
+  PlaceholderTypeInformation(
+      AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
+      : super(abstractValueDomain.emptyType, context);
 
   void accept(TypeInformationVisitor visitor) {
     throw new UnsupportedError("Cannot visit placeholder");
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
+  AbstractValue computeType(InferrerEngine inferrer) {
     throw new UnsupportedError("Cannot refine placeholder");
   }
 
@@ -350,11 +345,15 @@
   /// Marker to disable inference for closures in [handleSpecialCases].
   bool disableInferenceForClosures = true;
 
-  ElementTypeInformation._internal(MemberTypeInformation context)
-      : super(context);
+  ElementTypeInformation._internal(
+      AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
+      : super(abstractValueDomain.emptyType, context);
   ElementTypeInformation._withAssignments(
-      MemberTypeInformation context, ParameterAssignments assignments)
-      : super.withAssignments(context, assignments);
+      AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context,
+      ParameterAssignments assignments)
+      : super.withAssignments(
+            abstractValueDomain.emptyType, context, assignments);
 
   String getInferredSignature(TypeSystem types);
 
@@ -399,7 +398,9 @@
    */
   Map<MemberEntity, Setlet<Object>> _callers;
 
-  MemberTypeInformation._internal(this._member) : super._internal(null);
+  MemberTypeInformation._internal(
+      AbstractValueDomain abstractValueDomain, this._member)
+      : super._internal(abstractValueDomain, null);
 
   MemberEntity get member => _member;
 
@@ -452,9 +453,9 @@
   // state of the [isStable] field inherited from [TypeInformation].
   bool get isStable => super.isStable && !isClosurized;
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer);
+  AbstractValue handleSpecialCases(InferrerEngine inferrer);
 
-  TypeMask _handleFunctionCase(
+  AbstractValue _handleFunctionCase(
       FunctionEntity function, InferrerEngine inferrer) {
     if (inferrer.closedWorld.nativeData.isNativeMember(function)) {
       // Use the type annotation as the type for native elements. We
@@ -469,7 +470,8 @@
     return null;
   }
 
-  TypeMask potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     if (inferrer.options.assignmentCheckPolicy.isTrusted ||
         inferrer.options.assignmentCheckPolicy.isEmitted ||
         inferrer.trustTypeAnnotations(_member)) {
@@ -478,16 +480,17 @@
     return mask;
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer);
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer);
 
-  TypeMask computeType(InferrerEngine inferrer) {
-    TypeMask special = handleSpecialCases(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValue special = handleSpecialCases(inferrer);
     if (special != null) return potentiallyNarrowType(special, inferrer);
     return potentiallyNarrowType(
         inferrer.types.computeTypeMask(assignments), inferrer);
   }
 
-  TypeMask safeType(InferrerEngine inferrer) {
+  AbstractValue safeType(InferrerEngine inferrer) {
     return potentiallyNarrowType(super.safeType(inferrer), inferrer);
   }
 
@@ -515,10 +518,11 @@
   FieldEntity get _field => _member;
   final DartType _type;
 
-  FieldTypeInformation(FieldEntity element, this._type)
-      : super._internal(element);
+  FieldTypeInformation(
+      AbstractValueDomain abstractValueDomain, FieldEntity element, this._type)
+      : super._internal(abstractValueDomain, element);
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     if (!inferrer.canFieldBeUsedForGlobalOptimizations(_field) ||
         inferrer.assumeDynamic(_field)) {
       // Do not infer types for fields that have a corresponding annotation or
@@ -540,7 +544,8 @@
     return null;
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type);
   }
 
@@ -558,14 +563,16 @@
   FunctionEntity get _getter => _member;
   final FunctionType _type;
 
-  GetterTypeInformation(FunctionEntity element, this._type)
-      : super._internal(element);
+  GetterTypeInformation(AbstractValueDomain abstractValueDomain,
+      FunctionEntity element, this._type)
+      : super._internal(abstractValueDomain, element);
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_getter, inferrer);
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type.returnType);
   }
 }
@@ -573,13 +580,16 @@
 class SetterTypeInformation extends MemberTypeInformation {
   FunctionEntity get _setter => _member;
 
-  SetterTypeInformation(FunctionEntity element) : super._internal(element);
+  SetterTypeInformation(
+      AbstractValueDomain abstractValueDomain, FunctionEntity element)
+      : super._internal(abstractValueDomain, element);
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_setter, inferrer);
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     return mask;
   }
 }
@@ -588,14 +598,16 @@
   FunctionEntity get _method => _member;
   final FunctionType _type;
 
-  MethodTypeInformation(FunctionEntity element, this._type)
-      : super._internal(element);
+  MethodTypeInformation(AbstractValueDomain abstractValueDomain,
+      FunctionEntity element, this._type)
+      : super._internal(abstractValueDomain, element);
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_method, inferrer);
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type.returnType);
   }
 
@@ -606,29 +618,31 @@
   ConstructorEntity get _constructor => _member;
   final FunctionType _type;
 
-  FactoryConstructorTypeInformation(ConstructorEntity element, this._type)
-      : super._internal(element);
+  FactoryConstructorTypeInformation(AbstractValueDomain abstractValueDomain,
+      ConstructorEntity element, this._type)
+      : super._internal(abstractValueDomain, element);
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
-    CommonMasks abstractValueDomain = inferrer.abstractValueDomain;
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
+    AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     if (_constructor.isFromEnvironmentConstructor) {
       if (_constructor.enclosingClass == inferrer.commonElements.intClass) {
         giveUp(inferrer);
-        return abstractValueDomain.intType.nullable();
+        return abstractValueDomain.includeNull(abstractValueDomain.intType);
       } else if (_constructor.enclosingClass ==
           inferrer.commonElements.boolClass) {
         giveUp(inferrer);
-        return abstractValueDomain.boolType.nullable();
+        return abstractValueDomain.includeNull(abstractValueDomain.boolType);
       } else if (_constructor.enclosingClass ==
           inferrer.commonElements.stringClass) {
         giveUp(inferrer);
-        return abstractValueDomain.stringType.nullable();
+        return abstractValueDomain.includeNull(abstractValueDomain.stringType);
       }
     }
     return _handleFunctionCase(_constructor, inferrer);
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     return _narrowType(inferrer.closedWorld, mask, _type.returnType);
   }
 
@@ -640,14 +654,16 @@
 class GenerativeConstructorTypeInformation extends MemberTypeInformation {
   ConstructorEntity get _constructor => _member;
 
-  GenerativeConstructorTypeInformation(ConstructorEntity element)
-      : super._internal(element);
+  GenerativeConstructorTypeInformation(
+      AbstractValueDomain abstractValueDomain, ConstructorEntity element)
+      : super._internal(abstractValueDomain, element);
 
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     return _handleFunctionCase(_constructor, inferrer);
   }
 
-  TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue _potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     return mask;
   }
 
@@ -675,21 +691,26 @@
   bool _isTearOffClosureParameter = false;
 
   ParameterTypeInformation.localFunction(
-      MemberTypeInformation context, this._parameter, this._type, this._method)
+      AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context,
+      this._parameter,
+      this._type,
+      this._method)
       : _isInstanceMemberParameter = false,
         _isClosureParameter = true,
         _isInitializingFormal = false,
-        super._internal(context);
+        super._internal(abstractValueDomain, context);
 
-  ParameterTypeInformation.static(
+  ParameterTypeInformation.static(AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context, this._parameter, this._type, this._method,
       {bool isInitializingFormal: false})
       : _isInstanceMemberParameter = false,
         _isClosureParameter = false,
         _isInitializingFormal = isInitializingFormal,
-        super._internal(context);
+        super._internal(abstractValueDomain, context);
 
   ParameterTypeInformation.instanceMember(
+      AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context,
       this._parameter,
       this._type,
@@ -698,7 +719,7 @@
       : _isInstanceMemberParameter = true,
         _isClosureParameter = false,
         _isInitializingFormal = false,
-        super._withAssignments(context, assignments);
+        super._withAssignments(abstractValueDomain, context, assignments);
 
   FunctionEntity get method => _method;
 
@@ -719,7 +740,7 @@
   }
 
   // TODO(herhut): Cleanup into one conditional.
-  TypeMask handleSpecialCases(InferrerEngine inferrer) {
+  AbstractValue handleSpecialCases(InferrerEngine inferrer) {
     if (!inferrer.canFunctionParametersBeUsedForGlobalOptimizations(_method) ||
         inferrer.assumeDynamic(_method)) {
       // Do not infer types for parameters that have a corresponding annotation
@@ -749,8 +770,7 @@
       giveUp(inferrer);
       return safeType(inferrer);
     }
-    if (inferrer.closedWorldRefiner
-        .getCurrentlyKnownMightBePassedToApply(_method)) {
+    if (inferrer.closedWorld.getCurrentlyKnownMightBePassedToApply(_method)) {
       giveUp(inferrer);
       return safeType(inferrer);
     }
@@ -767,7 +787,8 @@
     return null;
   }
 
-  TypeMask potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
+  AbstractValue potentiallyNarrowType(
+      AbstractValue mask, InferrerEngine inferrer) {
     if (inferrer.options.parameterCheckPolicy.isTrusted ||
         inferrer.trustTypeAnnotations(_method)) {
       // In checked or strong mode we don't trust the types of the arguments
@@ -804,14 +825,14 @@
     return mask;
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
-    TypeMask special = handleSpecialCases(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValue special = handleSpecialCases(inferrer);
     if (special != null) return special;
     return potentiallyNarrowType(
         inferrer.types.computeTypeMask(assignments), inferrer);
   }
 
-  TypeMask safeType(InferrerEngine inferrer) {
+  AbstractValue safeType(InferrerEngine inferrer) {
     return potentiallyNarrowType(super.safeType(inferrer), inferrer);
   }
 
@@ -866,13 +887,20 @@
   final Object _call;
   final MemberEntity caller;
   final Selector selector;
-  final TypeMask mask;
+  final AbstractValue mask;
   final ArgumentsTypes arguments;
   final bool inLoop;
 
-  CallSiteTypeInformation(MemberTypeInformation context, this._call,
-      this.caller, this.selector, this.mask, this.arguments, this.inLoop)
-      : super.noAssignments(context) {
+  CallSiteTypeInformation(
+      AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context,
+      this._call,
+      this.caller,
+      this.selector,
+      this.mask,
+      this.arguments,
+      this.inLoop)
+      : super.noAssignments(abstractValueDomain.emptyType, context) {
     assert(_call is ir.Node);
   }
 
@@ -891,15 +919,17 @@
   final MemberEntity calledElement;
 
   StaticCallSiteTypeInformation(
+      AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context,
       Object call,
       MemberEntity enclosing,
       this.calledElement,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       ArgumentsTypes arguments,
       bool inLoop)
-      : super(context, call, enclosing, selector, mask, arguments, inLoop);
+      : super(abstractValueDomain, context, call, enclosing, selector, mask,
+            arguments, inLoop);
 
   MemberTypeInformation _getCalledTypeInfo(InferrerEngine inferrer) {
     return inferrer.types.getInferredTypeOfMember(calledElement);
@@ -929,7 +959,7 @@
     return inferrer.typeOfMemberWithSelector(calledElement, selector);
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
+  AbstractValue computeType(InferrerEngine inferrer) {
     if (isSynthesized) {
       assert(arguments != null);
       return _getCalledTypeInfo(inferrer).type;
@@ -971,23 +1001,25 @@
   Iterable<MemberEntity> _concreteTargets;
 
   DynamicCallSiteTypeInformation(
+      AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context,
       this._callType,
       T call,
       MemberEntity enclosing,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       this.receiver,
       ArgumentsTypes arguments,
       bool inLoop,
       this.isConditional)
-      : super(context, call, enclosing, selector, mask, arguments, inLoop) {
+      : super(abstractValueDomain, context, call, enclosing, selector, mask,
+            arguments, inLoop) {
     assert(validCallType(_callType, _call));
   }
 
   void addToGraph(InferrerEngine inferrer) {
     assert(receiver != null);
-    TypeMask typeMask = computeTypedSelector(inferrer);
+    AbstractValue typeMask = computeTypedSelector(inferrer);
     _hasClosureCallTargets =
         inferrer.closedWorld.includesClosureCall(selector, typeMask);
     _concreteTargets = inferrer.closedWorld.locateMembers(selector, typeMask);
@@ -1016,8 +1048,8 @@
 
   Iterable<MemberEntity> get callees => _concreteTargets;
 
-  TypeMask computeTypedSelector(InferrerEngine inferrer) {
-    TypeMask receiverType = receiver.type;
+  AbstractValue computeTypedSelector(InferrerEngine inferrer) {
+    AbstractValue receiverType = receiver.type;
 
     if (mask != receiverType) {
       return receiverType == inferrer.abstractValueDomain.dynamicType
@@ -1047,10 +1079,10 @@
    * code.
    */
   TypeInformation handleIntrisifiedSelector(
-      Selector selector, TypeMask mask, InferrerEngine inferrer) {
-    ClosedWorld closedWorld = inferrer.closedWorld;
+      Selector selector, AbstractValue mask, InferrerEngine inferrer) {
+    JClosedWorld closedWorld = inferrer.closedWorld;
     if (mask == null) return null;
-    if (!mask.containsOnlyInt(closedWorld)) {
+    if (!inferrer.abstractValueDomain.isIntegerOrNull(mask)) {
       return null;
     }
     if (!selector.isCall && !selector.isOperator) return null;
@@ -1143,26 +1175,28 @@
     }
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
+  AbstractValue computeType(InferrerEngine inferrer) {
+    JClosedWorld closedWorld = inferrer.closedWorld;
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
     Iterable<MemberEntity> oldTargets = _concreteTargets;
-    TypeMask typeMask = computeTypedSelector(inferrer);
+    AbstractValue typeMask = computeTypedSelector(inferrer);
     inferrer.updateSelectorInMember(
         caller, _callType, _call, selector, typeMask);
 
-    TypeMask maskToUse =
-        inferrer.closedWorld.extendMaskIfReachesAll(selector, typeMask);
-    bool canReachAll = inferrer.closedWorld.backendUsage.isInvokeOnUsed &&
-        (maskToUse != typeMask);
+    AbstractValue maskToUse =
+        closedWorld.extendMaskIfReachesAll(selector, typeMask);
+    bool canReachAll =
+        closedWorld.backendUsage.isInvokeOnUsed && (maskToUse != typeMask);
 
     // If this call could potentially reach all methods that satisfy
     // the untyped selector (through noSuchMethod's `Invocation`
     // and a call to `delegate`), we iterate over all these methods to
     // update their parameter types.
     _hasClosureCallTargets =
-        inferrer.closedWorld.includesClosureCall(selector, maskToUse);
-    _concreteTargets = inferrer.closedWorld.locateMembers(selector, maskToUse);
+        closedWorld.includesClosureCall(selector, maskToUse);
+    _concreteTargets = closedWorld.locateMembers(selector, maskToUse);
     Iterable<MemberEntity> typedTargets = canReachAll
-        ? inferrer.closedWorld.locateMembers(selector, typeMask)
+        ? closedWorld.locateMembers(selector, typeMask)
         : _concreteTargets;
 
     // Update the call graph if the targets could have changed.
@@ -1196,9 +1230,9 @@
 
     // Walk over the found targets, and compute the joined union type mask
     // for all these targets.
-    TypeMask result;
+    AbstractValue result;
     if (_hasClosureCallTargets) {
-      result = inferrer.abstractValueDomain.dynamicType;
+      result = abstractValueDomain.dynamicType;
     } else {
       result = inferrer.types
           .joinTypeMasks(_concreteTargets.map((MemberEntity element) {
@@ -1208,24 +1242,24 @@
         // `Invocation.delegate`. Note that the `noSuchMethod` targets
         // are included in [typedTargets].
         if (canReachAll && !typedTargets.contains(element)) {
-          return const TypeMask.nonNullEmpty();
+          return abstractValueDomain.emptyType;
         }
         if (inferrer.returnsListElementType(selector, typeMask)) {
-          ContainerTypeMask containerTypeMask = receiver.type;
-          return containerTypeMask.elementType;
+          return abstractValueDomain.getContainerElementType(receiver.type);
         } else if (inferrer.returnsMapValueType(selector, typeMask)) {
-          if (typeMask.isDictionary) {
-            TypeMask arg = arguments.positional[0].type;
-            if (arg is ValueTypeMask && arg.value.isString) {
-              DictionaryTypeMask dictionaryTypeMask = typeMask;
-              StringConstantValue value = arg.value;
+          if (abstractValueDomain.isDictionary(typeMask)) {
+            AbstractValue arg = arguments.positional[0].type;
+            ConstantValue value = abstractValueDomain.getPrimitiveValue(arg);
+            if (value is StringConstantValue) {
               String key = value.stringValue;
-              if (dictionaryTypeMask.typeMap.containsKey(key)) {
+              if (abstractValueDomain.containsDictionaryKey(typeMask, key)) {
                 if (debug.VERBOSE) {
                   print("Dictionary lookup for $key yields "
-                      "${dictionaryTypeMask.typeMap[key]}.");
+                      "${abstractValueDomain.
+                      getDictionaryValueForKey(typeMask, key)}.");
                 }
-                return dictionaryTypeMask.typeMap[key];
+                return abstractValueDomain.getDictionaryValueForKey(
+                    typeMask, key);
               } else {
                 // The typeMap is precise, so if we do not find the key, the lookup
                 // will be [null] at runtime.
@@ -1236,11 +1270,12 @@
               }
             }
           }
-          MapTypeMask mapTypeMask = typeMask;
+          assert(abstractValueDomain.isMap(typeMask));
           if (debug.VERBOSE) {
-            print("Map lookup for $selector yields ${mapTypeMask.valueType}.");
+            print("Map lookup for $selector yields "
+                "${abstractValueDomain.getMapValueType(typeMask)}.");
           }
-          return mapTypeMask.valueType;
+          return abstractValueDomain.getMapValueType(typeMask);
         } else {
           TypeInformation info =
               handleIntrisifiedSelector(selector, typeMask, inferrer);
@@ -1249,10 +1284,10 @@
         }
       }));
     }
-    if (isConditional && receiver.type.isNullable) {
+    if (isConditional && abstractValueDomain.canBeNull(receiver.type)) {
       // Conditional call sites (e.g. `a?.b`) may be null if the receiver is
       // null.
-      result = result.nullable();
+      result = abstractValueDomain.includeNull(result);
     }
     return result;
   }
@@ -1309,22 +1344,24 @@
   final TypeInformation closure;
 
   ClosureCallSiteTypeInformation(
+      AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context,
       Object call,
       MemberEntity enclosing,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       this.closure,
       ArgumentsTypes arguments,
       bool inLoop)
-      : super(context, call, enclosing, selector, mask, arguments, inLoop);
+      : super(abstractValueDomain, context, call, enclosing, selector, mask,
+            arguments, inLoop);
 
   void addToGraph(InferrerEngine inferrer) {
     arguments.forEach((info) => info.addUser(this));
     closure.addUser(this);
   }
 
-  TypeMask computeType(InferrerEngine inferrer) => safeType(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
   Iterable<MemberEntity> get callees {
     throw new UnsupportedError("Cannot compute callees of a closure call.");
@@ -1358,8 +1395,7 @@
  * type.
  */
 class ConcreteTypeInformation extends TypeInformation {
-  ConcreteTypeInformation(TypeMask type) : super.untracked() {
-    this.type = type;
+  ConcreteTypeInformation(AbstractValue type) : super.untracked(type) {
     this.isStable = true;
   }
 
@@ -1385,7 +1421,7 @@
     throw "Not supported";
   }
 
-  TypeMask computeType(InferrerEngine inferrer) => type;
+  AbstractValue computeType(InferrerEngine inferrer) => type;
 
   bool reset(InferrerEngine inferrer) {
     throw "Not supported";
@@ -1403,8 +1439,10 @@
 class StringLiteralTypeInformation extends ConcreteTypeInformation {
   final String value;
 
-  StringLiteralTypeInformation(this.value, TypeMask mask)
-      : super(new ValueTypeMask(mask, new StringConstantValue(value)));
+  StringLiteralTypeInformation(
+      AbstractValueDomain abstractValueDomain, this.value, AbstractValue mask)
+      : super(abstractValueDomain.createPrimitiveValue(
+            mask, new StringConstantValue(value)));
 
   String asString() => value;
   String toString() => 'Type $type value ${value}';
@@ -1417,8 +1455,9 @@
 class BoolLiteralTypeInformation extends ConcreteTypeInformation {
   final bool value;
 
-  BoolLiteralTypeInformation(this.value, TypeMask mask)
-      : super(new ValueTypeMask(
+  BoolLiteralTypeInformation(
+      AbstractValueDomain abstractValueDomain, this.value, AbstractValue mask)
+      : super(abstractValueDomain.createPrimitiveValue(
             mask, value ? new TrueConstantValue() : new FalseConstantValue()));
 
   String toString() => 'Type $type value ${value}';
@@ -1448,10 +1487,11 @@
  *   information on the type of a local.
  */
 class NarrowTypeInformation extends TypeInformation {
-  final TypeMask typeAnnotation;
+  final AbstractValue typeAnnotation;
 
-  NarrowTypeInformation(TypeInformation narrowedType, this.typeAnnotation)
-      : super(narrowedType.context) {
+  NarrowTypeInformation(AbstractValueDomain abstractValueDomain,
+      TypeInformation narrowedType, this.typeAnnotation)
+      : super(abstractValueDomain.emptyType, narrowedType.context) {
     addAssignment(narrowedType);
   }
 
@@ -1460,13 +1500,14 @@
     assert(assignments.length == 1);
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
-    TypeMask input = assignments.first.type;
-    TypeMask intersection =
-        input.intersection(typeAnnotation, inferrer.closedWorld);
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
+    AbstractValue input = assignments.first.type;
+    AbstractValue intersection =
+        abstractValueDomain.intersection(input, typeAnnotation);
     if (debug.ANOMALY_WARN) {
-      if (!input.containsMask(intersection, inferrer.closedWorld) ||
-          !typeAnnotation.containsMask(intersection, inferrer.closedWorld)) {
+      if (!abstractValueDomain.contains(input, intersection) ||
+          !abstractValueDomain.contains(typeAnnotation, intersection)) {
         print("ANOMALY WARNING: narrowed $input to $intersection via "
             "$typeAnnotation");
       }
@@ -1493,13 +1534,13 @@
   /** Whether the element type in that container has been inferred. */
   bool inferred = false;
 
-  InferredTypeInformation(
+  InferredTypeInformation(AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context, TypeInformation parentType)
-      : super(context) {
+      : super(abstractValueDomain.emptyType, context) {
     if (parentType != null) addAssignment(parentType);
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
+  AbstractValue computeType(InferrerEngine inferrer) {
     if (!inferred) return safeType(inferrer);
     return inferrer.types.computeTypeMask(assignments);
   }
@@ -1517,7 +1558,7 @@
   final ElementInContainerTypeInformation elementType;
 
   /** The container type before it is inferred. */
-  final ContainerTypeMask originalType;
+  final AbstractValue originalType;
 
   /** The length at the allocation site. */
   final int originalLength;
@@ -1531,11 +1572,14 @@
    */
   bool checksGrowable = true;
 
-  ListTypeInformation(MemberTypeInformation context, this.originalType,
-      this.elementType, this.originalLength)
-      : super(context) {
-    type = originalType;
-    inferredLength = originalType.length;
+  ListTypeInformation(
+      AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context,
+      this.originalType,
+      this.elementType,
+      this.originalLength)
+      : super(originalType, context) {
+    inferredLength = abstractValueDomain.getContainerLength(originalType);
     elementType.addUser(this);
   }
 
@@ -1549,22 +1593,23 @@
     return elementType.isStable && super.hasStableType(inferrer);
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
-    dynamic mask = type;
-    if (!mask.isContainer ||
-        mask.elementType != elementType.type ||
-        mask.length != inferredLength) {
-      return new ContainerTypeMask(
-          originalType.forwardTo,
-          originalType.allocationNode,
-          originalType.allocationElement,
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
+    AbstractValue mask = type;
+    if (!abstractValueDomain.isContainer(type) ||
+        abstractValueDomain.getContainerElementType(type) != elementType.type ||
+        abstractValueDomain.getContainerLength(type) != inferredLength) {
+      return abstractValueDomain.createContainerValue(
+          abstractValueDomain.getGeneralization(originalType),
+          abstractValueDomain.getAllocationNode(originalType),
+          abstractValueDomain.getAllocationElement(originalType),
           elementType.type,
           inferredLength);
     }
     return mask;
   }
 
-  TypeMask safeType(InferrerEngine inferrer) => originalType;
+  AbstractValue safeType(InferrerEngine inferrer) => originalType;
 
   void cleanup() {
     super.cleanup();
@@ -1578,8 +1623,9 @@
  * elements in a [ListTypeInformation].
  */
 class ElementInContainerTypeInformation extends InferredTypeInformation {
-  ElementInContainerTypeInformation(MemberTypeInformation context, elementType)
-      : super(context, elementType);
+  ElementInContainerTypeInformation(AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context, elementType)
+      : super(abstractValueDomain, context, elementType);
 
   String toString() => 'Element in container $type';
 
@@ -1599,7 +1645,7 @@
   // These fields track the overall type of the keys/values in the map.
   final KeyInMapTypeInformation keyType;
   final ValueInMapTypeInformation valueType;
-  final MapTypeMask originalType;
+  final AbstractValue originalType;
 
   // Set to false if a statically unknown key flows into this map.
   bool _allKeysAreStrings = true;
@@ -1608,19 +1654,20 @@
 
   MapTypeInformation(MemberTypeInformation context, this.originalType,
       this.keyType, this.valueType)
-      : super(context) {
+      : super(originalType, context) {
     keyType.addUser(this);
     valueType.addUser(this);
-    type = originalType;
   }
 
-  TypeInformation addEntryAssignment(TypeInformation key, TypeInformation value,
+  TypeInformation addEntryAssignment(AbstractValueDomain abstractValueDomain,
+      TypeInformation key, TypeInformation value,
       [bool nonNull = false]) {
     TypeInformation newInfo = null;
     if (_allKeysAreStrings && key is StringLiteralTypeInformation) {
       String keyString = key.asString();
       typeInfoMap.putIfAbsent(keyString, () {
-        newInfo = new ValueInMapTypeInformation(context, null, nonNull);
+        newInfo = new ValueInMapTypeInformation(
+            abstractValueDomain, context, null, nonNull);
         return newInfo;
       });
       typeInfoMap[keyString].addAssignment(value);
@@ -1635,13 +1682,14 @@
     return newInfo;
   }
 
-  List<TypeInformation> addMapAssignment(MapTypeInformation other) {
+  List<TypeInformation> addMapAssignment(
+      AbstractValueDomain abstractValueDomain, MapTypeInformation other) {
     List<TypeInformation> newInfos = <TypeInformation>[];
     if (_allKeysAreStrings && other.inDictionaryMode) {
       other.typeInfoMap.forEach((keyString, value) {
         typeInfoMap.putIfAbsent(keyString, () {
-          TypeInformation newInfo =
-              new ValueInMapTypeInformation(context, null, false);
+          TypeInformation newInfo = new ValueInMapTypeInformation(
+              abstractValueDomain, context, null, false);
           newInfos.add(newInfo);
           return newInfo;
         });
@@ -1670,49 +1718,51 @@
     return visitor.visitMapTypeInformation(this);
   }
 
-  TypeMask toTypeMask(InferrerEngine inferrer) {
+  AbstractValue toTypeMask(InferrerEngine inferrer) {
+    AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
     if (inDictionaryMode) {
-      Map<String, TypeMask> mappings = new Map<String, TypeMask>();
+      Map<String, AbstractValue> mappings = new Map<String, AbstractValue>();
       for (var key in typeInfoMap.keys) {
         mappings[key] = typeInfoMap[key].type;
       }
-      return new DictionaryTypeMask(
-          originalType.forwardTo,
-          originalType.allocationNode,
-          originalType.allocationElement,
+      return inferrer.abstractValueDomain.createDictionaryValue(
+          abstractValueDomain.getGeneralization(originalType),
+          abstractValueDomain.getAllocationNode(originalType),
+          abstractValueDomain.getAllocationElement(originalType),
           keyType.type,
           valueType.type,
           mappings);
     } else {
-      return new MapTypeMask(
-          originalType.forwardTo,
-          originalType.allocationNode,
-          originalType.allocationElement,
+      return inferrer.abstractValueDomain.createMapValue(
+          abstractValueDomain.getGeneralization(originalType),
+          abstractValueDomain.getAllocationNode(originalType),
+          abstractValueDomain.getAllocationElement(originalType),
           keyType.type,
           valueType.type);
     }
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
-    if (type.isDictionary != inDictionaryMode) {
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
+    if (abstractValueDomain.isDictionary(type) != inDictionaryMode) {
       return toTypeMask(inferrer);
-    } else if (type.isDictionary) {
+    } else if (abstractValueDomain.isDictionary(type)) {
       assert(inDictionaryMode);
-      DictionaryTypeMask mask = type;
-      for (var key in typeInfoMap.keys) {
+      for (String key in typeInfoMap.keys) {
         TypeInformation value = typeInfoMap[key];
-        if (!mask.typeMap.containsKey(key) &&
-            !value.type.containsAll(inferrer.closedWorld) &&
-            !value.type.isNullable) {
+        if (!abstractValueDomain.containsDictionaryKey(type, key) &&
+            !abstractValueDomain.containsAll(value.type) &&
+            !abstractValueDomain.canBeNull(value.type)) {
           return toTypeMask(inferrer);
         }
-        if (mask.typeMap[key] != typeInfoMap[key].type) {
+        if (abstractValueDomain.getDictionaryValueForKey(type, key) !=
+            typeInfoMap[key].type) {
           return toTypeMask(inferrer);
         }
       }
-    } else if (type.isMap) {
-      MapTypeMask mask = type;
-      if (mask.keyType != keyType.type || mask.valueType != valueType.type) {
+    } else if (abstractValueDomain.isMap(type)) {
+      if (abstractValueDomain.getMapKeyType(type) != keyType.type ||
+          abstractValueDomain.getMapValueType(type) != valueType.type) {
         return toTypeMask(inferrer);
       }
     } else {
@@ -1722,7 +1772,7 @@
     return type;
   }
 
-  TypeMask safeType(InferrerEngine inferrer) => originalType;
+  AbstractValue safeType(InferrerEngine inferrer) => originalType;
 
   bool hasStableType(InferrerEngine inferrer) {
     return keyType.isStable &&
@@ -1750,9 +1800,9 @@
  * for the keys in a [MapTypeInformation]
  */
 class KeyInMapTypeInformation extends InferredTypeInformation {
-  KeyInMapTypeInformation(
+  KeyInMapTypeInformation(AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context, TypeInformation keyType)
-      : super(context, keyType);
+      : super(abstractValueDomain, context, keyType);
 
   accept(TypeInformationVisitor visitor) {
     return visitor.visitKeyInMapTypeInformation(this);
@@ -1771,19 +1821,19 @@
   // mode can ever be marked as [nonNull].
   final bool nonNull;
 
-  ValueInMapTypeInformation(
+  ValueInMapTypeInformation(AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context, TypeInformation valueType,
       [this.nonNull = false])
-      : super(context, valueType);
+      : super(abstractValueDomain, context, valueType);
 
   accept(TypeInformationVisitor visitor) {
     return visitor.visitValueInMapTypeInformation(this);
   }
 
-  TypeMask computeType(InferrerEngine inferrer) {
+  AbstractValue computeType(InferrerEngine inferrer) {
     return nonNull
         ? super.computeType(inferrer)
-        : super.computeType(inferrer).nullable();
+        : inferrer.abstractValueDomain.includeNull(super.computeType(inferrer));
   }
 
   String toString() => 'Value in Map $type';
@@ -1798,12 +1848,12 @@
   final Local variable;
   final bool isTry;
 
-  PhiElementTypeInformation(
+  PhiElementTypeInformation(AbstractValueDomain abstractValueDomain,
       MemberTypeInformation context, this.branchNode, this.variable,
       {this.isTry})
-      : super(context);
+      : super(abstractValueDomain.emptyType, context);
 
-  TypeMask computeType(InferrerEngine inferrer) {
+  AbstractValue computeType(InferrerEngine inferrer) {
     return inferrer.types.computeTypeMask(assignments);
   }
 
@@ -1835,14 +1885,15 @@
     with ApplyableTypeInformation {
   final FunctionEntity _element;
 
-  ClosureTypeInformation(MemberTypeInformation context, this._element)
-      : super(context);
+  ClosureTypeInformation(AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context, this._element)
+      : super(abstractValueDomain.emptyType, context);
 
   FunctionEntity get closure => _element;
 
-  TypeMask computeType(InferrerEngine inferrer) => safeType(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
-  TypeMask safeType(InferrerEngine inferrer) {
+  AbstractValue safeType(InferrerEngine inferrer) {
     return inferrer.types.functionType.type;
   }
 
@@ -1900,11 +1951,12 @@
 class AwaitTypeInformation<T> extends TypeInformation {
   final T _node;
 
-  AwaitTypeInformation(MemberTypeInformation context, this._node)
-      : super(context);
+  AwaitTypeInformation(AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context, this._node)
+      : super(abstractValueDomain.emptyType, context);
 
   // TODO(22894): Compute a better type here.
-  TypeMask computeType(InferrerEngine inferrer) => safeType(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
   String get debugName => '$_node';
 
@@ -1918,10 +1970,11 @@
 class YieldTypeInformation<T> extends TypeInformation {
   final T _node;
 
-  YieldTypeInformation(MemberTypeInformation context, this._node)
-      : super(context);
+  YieldTypeInformation(AbstractValueDomain abstractValueDomain,
+      MemberTypeInformation context, this._node)
+      : super(abstractValueDomain.emptyType, context);
 
-  TypeMask computeType(InferrerEngine inferrer) => safeType(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
 
   String get debugName => '$_node';
 
@@ -1954,10 +2007,11 @@
   T visitYieldTypeInformation(YieldTypeInformation info);
 }
 
-TypeMask _narrowType(
-    ClosedWorld closedWorld, TypeMask type, DartType annotation,
+AbstractValue _narrowType(
+    JClosedWorld closedWorld, AbstractValue type, DartType annotation,
     {bool isNullable: true}) {
-  TypeMask otherType;
+  AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+  AbstractValue otherType;
   if (annotation.treatAsDynamic) {
     return type;
   } else if (annotation.isInterfaceType) {
@@ -1965,7 +2019,7 @@
     if (interfaceType.element == closedWorld.commonElements.objectClass) {
       return type;
     }
-    otherType = new TypeMask.nonNullSubtype(interfaceType.element, closedWorld);
+    otherType = abstractValueDomain.createNonNullSubtype(interfaceType.element);
   } else if (annotation.isVoid) {
     return type;
   } else if (annotation.isTypedef || annotation.isFunctionType) {
@@ -1978,7 +2032,11 @@
     // TODO(ngeoffray): Narrow to bound.
     return type;
   }
-  if (isNullable) otherType = otherType.nullable();
-  if (type == null) return otherType;
-  return type.intersection(otherType, closedWorld);
+  if (isNullable) {
+    otherType = abstractValueDomain.includeNull(otherType);
+  }
+  if (type == null) {
+    return otherType;
+  }
+  return abstractValueDomain.intersection(type, otherType);
 }
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index 3d3c9c8..b5c8895 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -5,7 +5,7 @@
 import '../common.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../universe/selector.dart';
 import '../world.dart';
 import 'type_graph_nodes.dart';
@@ -14,11 +14,14 @@
 /// information for nodes.
 abstract class TypeSystemStrategy<T> {
   /// Creates [MemberTypeInformation] for [member].
-  MemberTypeInformation createMemberTypeInformation(MemberEntity member);
+  MemberTypeInformation createMemberTypeInformation(
+      AbstractValueDomain abstractValueDomain, MemberEntity member);
 
   /// Creates [ParameterTypeInformation] for [parameter].
   ParameterTypeInformation createParameterTypeInformation(
-      Local parameter, TypeSystem<T> types);
+      AbstractValueDomain abstractValueDomain,
+      Local parameter,
+      TypeSystem<T> types);
 
   /// Calls [f] for each parameter in [function].
   void forEachParameter(FunctionEntity function, void f(Local parameter));
@@ -43,7 +46,7 @@
  * The class [SimpleInferrerVisitor] will use when working on types.
  */
 class TypeSystem<T> {
-  final ClosedWorld closedWorld;
+  final JClosedWorld _closedWorld;
   final TypeSystemStrategy<T> strategy;
 
   /// [parameterTypeInformations] and [memberTypeInformations] ordered by
@@ -68,8 +71,8 @@
   final Set<TypeInformation> allocatedClosures = new Set<TypeInformation>();
 
   /// Cache of [ConcreteTypeInformation].
-  final Map<TypeMask, TypeInformation> concreteTypes =
-      new Map<TypeMask, TypeInformation>();
+  final Map<AbstractValue, TypeInformation> concreteTypes =
+      new Map<AbstractValue, TypeInformation>();
 
   /// List of [TypeInformation]s for calls inside method bodies.
   final List<CallSiteTypeInformation> allocatedCalls =
@@ -95,11 +98,12 @@
         allocatedTypes
       ].expand((x) => x);
 
-  TypeSystem(this.closedWorld, this.strategy) {
-    nonNullEmptyType = getConcreteTypeFor(commonMasks.emptyType);
+  TypeSystem(this._closedWorld, this.strategy) {
+    nonNullEmptyType = getConcreteTypeFor(_abstractValueDomain.emptyType);
   }
 
-  CommonMasks get commonMasks => closedWorld.abstractValueDomain;
+  AbstractValueDomain get _abstractValueDomain =>
+      _closedWorld.abstractValueDomain;
 
   /// Used to group [TypeInformation] nodes by the element that triggered their
   /// creation.
@@ -117,111 +121,120 @@
   TypeInformation nullTypeCache;
   TypeInformation get nullType {
     if (nullTypeCache != null) return nullTypeCache;
-    return nullTypeCache = getConcreteTypeFor(commonMasks.nullType);
+    return nullTypeCache = getConcreteTypeFor(_abstractValueDomain.nullType);
   }
 
   TypeInformation intTypeCache;
   TypeInformation get intType {
     if (intTypeCache != null) return intTypeCache;
-    return intTypeCache = getConcreteTypeFor(commonMasks.intType);
+    return intTypeCache = getConcreteTypeFor(_abstractValueDomain.intType);
   }
 
   TypeInformation uint32TypeCache;
   TypeInformation get uint32Type {
     if (uint32TypeCache != null) return uint32TypeCache;
-    return uint32TypeCache = getConcreteTypeFor(commonMasks.uint32Type);
+    return uint32TypeCache =
+        getConcreteTypeFor(_abstractValueDomain.uint32Type);
   }
 
   TypeInformation uint31TypeCache;
   TypeInformation get uint31Type {
     if (uint31TypeCache != null) return uint31TypeCache;
-    return uint31TypeCache = getConcreteTypeFor(commonMasks.uint31Type);
+    return uint31TypeCache =
+        getConcreteTypeFor(_abstractValueDomain.uint31Type);
   }
 
   TypeInformation positiveIntTypeCache;
   TypeInformation get positiveIntType {
     if (positiveIntTypeCache != null) return positiveIntTypeCache;
     return positiveIntTypeCache =
-        getConcreteTypeFor(commonMasks.positiveIntType);
+        getConcreteTypeFor(_abstractValueDomain.positiveIntType);
   }
 
   TypeInformation doubleTypeCache;
   TypeInformation get doubleType {
     if (doubleTypeCache != null) return doubleTypeCache;
-    return doubleTypeCache = getConcreteTypeFor(commonMasks.doubleType);
+    return doubleTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.doubleType);
   }
 
   TypeInformation numTypeCache;
   TypeInformation get numType {
     if (numTypeCache != null) return numTypeCache;
-    return numTypeCache = getConcreteTypeFor(commonMasks.numType);
+    return numTypeCache = getConcreteTypeFor(_abstractValueDomain.numType);
   }
 
   TypeInformation boolTypeCache;
   TypeInformation get boolType {
     if (boolTypeCache != null) return boolTypeCache;
-    return boolTypeCache = getConcreteTypeFor(commonMasks.boolType);
+    return boolTypeCache = getConcreteTypeFor(_abstractValueDomain.boolType);
   }
 
   TypeInformation functionTypeCache;
   TypeInformation get functionType {
     if (functionTypeCache != null) return functionTypeCache;
-    return functionTypeCache = getConcreteTypeFor(commonMasks.functionType);
+    return functionTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.functionType);
   }
 
   TypeInformation listTypeCache;
   TypeInformation get listType {
     if (listTypeCache != null) return listTypeCache;
-    return listTypeCache = getConcreteTypeFor(commonMasks.listType);
+    return listTypeCache = getConcreteTypeFor(_abstractValueDomain.listType);
   }
 
   TypeInformation constListTypeCache;
   TypeInformation get constListType {
     if (constListTypeCache != null) return constListTypeCache;
-    return constListTypeCache = getConcreteTypeFor(commonMasks.constListType);
+    return constListTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.constListType);
   }
 
   TypeInformation fixedListTypeCache;
   TypeInformation get fixedListType {
     if (fixedListTypeCache != null) return fixedListTypeCache;
-    return fixedListTypeCache = getConcreteTypeFor(commonMasks.fixedListType);
+    return fixedListTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.fixedListType);
   }
 
   TypeInformation growableListTypeCache;
   TypeInformation get growableListType {
     if (growableListTypeCache != null) return growableListTypeCache;
     return growableListTypeCache =
-        getConcreteTypeFor(commonMasks.growableListType);
+        getConcreteTypeFor(_abstractValueDomain.growableListType);
   }
 
   TypeInformation mapTypeCache;
   TypeInformation get mapType {
     if (mapTypeCache != null) return mapTypeCache;
-    return mapTypeCache = getConcreteTypeFor(commonMasks.mapType);
+    return mapTypeCache = getConcreteTypeFor(_abstractValueDomain.mapType);
   }
 
   TypeInformation constMapTypeCache;
   TypeInformation get constMapType {
     if (constMapTypeCache != null) return constMapTypeCache;
-    return constMapTypeCache = getConcreteTypeFor(commonMasks.constMapType);
+    return constMapTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.constMapType);
   }
 
   TypeInformation stringTypeCache;
   TypeInformation get stringType {
     if (stringTypeCache != null) return stringTypeCache;
-    return stringTypeCache = getConcreteTypeFor(commonMasks.stringType);
+    return stringTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.stringType);
   }
 
   TypeInformation typeTypeCache;
   TypeInformation get typeType {
     if (typeTypeCache != null) return typeTypeCache;
-    return typeTypeCache = getConcreteTypeFor(commonMasks.typeType);
+    return typeTypeCache = getConcreteTypeFor(_abstractValueDomain.typeType);
   }
 
   TypeInformation dynamicTypeCache;
   TypeInformation get dynamicType {
     if (dynamicTypeCache != null) return dynamicTypeCache;
-    return dynamicTypeCache = getConcreteTypeFor(commonMasks.dynamicType);
+    return dynamicTypeCache =
+        getConcreteTypeFor(_abstractValueDomain.dynamicType);
   }
 
   TypeInformation asyncFutureTypeCache;
@@ -229,31 +242,33 @@
   TypeInformation get asyncFutureType {
     if (asyncFutureTypeCache != null) return asyncFutureTypeCache;
     return asyncFutureTypeCache =
-        getConcreteTypeFor(commonMasks.asyncFutureType);
+        getConcreteTypeFor(_abstractValueDomain.asyncFutureType);
   }
 
   TypeInformation syncStarIterableTypeCache;
   TypeInformation get syncStarIterableType {
     if (syncStarIterableTypeCache != null) return syncStarIterableTypeCache;
     return syncStarIterableTypeCache =
-        getConcreteTypeFor(commonMasks.syncStarIterableType);
+        getConcreteTypeFor(_abstractValueDomain.syncStarIterableType);
   }
 
   TypeInformation asyncStarStreamTypeCache;
   TypeInformation get asyncStarStreamType {
     if (asyncStarStreamTypeCache != null) return asyncStarStreamTypeCache;
     return asyncStarStreamTypeCache =
-        getConcreteTypeFor(commonMasks.asyncStarStreamType);
+        getConcreteTypeFor(_abstractValueDomain.asyncStarStreamType);
   }
 
   TypeInformation nonNullEmptyType;
 
   TypeInformation stringLiteralType(String value) {
-    return new StringLiteralTypeInformation(value, commonMasks.stringType);
+    return new StringLiteralTypeInformation(
+        _abstractValueDomain, value, _abstractValueDomain.stringType);
   }
 
   TypeInformation boolLiteralType(bool value) {
-    return new BoolLiteralTypeInformation(value, commonMasks.boolType);
+    return new BoolLiteralTypeInformation(
+        _abstractValueDomain, value, _abstractValueDomain.boolType);
   }
 
   /**
@@ -270,14 +285,14 @@
       return dynamicType;
     }
     return getConcreteTypeFor(
-        firstType.type.union(secondType.type, closedWorld));
+        _abstractValueDomain.union(firstType.type, secondType.type));
   }
 
   /**
    * Returns `true` if `selector` should be updated to reflect the new
    * `receiverType`.
    */
-  bool selectorNeedsUpdate(TypeInformation info, TypeMask mask) {
+  bool selectorNeedsUpdate(TypeInformation info, AbstractValue mask) {
     return info.type != mask;
   }
 
@@ -290,24 +305,25 @@
    * be null.
    */
   TypeInformation refineReceiver(
-      Selector selector, TypeMask mask, TypeInformation receiver,
+      Selector selector, AbstractValue mask, TypeInformation receiver,
       {bool isConditional}) {
-    if (receiver.type.isExact) return receiver;
-    TypeMask otherType = closedWorld.computeReceiverType(selector, mask);
+    if (_abstractValueDomain.isExact(receiver.type)) return receiver;
+    AbstractValue otherType = _closedWorld.computeReceiverType(selector, mask);
     // Conditional sends (a?.b) can still narrow the possible types of `a`,
     // however, we still need to consider that `a` may be null.
     if (isConditional) {
       // Note: we don't check that receiver.type.isNullable here because this is
       // called during the graph construction.
-      otherType = otherType.nullable();
+      otherType = _abstractValueDomain.includeNull(otherType);
     }
     // If this is refining to nullable subtype of `Object` just return
     // the receiver. We know the narrowing is useless.
-    if (otherType.isNullable && otherType.containsAll(closedWorld)) {
+    if (_abstractValueDomain.canBeNull(otherType) &&
+        _abstractValueDomain.containsAll(otherType)) {
       return receiver;
     }
-    assert(TypeMask.assertIsNormalized(otherType, closedWorld));
-    TypeInformation newType = new NarrowTypeInformation(receiver, otherType);
+    TypeInformation newType =
+        new NarrowTypeInformation(_abstractValueDomain, receiver, otherType);
     allocatedTypes.add(newType);
     return newType;
   }
@@ -321,16 +337,17 @@
       {bool isNullable: true}) {
     if (annotation.treatAsDynamic) return type;
     if (annotation.isVoid) return type;
-    TypeMask otherType;
+    AbstractValue otherType;
     if (annotation.isInterfaceType) {
       InterfaceType interface = annotation;
-      if (interface.element == closedWorld.commonElements.objectClass) {
+      if (interface.element == _closedWorld.commonElements.objectClass) {
         if (isNullable) {
           return type;
         }
-        otherType = dynamicType.type.nonNullable();
+        otherType = _abstractValueDomain.excludeNull(dynamicType.type);
       } else {
-        otherType = new TypeMask.nonNullSubtype(interface.element, closedWorld);
+        otherType =
+            _abstractValueDomain.createNonNullSubtype(interface.element);
       }
     } else if (annotation.isTypedef || annotation.isFunctionType) {
       otherType = functionType.type;
@@ -342,12 +359,14 @@
       // TODO(ngeoffray): Narrow to bound.
       return type;
     }
-    if (isNullable) otherType = otherType.nullable();
-    if (type.type.isExact) {
+    if (isNullable) {
+      otherType = _abstractValueDomain.includeNull(otherType);
+    }
+    if (_abstractValueDomain.isExact(type.type)) {
       return type;
     } else {
-      assert(TypeMask.assertIsNormalized(otherType, closedWorld));
-      TypeInformation newType = new NarrowTypeInformation(type, otherType);
+      TypeInformation newType =
+          new NarrowTypeInformation(_abstractValueDomain, type, otherType);
       allocatedTypes.add(newType);
       return newType;
     }
@@ -357,11 +376,11 @@
    * Returns the non-nullable type of [type].
    */
   TypeInformation narrowNotNull(TypeInformation type) {
-    if (type.type.isExact && !type.type.isNullable) {
+    if (_abstractValueDomain.isExact(type.type)) {
       return type;
     }
-    TypeInformation newType =
-        new NarrowTypeInformation(type, dynamicType.type.nonNullable());
+    TypeInformation newType = new NarrowTypeInformation(_abstractValueDomain,
+        type, _abstractValueDomain.excludeNull(dynamicType.type));
     allocatedTypes.add(newType);
     return newType;
   }
@@ -369,7 +388,8 @@
   ParameterTypeInformation getInferredTypeOfParameter(Local parameter) {
     return parameterTypeInformations.putIfAbsent(parameter, () {
       ParameterTypeInformation typeInformation =
-          strategy.createParameterTypeInformation(parameter, this);
+          strategy.createParameterTypeInformation(
+              _abstractValueDomain, parameter, this);
       _orderedTypeInformations.add(typeInformation);
       return typeInformation;
     });
@@ -380,7 +400,7 @@
         failedAt(member, "Unexpected abstract member $member."));
     return memberTypeInformations.putIfAbsent(member, () {
       MemberTypeInformation typeInformation =
-          strategy.createMemberTypeInformation(member);
+          strategy.createMemberTypeInformation(_abstractValueDomain, member);
       _orderedTypeInformations.add(typeInformation);
       return typeInformation;
     });
@@ -389,7 +409,7 @@
   /**
    * Returns the internal inferrer representation for [mask].
    */
-  ConcreteTypeInformation getConcreteTypeFor(TypeMask mask) {
+  ConcreteTypeInformation getConcreteTypeFor(AbstractValue mask) {
     assert(mask != null);
     return concreteTypes.putIfAbsent(mask, () {
       return new ConcreteTypeInformation(mask);
@@ -409,17 +429,17 @@
 
   TypeInformation nonNullSubtype(ClassEntity cls) {
     assert(strategy.checkClassEntity(cls));
-    return getConcreteTypeFor(new TypeMask.nonNullSubtype(cls, closedWorld));
+    return getConcreteTypeFor(_abstractValueDomain.createNonNullSubtype(cls));
   }
 
   TypeInformation nonNullSubclass(ClassEntity cls) {
     assert(strategy.checkClassEntity(cls));
-    return getConcreteTypeFor(new TypeMask.nonNullSubclass(cls, closedWorld));
+    return getConcreteTypeFor(_abstractValueDomain.createNonNullSubclass(cls));
   }
 
   TypeInformation nonNullExact(ClassEntity cls) {
     assert(strategy.checkClassEntity(cls));
-    return getConcreteTypeFor(new TypeMask.nonNullExact(cls, closedWorld));
+    return getConcreteTypeFor(_abstractValueDomain.createNonNullExact(cls));
   }
 
   TypeInformation nonNullEmpty() {
@@ -434,34 +454,37 @@
       TypeInformation type, T node, MemberEntity enclosing,
       [TypeInformation elementType, int length]) {
     assert(strategy.checkListNode(node));
-    ClassEntity typedDataClass = closedWorld.commonElements.typedDataClass;
+    ClassEntity typedDataClass = _closedWorld.commonElements.typedDataClass;
     bool isTypedArray = typedDataClass != null &&
-        closedWorld.isInstantiated(typedDataClass) &&
-        type.type.satisfies(typedDataClass, closedWorld);
-    bool isConst = (type.type == commonMasks.constListType);
-    bool isFixed =
-        (type.type == commonMasks.fixedListType) || isConst || isTypedArray;
+        _closedWorld.isInstantiated(typedDataClass) &&
+        _abstractValueDomain.isInstanceOfOrNull(type.type, typedDataClass);
+    bool isConst = (type.type == _abstractValueDomain.constListType);
+    bool isFixed = (type.type == _abstractValueDomain.fixedListType) ||
+        isConst ||
+        isTypedArray;
     bool isElementInferred = isConst || isTypedArray;
 
     int inferredLength = isFixed ? length : null;
-    TypeMask elementTypeMask =
+    AbstractValue elementTypeMask =
         isElementInferred ? elementType.type : dynamicType.type;
-    ContainerTypeMask<T> mask = new ContainerTypeMask<T>(
+    AbstractValue mask = _abstractValueDomain.createContainerValue(
         type.type, node, enclosing, elementTypeMask, inferredLength);
     ElementInContainerTypeInformation element =
-        new ElementInContainerTypeInformation(currentMember, elementType);
+        new ElementInContainerTypeInformation(
+            _abstractValueDomain, currentMember, elementType);
     element.inferred = isElementInferred;
 
     allocatedTypes.add(element);
-    return allocatedLists[node] =
-        new ListTypeInformation(currentMember, mask, element, length);
+    return allocatedLists[node] = new ListTypeInformation(
+        _abstractValueDomain, currentMember, mask, element, length);
   }
 
   /// Creates a [TypeInformation] object either for the closurization of a
   /// static or top-level method [element] used as a function constant or for
   /// the synthesized 'call' method [element] created for a local function.
   TypeInformation allocateClosure(FunctionEntity element) {
-    TypeInformation result = new ClosureTypeInformation(currentMember, element);
+    TypeInformation result = new ClosureTypeInformation(
+        _abstractValueDomain, currentMember, element);
     allocatedClosures.add(result);
     return result;
   }
@@ -471,24 +494,24 @@
       [List<TypeInformation> keyTypes, List<TypeInformation> valueTypes]) {
     assert(strategy.checkMapNode(node));
     assert(keyTypes.length == valueTypes.length);
-    bool isFixed = (type.type == commonMasks.constMapType);
+    bool isFixed = (type.type == _abstractValueDomain.constMapType);
 
-    TypeMask keyType, valueType;
+    AbstractValue keyType, valueType;
     if (isFixed) {
       keyType = keyTypes.fold(nonNullEmptyType.type,
-          (type, info) => type.union(info.type, closedWorld));
+          (type, info) => _abstractValueDomain.union(type, info.type));
       valueType = valueTypes.fold(nonNullEmptyType.type,
-          (type, info) => type.union(info.type, closedWorld));
+          (type, info) => _abstractValueDomain.union(type, info.type));
     } else {
       keyType = valueType = dynamicType.type;
     }
-    MapTypeMask mask =
-        new MapTypeMask(type.type, node, element, keyType, valueType);
+    AbstractValue mask = _abstractValueDomain.createMapValue(
+        type.type, node, element, keyType, valueType);
 
     TypeInformation keyTypeInfo =
-        new KeyInMapTypeInformation(currentMember, null);
-    TypeInformation valueTypeInfo =
-        new ValueInMapTypeInformation(currentMember, null);
+        new KeyInMapTypeInformation(_abstractValueDomain, currentMember, null);
+    TypeInformation valueTypeInfo = new ValueInMapTypeInformation(
+        _abstractValueDomain, currentMember, null);
     allocatedTypes.add(keyTypeInfo);
     allocatedTypes.add(valueTypeInfo);
 
@@ -496,8 +519,8 @@
         new MapTypeInformation(currentMember, mask, keyTypeInfo, valueTypeInfo);
 
     for (int i = 0; i < keyTypes.length; ++i) {
-      TypeInformation newType =
-          map.addEntryAssignment(keyTypes[i], valueTypes[i], true);
+      TypeInformation newType = map.addEntryAssignment(
+          _abstractValueDomain, keyTypes[i], valueTypes[i], true);
       if (newType != null) allocatedTypes.add(newType);
     }
 
@@ -509,7 +532,7 @@
     return map;
   }
 
-  TypeMask newTypedSelector(TypeInformation info, TypeMask mask) {
+  AbstractValue newTypedSelector(TypeInformation info, AbstractValue mask) {
     // Only type the selector if [info] is concrete, because the other
     // kinds of [TypeInformation] have the empty type at this point of
     // analysis.
@@ -522,7 +545,7 @@
   TypeInformation allocateDiamondPhi(
       TypeInformation firstInput, TypeInformation secondInput) {
     PhiElementTypeInformation<T> result = new PhiElementTypeInformation<T>(
-        currentMember, null, null,
+        _abstractValueDomain, currentMember, null, null,
         isTry: false);
     result.addAssignment(firstInput);
     result.addAssignment(secondInput);
@@ -533,7 +556,7 @@
   PhiElementTypeInformation<T> _addPhi(
       T node, Local variable, TypeInformation inputType, bool isTry) {
     PhiElementTypeInformation<T> result = new PhiElementTypeInformation<T>(
-        currentMember, node, variable,
+        _abstractValueDomain, currentMember, node, variable,
         isTry: isTry);
     allocatedTypes.add(result);
     result.addAssignment(inputType);
@@ -595,32 +618,33 @@
     return phiType;
   }
 
-  TypeMask computeTypeMask(Iterable<TypeInformation> assignments) {
+  AbstractValue computeTypeMask(Iterable<TypeInformation> assignments) {
     return joinTypeMasks(assignments.map((e) => e.type));
   }
 
-  TypeMask joinTypeMasks(Iterable<TypeMask> masks) {
-    var dynamicType = commonMasks.dynamicType;
+  AbstractValue joinTypeMasks(Iterable<AbstractValue> masks) {
+    var dynamicType = _abstractValueDomain.dynamicType;
     // Optimization: we are iterating over masks twice, but because `masks` is a
     // mapped iterable, we save the intermediate results to avoid computing them
     // again.
     var list = [];
-    for (TypeMask mask in masks) {
+    for (AbstractValue mask in masks) {
       // Don't do any work on computing unions if we know that after all that
       // work the result will be `dynamic`.
       // TODO(sigmund): change to `mask == dynamicType` so we can continue to
       // track the non-nullable bit.
-      if (mask.containsAll(closedWorld)) return dynamicType;
+      if (_abstractValueDomain.containsAll(mask)) return dynamicType;
       list.add(mask);
     }
 
-    TypeMask newType = null;
-    for (TypeMask mask in list) {
-      newType = newType == null ? mask : newType.union(mask, closedWorld);
+    AbstractValue newType = null;
+    for (AbstractValue mask in list) {
+      newType =
+          newType == null ? mask : _abstractValueDomain.union(newType, mask);
       // Likewise - stop early if we already reach dynamic.
-      if (newType.containsAll(closedWorld)) return dynamicType;
+      if (_abstractValueDomain.containsAll(newType)) return dynamicType;
     }
 
-    return newType ?? const TypeMask.nonNullEmpty();
+    return newType ?? _abstractValueDomain.emptyType;
   }
 }
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
similarity index 68%
rename from pkg/compiler/lib/src/types/constants.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/constants.dart
index 58a51d7..5003c72b 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
@@ -4,24 +4,24 @@
 
 library types.constants;
 
-import '../common.dart';
-import '../constants/values.dart';
-import '../js_backend/js_backend.dart' show SyntheticConstantKind;
-import '../world.dart' show ClosedWorld;
+import '../../common.dart';
+import '../../constants/values.dart';
+import '../../js_backend/js_backend.dart' show SyntheticConstantKind;
+import '../../world.dart' show JClosedWorld;
 import 'masks.dart';
 
 /// Computes the [TypeMask] for the constant [value].
-TypeMask computeTypeMask(ClosedWorld closedWorld, ConstantValue value) {
+TypeMask computeTypeMask(JClosedWorld closedWorld, ConstantValue value) {
   return value.accept(const ConstantValueTypeMasks(), closedWorld);
 }
 
 class ConstantValueTypeMasks
-    extends ConstantValueVisitor<TypeMask, ClosedWorld> {
+    extends ConstantValueVisitor<TypeMask, JClosedWorld> {
   const ConstantValueTypeMasks();
 
   @override
   TypeMask visitConstructed(
-      ConstructedConstantValue constant, ClosedWorld closedWorld) {
+      ConstructedConstantValue constant, JClosedWorld closedWorld) {
     if (closedWorld.interceptorData.isInterceptedClass(constant.type.element)) {
       return closedWorld.abstractValueDomain.nonNullType;
     }
@@ -30,18 +30,18 @@
 
   @override
   TypeMask visitDeferred(
-      DeferredConstantValue constant, ClosedWorld closedWorld) {
+      DeferredConstantValue constant, JClosedWorld closedWorld) {
     return constant.referenced.accept(this, closedWorld);
   }
 
   @override
   TypeMask visitDeferredGlobal(
-      DeferredGlobalConstantValue constant, ClosedWorld closedWorld) {
+      DeferredGlobalConstantValue constant, JClosedWorld closedWorld) {
     return constant.referenced.accept(this, closedWorld);
   }
 
   @override
-  TypeMask visitDouble(DoubleConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitDouble(DoubleConstantValue constant, JClosedWorld closedWorld) {
     // We have to recognize double constants that are 'is int'.
     if (closedWorld.constantSystem.isInt(constant)) {
       if (constant.isMinusZero) {
@@ -56,7 +56,7 @@
 
   @override
   TypeMask visitSynthetic(
-      SyntheticConstantValue constant, ClosedWorld closedWorld) {
+      SyntheticConstantValue constant, JClosedWorld closedWorld) {
     switch (constant.valueKind) {
       case SyntheticConstantKind.DUMMY_INTERCEPTOR:
         return constant.payload;
@@ -73,24 +73,24 @@
   }
 
   @override
-  TypeMask visitBool(BoolConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitBool(BoolConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.boolType;
   }
 
   @override
   TypeMask visitFunction(
-      FunctionConstantValue constant, ClosedWorld closedWorld) {
+      FunctionConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.functionType;
   }
 
   @override
   TypeMask visitInstantiation(
-      InstantiationConstantValue constant, ClosedWorld closedWorld) {
+      InstantiationConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.functionType;
   }
 
   @override
-  TypeMask visitInt(IntConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitInt(IntConstantValue constant, JClosedWorld closedWorld) {
     if (constant.isUInt31()) return closedWorld.abstractValueDomain.uint31Type;
     if (constant.isUInt32()) return closedWorld.abstractValueDomain.uint32Type;
     if (constant.isPositive())
@@ -100,38 +100,38 @@
 
   @override
   TypeMask visitInterceptor(
-      InterceptorConstantValue constant, ClosedWorld closedWorld) {
+      InterceptorConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.nonNullType;
   }
 
   @override
-  TypeMask visitList(ListConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitList(ListConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.constListType;
   }
 
   @override
-  TypeMask visitMap(MapConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitMap(MapConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.constMapType;
   }
 
   @override
-  TypeMask visitNull(NullConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitNull(NullConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.nullType;
   }
 
   @override
   TypeMask visitNonConstant(
-      NonConstantValue constant, ClosedWorld closedWorld) {
+      NonConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.nullType;
   }
 
   @override
-  TypeMask visitString(StringConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitString(StringConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.stringType;
   }
 
   @override
-  TypeMask visitType(TypeConstantValue constant, ClosedWorld closedWorld) {
+  TypeMask visitType(TypeConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.typeType;
   }
 }
diff --git a/pkg/compiler/lib/src/types/container_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
similarity index 93%
rename from pkg/compiler/lib/src/types/container_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
index fbbd59f..9e35791 100644
--- a/pkg/compiler/lib/src/types/container_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
@@ -7,7 +7,7 @@
 /// A [ContainerTypeMask] is a [TypeMask] for a specific allocation
 /// site of a container (currently only List) that will get specialized
 /// once the [TypeGraphInferrer] phase finds an element type for it.
-class ContainerTypeMask<T> extends ForwardingTypeMask {
+class ContainerTypeMask<T> extends AllocationTypeMask<T> {
   final TypeMask forwardTo;
 
   // The [Node] where this type mask was created.
@@ -50,13 +50,13 @@
         length == other.length;
   }
 
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(dynamic other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
diff --git a/pkg/compiler/lib/src/types/dictionary_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
similarity index 76%
rename from pkg/compiler/lib/src/types/dictionary_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
index 3d92fcc..d04e18a 100644
--- a/pkg/compiler/lib/src/types/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
@@ -14,7 +14,7 @@
  */
 class DictionaryTypeMask<T> extends MapTypeMask<T> {
   // The underlying key/value map of this dictionary.
-  final Map<String, TypeMask> typeMap;
+  final Map<String, AbstractValue> _typeMap;
 
   DictionaryTypeMask(
       TypeMask forwardTo,
@@ -22,43 +22,47 @@
       MemberEntity allocationElement,
       TypeMask keyType,
       TypeMask valueType,
-      this.typeMap)
+      this._typeMap)
       : super(forwardTo, allocationNode, allocationElement, keyType, valueType);
 
   TypeMask nullable() {
     return isNullable
         ? this
         : new DictionaryTypeMask<T>(forwardTo.nullable(), allocationNode,
-            allocationElement, keyType, valueType, typeMap);
+            allocationElement, keyType, valueType, _typeMap);
   }
 
   TypeMask nonNullable() {
     return isNullable
         ? new DictionaryTypeMask<T>(forwardTo.nonNullable(), allocationNode,
-            allocationElement, keyType, valueType, typeMap)
+            allocationElement, keyType, valueType, _typeMap)
         : this;
   }
 
   bool get isDictionary => true;
   bool get isExact => true;
 
+  bool containsKey(String key) => _typeMap.containsKey(key);
+
+  TypeMask getValueForKey(String key) => _typeMap[key];
+
   bool equalsDisregardNull(other) {
     if (other is! DictionaryTypeMask) return false;
     return allocationNode == other.allocationNode &&
         keyType == other.keyType &&
         valueType == other.valueType &&
-        typeMap.keys.every((k) => other.typeMap.containsKey(k)) &&
-        other.typeMap.keys.every(
-            (k) => typeMap.containsKey(k) && typeMap[k] == other.typeMap[k]);
+        _typeMap.keys.every((k) => other._typeMap.containsKey(k)) &&
+        other._typeMap.keys.every(
+            (k) => _typeMap.containsKey(k) && _typeMap[k] == other._typeMap[k]);
   }
 
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(dynamic other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
@@ -70,14 +74,14 @@
       TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
       TypeMask newValueType = valueType.union(other.valueType, closedWorld);
       Map<String, TypeMask> mappings = <String, TypeMask>{};
-      typeMap.forEach((k, v) {
-        if (!other.typeMap.containsKey(k)) {
+      _typeMap.forEach((k, dynamic v) {
+        if (!other._typeMap.containsKey(k)) {
           mappings[k] = v.nullable();
         }
       });
-      other.typeMap.forEach((k, v) {
-        if (typeMap.containsKey(k)) {
-          mappings[k] = v.union(typeMap[k], closedWorld);
+      other._typeMap.forEach((k, v) {
+        if (_typeMap.containsKey(k)) {
+          mappings[k] = v.union(_typeMap[k], closedWorld);
         } else {
           mappings[k] = v.nullable();
         }
@@ -100,11 +104,11 @@
   bool operator ==(other) => super == other;
 
   int get hashCode {
-    return computeHashCode(allocationNode, isNullable, typeMap, forwardTo);
+    return computeHashCode(allocationNode, isNullable, _typeMap, forwardTo);
   }
 
   String toString() {
     return 'Dictionary($forwardTo, key: $keyType, '
-        'value: $valueType, map: $typeMap)';
+        'value: $valueType, map: $_typeMap)';
   }
 }
diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
similarity index 92%
rename from pkg/compiler/lib/src/types/flat_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
index f83240a..644cfd2 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
@@ -50,7 +50,7 @@
    * [TypeMask.assertIsNormalized] with the factory's result returns `true`.
    */
   factory FlatTypeMask.normalized(
-      ClassEntity base, int flags, ClosedWorld world) {
+      ClassEntity base, int flags, JClosedWorld world) {
     if ((flags >> 1) == EMPTY || ((flags >> 1) == EXACT)) {
       return new FlatTypeMask.internal(base, flags);
     }
@@ -94,7 +94,7 @@
     return isNullable ? new FlatTypeMask.internal(base, flags & ~1) : this;
   }
 
-  bool contains(ClassEntity other, ClosedWorld closedWorld) {
+  bool contains(ClassEntity other, JClosedWorld closedWorld) {
     if (isEmptyOrNull) {
       return false;
     } else if (identical(base, other)) {
@@ -109,7 +109,7 @@
     }
   }
 
-  bool isSingleImplementationOf(ClassEntity cls, ClosedWorld closedWorld) {
+  bool isSingleImplementationOf(ClassEntity cls, JClosedWorld closedWorld) {
     // Special case basic types so that, for example, JSString is the
     // single implementation of String.
     // The general optimization is to realize there is only one class that
@@ -138,7 +138,7 @@
     return false;
   }
 
-  bool isInMask(TypeMask other, ClosedWorld closedWorld) {
+  bool isInMask(TypeMask other, JClosedWorld closedWorld) {
     if (isEmptyOrNull) return isNullable ? other.isNullable : true;
     // The empty type contains no classes.
     if (other.isEmptyOrNull) return false;
@@ -171,11 +171,11 @@
     return satisfies(otherBase, closedWorld);
   }
 
-  bool containsMask(TypeMask other, ClosedWorld closedWorld) {
+  bool containsMask(TypeMask other, JClosedWorld closedWorld) {
     return other.isInMask(this, closedWorld);
   }
 
-  bool containsOnlyInt(ClosedWorld closedWorld) {
+  bool containsOnlyInt(JClosedWorld closedWorld) {
     CommonElements commonElements = closedWorld.commonElements;
     return base == closedWorld.commonElements.intClass ||
         base == commonElements.jsIntClass ||
@@ -184,24 +184,24 @@
         base == commonElements.jsUInt32Class;
   }
 
-  bool containsOnlyDouble(ClosedWorld closedWorld) {
+  bool containsOnlyDouble(JClosedWorld closedWorld) {
     return base == closedWorld.commonElements.doubleClass ||
         base == closedWorld.commonElements.jsDoubleClass;
   }
 
-  bool containsOnlyNum(ClosedWorld closedWorld) {
+  bool containsOnlyNum(JClosedWorld closedWorld) {
     return containsOnlyInt(closedWorld) ||
         containsOnlyDouble(closedWorld) ||
         base == closedWorld.commonElements.numClass ||
         base == closedWorld.commonElements.jsNumberClass;
   }
 
-  bool containsOnlyBool(ClosedWorld closedWorld) {
+  bool containsOnlyBool(JClosedWorld closedWorld) {
     return base == closedWorld.commonElements.boolClass ||
         base == closedWorld.commonElements.jsBoolClass;
   }
 
-  bool containsOnlyString(ClosedWorld closedWorld) {
+  bool containsOnlyString(JClosedWorld closedWorld) {
     return base == closedWorld.commonElements.stringClass ||
         base == closedWorld.commonElements.jsStringClass;
   }
@@ -210,7 +210,7 @@
     return base == cls;
   }
 
-  bool satisfies(ClassEntity cls, ClosedWorld closedWorld) {
+  bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
     if (isEmptyOrNull) return false;
     if (closedWorld.isSubtypeOf(base, cls)) return true;
     return false;
@@ -218,7 +218,7 @@
 
   /// Returns the [Entity] if this type represents a single class, otherwise
   /// returns `null`.  This method is conservative.
-  ClassEntity singleClass(ClosedWorld closedWorld) {
+  ClassEntity singleClass(JClosedWorld closedWorld) {
     if (isEmptyOrNull) return null;
     if (isNullable) return null; // It is Null and some other class.
     if (isExact) {
@@ -234,12 +234,12 @@
   /**
    * Returns whether or not this type mask contains all types.
    */
-  bool containsAll(ClosedWorld closedWorld) {
+  bool containsAll(JClosedWorld closedWorld) {
     if (isEmptyOrNull || isExact) return false;
     return identical(base, closedWorld.commonElements.objectClass);
   }
 
-  TypeMask union(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask union(TypeMask other, JClosedWorld closedWorld) {
     assert(other != null);
     assert(TypeMask.assertIsNormalized(this, closedWorld));
     assert(TypeMask.assertIsNormalized(other, closedWorld));
@@ -264,7 +264,7 @@
     }
   }
 
-  TypeMask unionSame(FlatTypeMask other, ClosedWorld closedWorld) {
+  TypeMask unionSame(FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base == other.base);
     assert(TypeMask.assertIsNormalized(this, closedWorld));
     assert(TypeMask.assertIsNormalized(other, closedWorld));
@@ -284,7 +284,7 @@
     }
   }
 
-  TypeMask unionStrictSubclass(FlatTypeMask other, ClosedWorld closedWorld) {
+  TypeMask unionStrictSubclass(FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base != other.base);
     assert(closedWorld.isSubclassOf(other.base, base));
     assert(TypeMask.assertIsNormalized(this, closedWorld));
@@ -311,7 +311,7 @@
         : this;
   }
 
-  TypeMask unionStrictSubtype(FlatTypeMask other, ClosedWorld closedWorld) {
+  TypeMask unionStrictSubtype(FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base != other.base);
     assert(!closedWorld.isSubclassOf(other.base, base));
     assert(closedWorld.isSubtypeOf(other.base, base));
@@ -328,7 +328,7 @@
         : this;
   }
 
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     assert(other != null);
     if (other is! FlatTypeMask) return other.intersection(this, closedWorld);
     assert(TypeMask.assertIsNormalized(this, closedWorld));
@@ -353,7 +353,7 @@
     }
   }
 
-  bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
+  bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
     if (other is! FlatTypeMask) return other.isDisjoint(this, closedWorld);
     FlatTypeMask flatOther = other;
 
@@ -379,7 +379,7 @@
   }
 
   static bool _isDisjointHelper(
-      FlatTypeMask a, FlatTypeMask b, ClosedWorld closedWorld) {
+      FlatTypeMask a, FlatTypeMask b, JClosedWorld closedWorld) {
     if (!a.isSubclass && b.isSubclass) {
       return _isDisjointHelper(b, a, closedWorld);
     }
@@ -394,7 +394,7 @@
     return true;
   }
 
-  TypeMask intersectionSame(FlatTypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersectionSame(FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base == other.base);
     // The two masks share the base type, so we must chose the most
     // constraining kind (the lowest) of the two. Only if both masks
@@ -413,7 +413,7 @@
   }
 
   TypeMask intersectionStrictSubclass(
-      FlatTypeMask other, ClosedWorld closedWorld) {
+      FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base != other.base);
     assert(closedWorld.isSubclassOf(other.base, base));
     // If this mask isn't at least a subclass mask, then the
@@ -433,7 +433,7 @@
   }
 
   TypeMask intersectionStrictSubtype(
-      FlatTypeMask other, ClosedWorld closedWorld) {
+      FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base != other.base);
     assert(closedWorld.isSubtypeOf(other.base, base));
     if (!isSubtype) return intersectionHelper(other, closedWorld);
@@ -450,14 +450,14 @@
     }
   }
 
-  TypeMask intersectionDisjoint(FlatTypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersectionDisjoint(FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base != other.base);
     assert(!closedWorld.isSubtypeOf(base, other.base));
     assert(!closedWorld.isSubtypeOf(other.base, base));
     return intersectionHelper(other, closedWorld);
   }
 
-  TypeMask intersectionHelper(FlatTypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersectionHelper(FlatTypeMask other, JClosedWorld closedWorld) {
     assert(base != other.base);
     assert(!closedWorld.isSubclassOf(base, other.base));
     assert(!closedWorld.isSubclassOf(other.base, base));
@@ -492,7 +492,7 @@
    * privacy is taken into account.
    */
   bool canHit(
-      MemberEntity element, Selector selector, ClosedWorld closedWorld) {
+      MemberEntity element, Selector selector, JClosedWorld closedWorld) {
     CommonElements commonElements = closedWorld.commonElements;
     assert(element.name == selector.name);
     if (isEmpty) return false;
@@ -528,7 +528,7 @@
   }
 
   bool needsNoSuchMethodHandling(
-      Selector selector, covariant ClosedWorld closedWorld) {
+      Selector selector, covariant JClosedWorld closedWorld) {
     // A call on an empty type mask is either dead code, or a call on
     // `null`.
     if (isEmptyOrNull) return false;
@@ -536,12 +536,12 @@
     // TODO(johnniwinther): A type mask cannot be abstract. Remove the need
     // for this noise (currently used for super-calls in inference and mirror
     // usage).
-    if (isExact && closedWorld.isAbstract(base)) return false;
+    if (isExact && base.isAbstract) return false;
 
     return closedWorld.needsNoSuchMethod(base, selector, _classQuery);
   }
 
-  MemberEntity locateSingleMember(Selector selector, ClosedWorld closedWorld) {
+  MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
     if (isEmptyOrNull) return null;
     if (closedWorld.includesClosureCall(selector, this)) return null;
     Iterable<MemberEntity> targets = closedWorld.locateMembers(selector, this);
diff --git a/pkg/compiler/lib/src/types/forwarding_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
similarity index 68%
rename from pkg/compiler/lib/src/types/forwarding_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
index 0bfed426..9841e46 100644
--- a/pkg/compiler/lib/src/types/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
@@ -26,31 +26,31 @@
   bool get isValue => false;
   bool get isForwarding => true;
 
-  bool isInMask(TypeMask other, ClosedWorld closedWorld) {
+  bool isInMask(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.isInMask(other, closedWorld);
   }
 
-  bool containsMask(TypeMask other, ClosedWorld closedWorld) {
+  bool containsMask(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.containsMask(other, closedWorld);
   }
 
-  bool containsOnlyInt(ClosedWorld closedWorld) {
+  bool containsOnlyInt(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyInt(closedWorld);
   }
 
-  bool containsOnlyDouble(ClosedWorld closedWorld) {
+  bool containsOnlyDouble(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyDouble(closedWorld);
   }
 
-  bool containsOnlyNum(ClosedWorld closedWorld) {
+  bool containsOnlyNum(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyNum(closedWorld);
   }
 
-  bool containsOnlyBool(ClosedWorld closedWorld) {
+  bool containsOnlyBool(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyBool(closedWorld);
   }
 
-  bool containsOnlyString(ClosedWorld closedWorld) {
+  bool containsOnlyString(JClosedWorld closedWorld) {
     return forwardTo.containsOnlyString(closedWorld);
   }
 
@@ -58,23 +58,23 @@
     return forwardTo.containsOnly(cls);
   }
 
-  bool satisfies(ClassEntity cls, ClosedWorld closedWorld) {
+  bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
     return forwardTo.satisfies(cls, closedWorld);
   }
 
-  bool contains(ClassEntity cls, ClosedWorld closedWorld) {
+  bool contains(ClassEntity cls, JClosedWorld closedWorld) {
     return forwardTo.contains(cls, closedWorld);
   }
 
-  bool containsAll(ClosedWorld closedWorld) {
+  bool containsAll(JClosedWorld closedWorld) {
     return forwardTo.containsAll(closedWorld);
   }
 
-  ClassEntity singleClass(ClosedWorld closedWorld) {
+  ClassEntity singleClass(JClosedWorld closedWorld) {
     return forwardTo.singleClass(closedWorld);
   }
 
-  TypeMask union(other, ClosedWorld closedWorld) {
+  TypeMask union(other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
@@ -85,25 +85,25 @@
     return forwardTo.union(other, closedWorld);
   }
 
-  bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
+  bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.isDisjoint(other, closedWorld);
   }
 
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     return forwardTo.intersection(other, closedWorld);
   }
 
   bool needsNoSuchMethodHandling(
-      Selector selector, covariant ClosedWorld closedWorld) {
+      Selector selector, covariant JClosedWorld closedWorld) {
     return forwardTo.needsNoSuchMethodHandling(selector, closedWorld);
   }
 
   bool canHit(
-      MemberEntity element, Selector selector, ClosedWorld closedWorld) {
+      MemberEntity element, Selector selector, JClosedWorld closedWorld) {
     return forwardTo.canHit(element, selector, closedWorld);
   }
 
-  MemberEntity locateSingleMember(Selector selector, ClosedWorld closedWorld) {
+  MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
     return forwardTo.locateSingleMember(selector, closedWorld);
   }
 
@@ -122,3 +122,11 @@
 
   int get hashCode => throw "Subclass should implement hashCode getter";
 }
+
+abstract class AllocationTypeMask<T> extends ForwardingTypeMask {
+  // The [Node] where this type mask was created.
+  T get allocationNode;
+
+  // The [Entity] where this type mask was created.
+  MemberEntity get allocationElement;
+}
diff --git a/pkg/compiler/lib/src/types/map_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
similarity index 95%
rename from pkg/compiler/lib/src/types/map_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
index b1ded1d..7feedff 100644
--- a/pkg/compiler/lib/src/types/map_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
@@ -9,7 +9,7 @@
  * site of a map (currently only internal Map class) that will get specialized
  * once the [TypeGraphInferrer] phase finds a key and/or value type for it.
  */
-class MapTypeMask<T> extends ForwardingTypeMask {
+class MapTypeMask<T> extends AllocationTypeMask<T> {
   final TypeMask forwardTo;
 
   // The [Node] where this type mask was created.
@@ -53,13 +53,13 @@
         valueType == other.valueType;
   }
 
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(dynamic other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, JClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
similarity index 60%
rename from pkg/compiler/lib/src/types/masks.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index 19455cc..2b6ae66 100644
--- a/pkg/compiler/lib/src/types/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -4,20 +4,18 @@
 
 library masks;
 
-import '../common.dart';
-import '../common_elements.dart' show CommonElements;
-import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
-import '../elements/entities.dart';
-import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
-import '../universe/selector.dart' show Selector;
-import '../universe/world_builder.dart'
-    show
-        ReceiverConstraint,
-        UniverseSelectorConstraints,
-        SelectorConstraintsStrategy;
-import '../util/util.dart';
-import '../world.dart' show ClassQuery, ClosedWorld;
-import 'abstract_value_domain.dart';
+import '../../common.dart';
+import '../../common_elements.dart' show CommonElements;
+import '../../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
+import '../../elements/entities.dart';
+import '../../types/abstract_value_domain.dart';
+import '../../universe/selector.dart' show Selector;
+import '../../universe/use.dart' show DynamicUse;
+import '../../universe/world_builder.dart'
+    show UniverseSelectorConstraints, SelectorConstraintsStrategy;
+import '../../util/util.dart';
+import '../../world.dart' show ClassQuery, JClosedWorld;
+import '../type_graph_inferrer.dart' show TypeGraphInferrer;
 import 'constants.dart';
 
 part 'container_type_mask.dart';
@@ -32,7 +30,7 @@
 class CommonMasks implements AbstractValueDomain {
   // TODO(sigmund): once we split out the backend common elements, depend
   // directly on those instead.
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   CommonMasks(this._closedWorld);
 
@@ -79,75 +77,98 @@
     return cachedMasks.putIfAbsent(base, createMask);
   }
 
+  @override
   TypeMask get dynamicType => _dynamicType ??= new TypeMask.subclass(
       _closedWorld.commonElements.objectClass, _closedWorld);
 
+  @override
   TypeMask get nonNullType => _nonNullType ??= new TypeMask.nonNullSubclass(
       _closedWorld.commonElements.objectClass, _closedWorld);
 
+  @override
   TypeMask get intType => _intType ??=
       new TypeMask.nonNullSubclass(commonElements.jsIntClass, _closedWorld);
 
+  @override
   TypeMask get uint32Type => _uint32Type ??=
       new TypeMask.nonNullSubclass(commonElements.jsUInt32Class, _closedWorld);
 
+  @override
   TypeMask get uint31Type => _uint31Type ??=
       new TypeMask.nonNullExact(commonElements.jsUInt31Class, _closedWorld);
 
+  @override
   TypeMask get positiveIntType =>
       _positiveIntType ??= new TypeMask.nonNullSubclass(
           commonElements.jsPositiveIntClass, _closedWorld);
 
+  @override
   TypeMask get doubleType => _doubleType ??=
       new TypeMask.nonNullExact(commonElements.jsDoubleClass, _closedWorld);
 
+  @override
   TypeMask get numType => _numType ??=
       new TypeMask.nonNullSubclass(commonElements.jsNumberClass, _closedWorld);
 
+  @override
   TypeMask get boolType => _boolType ??=
       new TypeMask.nonNullExact(commonElements.jsBoolClass, _closedWorld);
 
+  @override
   TypeMask get functionType => _functionType ??=
       new TypeMask.nonNullSubtype(commonElements.functionClass, _closedWorld);
 
+  @override
   TypeMask get listType => _listType ??=
       new TypeMask.nonNullExact(commonElements.jsArrayClass, _closedWorld);
 
+  @override
   TypeMask get constListType => _constListType ??= new TypeMask.nonNullExact(
       commonElements.jsUnmodifiableArrayClass, _closedWorld);
 
+  @override
   TypeMask get fixedListType => _fixedListType ??=
       new TypeMask.nonNullExact(commonElements.jsFixedArrayClass, _closedWorld);
 
+  @override
   TypeMask get growableListType =>
       _growableListType ??= new TypeMask.nonNullExact(
           commonElements.jsExtendableArrayClass, _closedWorld);
 
+  @override
   TypeMask get mapType => _mapType ??=
       new TypeMask.nonNullSubtype(commonElements.mapLiteralClass, _closedWorld);
 
+  @override
   TypeMask get constMapType => _constMapType ??= new TypeMask.nonNullSubtype(
       commonElements.constMapLiteralClass, _closedWorld);
 
+  @override
   TypeMask get stringType => _stringType ??=
       new TypeMask.nonNullExact(commonElements.jsStringClass, _closedWorld);
 
+  @override
   TypeMask get typeType => _typeType ??=
       new TypeMask.nonNullExact(commonElements.typeLiteralClass, _closedWorld);
 
+  @override
   TypeMask get syncStarIterableType => _syncStarIterableType ??=
       new TypeMask.nonNullExact(commonElements.syncStarIterable, _closedWorld);
 
+  @override
   TypeMask get asyncFutureType =>
       _asyncFutureType ??= new TypeMask.nonNullExact(
           commonElements.futureImplementation, _closedWorld);
 
+  @override
   TypeMask get asyncStarStreamType => _asyncStarStreamType ??=
       new TypeMask.nonNullExact(commonElements.controllerStream, _closedWorld);
 
   // TODO(johnniwinther): Assert that the null type has been resolved.
+  @override
   TypeMask get nullType => _nullType ??= const TypeMask.empty();
 
+  @override
   TypeMask get emptyType => const TypeMask.nonNullEmpty();
 
   TypeMask get indexablePrimitiveType =>
@@ -169,6 +190,7 @@
       _interceptorType ??= new TypeMask.nonNullSubclass(
           commonElements.jsInterceptorClass, _closedWorld);
 
+  @override
   bool isTypedArray(TypeMask mask) {
     // Just checking for `TypedData` is not sufficient, as it is an abstract
     // class any user-defined class can implement. So we also check for the
@@ -181,6 +203,7 @@
             _closedWorld);
   }
 
+  @override
   bool couldBeTypedArray(TypeMask mask) {
     bool intersects(TypeMask type1, TypeMask type2) =>
         !type1.intersection(type2, _closedWorld).isEmpty;
@@ -197,47 +220,108 @@
                 _closedWorld));
   }
 
+  @override
   TypeMask createNonNullExact(ClassEntity cls) {
     return new TypeMask.nonNullExact(cls, _closedWorld);
   }
 
+  @override
+  TypeMask createNullableExact(ClassEntity cls) {
+    return new TypeMask.exact(cls, _closedWorld);
+  }
+
+  @override
+  TypeMask createNonNullSubclass(ClassEntity cls) {
+    return new TypeMask.nonNullSubclass(cls, _closedWorld);
+  }
+
+  @override
   TypeMask createNonNullSubtype(ClassEntity cls) {
     return new TypeMask.nonNullSubtype(cls, _closedWorld);
   }
 
+  @override
   TypeMask createNullableSubtype(ClassEntity cls) {
     return new TypeMask.subtype(cls, _closedWorld);
   }
 
+  @override
   TypeMask excludeNull(TypeMask mask) => mask.nonNullable();
 
   @override
   TypeMask includeNull(TypeMask mask) => mask.nullable();
 
+  @override
   bool containsType(TypeMask typeMask, ClassEntity cls) {
     return _closedWorld.isInstantiated(cls) &&
         typeMask.contains(cls, _closedWorld);
   }
 
+  @override
   bool containsOnlyType(TypeMask typeMask, ClassEntity cls) {
     return _closedWorld.isInstantiated(cls) && typeMask.containsOnly(cls);
   }
 
-  bool isInstanceOf(TypeMask typeMask, ClassEntity cls) {
+  @override
+  bool isInstanceOfOrNull(TypeMask typeMask, ClassEntity cls) {
     return _closedWorld.isImplemented(cls) &&
         typeMask.satisfies(cls, _closedWorld);
   }
 
+  @override
+  AbstractBool isInstanceOf(
+      covariant TypeMask expressionMask, ClassEntity cls) {
+    AbstractValue typeMask = (cls == commonElements.nullClass)
+        ? createNullableSubtype(cls)
+        : createNonNullSubtype(cls);
+    if (expressionMask.union(typeMask, _closedWorld) == typeMask) {
+      return AbstractBool.True;
+    } else if (expressionMask.isDisjoint(typeMask, _closedWorld)) {
+      return AbstractBool.False;
+    } else {
+      return AbstractBool.Maybe;
+    }
+  }
+
+  @override
   bool isEmpty(TypeMask value) => value.isEmpty;
 
-  bool isExact(TypeMask value) => value.isExact || isNull(value);
+  @override
+  bool isExact(TypeMask value) => value.isExact && !value.isNullable;
 
-  bool isValue(TypeMask value) => value.isValue;
+  @override
+  bool isExactOrNull(TypeMask value) => value.isExact || isNull(value);
 
+  @override
+  ClassEntity getExactClass(TypeMask mask) {
+    return mask.singleClass(_closedWorld);
+  }
+
+  @override
+  bool isPrimitiveValue(TypeMask value) => value.isValue;
+
+  @override
+  PrimitiveConstantValue getPrimitiveValue(TypeMask mask) {
+    if (mask.isValue) {
+      ValueTypeMask valueMask = mask;
+      return valueMask.value;
+    }
+    return null;
+  }
+
+  @override
+  AbstractValue createPrimitiveValue(
+      covariant TypeMask originalValue, PrimitiveConstantValue value) {
+    return new ValueTypeMask(originalValue, value);
+  }
+
+  @override
   bool canBeNull(TypeMask value) => value.isNullable;
 
+  @override
   bool isNull(TypeMask value) => value.isNull;
 
+  @override
   bool canBePrimitive(TypeMask value) {
     return canBePrimitiveNumber(value) ||
         canBePrimitiveArray(value) ||
@@ -246,6 +330,7 @@
         isNull(value);
   }
 
+  @override
   bool canBePrimitiveNumber(TypeMask value) {
     // TODO(sra): It should be possible to test only jsDoubleClass and
     // jsUInt31Class, since all others are superclasses of these two.
@@ -257,10 +342,12 @@
         containsType(value, commonElements.jsDoubleClass);
   }
 
+  @override
   bool canBePrimitiveBoolean(TypeMask value) {
     return containsType(value, commonElements.jsBoolClass);
   }
 
+  @override
   bool canBePrimitiveArray(TypeMask value) {
     return containsType(value, commonElements.jsArrayClass) ||
         containsType(value, commonElements.jsFixedArrayClass) ||
@@ -268,102 +355,123 @@
         containsType(value, commonElements.jsUnmodifiableArrayClass);
   }
 
+  @override
   bool isIndexablePrimitive(TypeMask value) {
     return value.containsOnlyString(_closedWorld) ||
-        isInstanceOf(value, commonElements.jsIndexableClass);
+        isInstanceOfOrNull(value, commonElements.jsIndexableClass);
   }
 
+  @override
   bool isFixedArray(TypeMask value) {
     // TODO(sra): Recognize the union of these types as well.
     return containsOnlyType(value, commonElements.jsFixedArrayClass) ||
         containsOnlyType(value, commonElements.jsUnmodifiableArrayClass);
   }
 
+  @override
   bool isExtendableArray(TypeMask value) {
     return containsOnlyType(value, commonElements.jsExtendableArrayClass);
   }
 
+  @override
   bool isMutableArray(TypeMask value) {
-    return isInstanceOf(value, commonElements.jsMutableArrayClass);
+    return isInstanceOfOrNull(value, commonElements.jsMutableArrayClass);
   }
 
-  bool isReadableArray(TypeMask value) {
-    return isInstanceOf(value, commonElements.jsArrayClass);
-  }
-
+  @override
   bool isMutableIndexable(TypeMask value) {
-    return isInstanceOf(value, commonElements.jsMutableIndexableClass);
+    return isInstanceOfOrNull(value, commonElements.jsMutableIndexableClass);
   }
 
-  bool isArray(TypeMask value) => isReadableArray(value);
+  @override
+  bool isArray(TypeMask value) {
+    return isInstanceOfOrNull(value, commonElements.jsArrayClass);
+  }
 
+  @override
   bool canBePrimitiveString(TypeMask value) {
     return containsType(value, commonElements.jsStringClass);
   }
 
+  @override
   bool isInteger(TypeMask value) {
     return value.containsOnlyInt(_closedWorld) && !value.isNullable;
   }
 
+  @override
   bool isUInt32(TypeMask value) {
     return !value.isNullable &&
-        isInstanceOf(value, commonElements.jsUInt32Class);
+        isInstanceOfOrNull(value, commonElements.jsUInt32Class);
   }
 
+  @override
   bool isUInt31(TypeMask value) {
     return !value.isNullable &&
-        isInstanceOf(value, commonElements.jsUInt31Class);
+        isInstanceOfOrNull(value, commonElements.jsUInt31Class);
   }
 
+  @override
   bool isPositiveInteger(TypeMask value) {
     return !value.isNullable &&
-        isInstanceOf(value, commonElements.jsPositiveIntClass);
+        isInstanceOfOrNull(value, commonElements.jsPositiveIntClass);
   }
 
+  @override
   bool isPositiveIntegerOrNull(TypeMask value) {
-    return isInstanceOf(value, commonElements.jsPositiveIntClass);
+    return isInstanceOfOrNull(value, commonElements.jsPositiveIntClass);
   }
 
+  @override
   bool isIntegerOrNull(TypeMask value) {
     return value.containsOnlyInt(_closedWorld);
   }
 
+  @override
   bool isNumber(TypeMask value) {
     return value.containsOnlyNum(_closedWorld) && !value.isNullable;
   }
 
+  @override
   bool isNumberOrNull(TypeMask value) {
     return value.containsOnlyNum(_closedWorld);
   }
 
+  @override
   bool isDouble(TypeMask value) {
     return value.containsOnlyDouble(_closedWorld) && !value.isNullable;
   }
 
+  @override
   bool isDoubleOrNull(TypeMask value) {
     return value.containsOnlyDouble(_closedWorld);
   }
 
+  @override
   bool isBoolean(TypeMask value) {
     return value.containsOnlyBool(_closedWorld) && !value.isNullable;
   }
 
+  @override
   bool isBooleanOrNull(TypeMask value) {
     return value.containsOnlyBool(_closedWorld);
   }
 
+  @override
   bool isString(TypeMask value) {
     return value.containsOnlyString(_closedWorld) && !value.isNullable;
   }
 
+  @override
   bool isStringOrNull(TypeMask value) {
     return value.containsOnlyString(_closedWorld);
   }
 
+  @override
   bool isPrimitive(TypeMask value) {
     return (isPrimitiveOrNull(value) && !value.isNullable) || isNull(value);
   }
 
+  @override
   bool isPrimitiveOrNull(TypeMask value) {
     return isIndexablePrimitive(value) ||
         isNumberOrNull(value) ||
@@ -371,13 +479,17 @@
         isNull(value);
   }
 
+  @override
   TypeMask union(TypeMask a, TypeMask b) => a.union(b, _closedWorld);
 
+  @override
   TypeMask intersection(TypeMask a, TypeMask b) =>
       a.intersection(b, _closedWorld);
 
+  @override
   bool areDisjoint(TypeMask a, TypeMask b) => a.isDisjoint(b, _closedWorld);
 
+  @override
   bool containsAll(TypeMask a) => a.containsAll(_closedWorld);
 
   @override
@@ -386,8 +498,17 @@
   }
 
   @override
+  AbstractValue getMapKeyType(AbstractValue value) {
+    if (value is MapTypeMask) {
+      return value.keyType;
+    }
+    return dynamicType;
+  }
+
+  @override
   AbstractValue getMapValueType(AbstractValue value) {
     if (value is MapTypeMask) {
+      // TODO(johnniwinther): Assert the `value.valueType` is not null.
       return value.valueType ?? dynamicType;
     }
     return dynamicType;
@@ -402,7 +523,23 @@
   }
 
   @override
-  AbstractValue unionOfMany(List<AbstractValue> values) {
+  int getContainerLength(AbstractValue value) {
+    return value is ContainerTypeMask ? value.length : null;
+  }
+
+  @override
+  AbstractValue createContainerValue(
+      AbstractValue forwardTo,
+      Object allocationNode,
+      MemberEntity allocationElement,
+      AbstractValue elementType,
+      int length) {
+    return new ContainerTypeMask(
+        forwardTo, allocationNode, allocationElement, elementType, length);
+  }
+
+  @override
+  AbstractValue unionOfMany(Iterable<AbstractValue> values) {
     TypeMask result = const TypeMask.nonNullEmpty();
     for (TypeMask value in values) {
       result = result.union(value, _closedWorld);
@@ -449,8 +586,170 @@
   }
 
   @override
+  bool isIn(covariant TypeMask subset, covariant TypeMask superset) {
+    return subset.isInMask(superset, _closedWorld);
+  }
+
+  @override
   MemberEntity locateSingleMember(
       covariant TypeMask receiver, Selector selector) {
     return receiver.locateSingleMember(selector, _closedWorld);
   }
+
+  @override
+  bool isJsIndexable(TypeMask mask) {
+    return mask.satisfies(
+        _closedWorld.commonElements.jsIndexableClass, _closedWorld);
+  }
+
+  @override
+  bool isJsIndexableAndIterable(covariant TypeMask mask) {
+    return mask != null &&
+        mask.satisfies(
+            _closedWorld.commonElements.jsIndexableClass, _closedWorld) &&
+        // String is indexable but not iterable.
+        !mask.satisfies(
+            _closedWorld.commonElements.jsStringClass, _closedWorld);
+  }
+
+  @override
+  bool isFixedLengthJsIndexable(covariant TypeMask mask) {
+    if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
+      // A container on which we have inferred the length.
+      return true;
+    }
+    // TODO(sra): Recognize any combination of fixed length indexables.
+    if (mask.containsOnly(_closedWorld.commonElements.jsFixedArrayClass) ||
+        mask.containsOnly(
+            _closedWorld.commonElements.jsUnmodifiableArrayClass) ||
+        mask.containsOnlyString(_closedWorld) ||
+        _closedWorld.abstractValueDomain.isTypedArray(mask)) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  bool canBeInterceptor(TypeMask value) {
+    return !interceptorType.isDisjoint(value, _closedWorld);
+  }
+
+  @override
+  bool isMap(TypeMask value) {
+    return value.isMap;
+  }
+
+  @override
+  bool isContainer(TypeMask value) {
+    return value.isContainer;
+  }
+
+  @override
+  bool isDictionary(TypeMask value) {
+    return value.isDictionary;
+  }
+
+  @override
+  bool containsDictionaryKey(AbstractValue value, String key) {
+    return value is DictionaryTypeMask && value.containsKey(key);
+  }
+
+  @override
+  AbstractValue getDictionaryValueForKey(AbstractValue value, String key) {
+    if (value is DictionaryTypeMask) return value.getValueForKey(key);
+    return dynamicType;
+  }
+
+  @override
+  AbstractValue createMapValue(AbstractValue forwardTo, Object allocationNode,
+      MemberEntity allocationElement, AbstractValue key, AbstractValue value) {
+    return new MapTypeMask(
+        forwardTo, allocationNode, allocationElement, key, value);
+  }
+
+  @override
+  AbstractValue createDictionaryValue(
+      AbstractValue forwardTo,
+      Object allocationNode,
+      MemberEntity allocationElement,
+      AbstractValue key,
+      AbstractValue value,
+      Map<String, AbstractValue> mappings) {
+    return new DictionaryTypeMask(
+        forwardTo, allocationNode, allocationElement, key, value, mappings);
+  }
+
+  @override
+  bool isSpecializationOf(
+      AbstractValue specialization, AbstractValue generalization) {
+    return specialization is ForwardingTypeMask &&
+        specialization.forwardTo == generalization;
+  }
+
+  @override
+  Object getAllocationNode(AbstractValue value) {
+    if (value is AllocationTypeMask) {
+      return value.allocationNode;
+    }
+    return null;
+  }
+
+  @override
+  MemberEntity getAllocationElement(AbstractValue value) {
+    if (value is AllocationTypeMask) {
+      return value.allocationElement;
+    }
+    return null;
+  }
+
+  @override
+  AbstractValue getGeneralization(AbstractValue value) {
+    if (value is AllocationTypeMask) {
+      return value.forwardTo;
+    }
+    return null;
+  }
+
+  @override
+  String getCompactText(AbstractValue value) {
+    return formatType(value);
+  }
+}
+
+/// Convert the given TypeMask to a compact string format.
+///
+/// The default format is too verbose for the graph format since long strings
+/// create oblong nodes that obstruct the graph layout.
+String formatType(TypeMask type) {
+  if (type is FlatTypeMask) {
+    // TODO(asgerf): Disambiguate classes whose name is not unique. Using the
+    //     library name for all classes is not a good idea, since library names
+    //     can be really long and mess up the layout.
+    // Capitalize Null to emphasize that it's the null type mask and not
+    // a null value we accidentally printed out.
+    if (type.isEmptyOrNull) return type.isNullable ? 'Null' : 'Empty';
+    String nullFlag = type.isNullable ? '?' : '';
+    String subFlag = type.isExact ? '' : type.isSubclass ? '+' : '*';
+    return '${type.base.name}$nullFlag$subFlag';
+  }
+  if (type is UnionTypeMask) {
+    return type.disjointMasks.map(formatType).join(' | ');
+  }
+  if (type is ContainerTypeMask) {
+    String container = formatType(type.forwardTo);
+    String member = formatType(type.elementType);
+    return '$container<$member>';
+  }
+  if (type is MapTypeMask) {
+    String container = formatType(type.forwardTo);
+    String key = formatType(type.keyType);
+    String value = formatType(type.valueType);
+    return '$container<$key,$value>';
+  }
+  if (type is ValueTypeMask) {
+    String baseType = formatType(type.forwardTo);
+    String value = type.value.toStructuredText();
+    return '$baseType=$value';
+  }
+  return '$type'; // Fall back on toString if not supported here.
 }
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
similarity index 77%
rename from pkg/compiler/lib/src/types/type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
index d7c9c01..ee7d4b2 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
@@ -12,7 +12,7 @@
   Set<TypeMask> _masks;
 
   @override
-  bool applies(MemberEntity element, Selector selector, ClosedWorld world) {
+  bool applies(MemberEntity element, Selector selector, JClosedWorld world) {
     if (isAll) return true;
     if (_masks == null) return false;
     for (TypeMask mask in _masks) {
@@ -22,7 +22,7 @@
   }
 
   @override
-  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld world) {
+  bool needsNoSuchMethodHandling(Selector selector, JClosedWorld world) {
     if (isAll) {
       TypeMask mask =
           new TypeMask.subclass(world.commonElements.objectClass, world);
@@ -59,13 +59,36 @@
   }
 }
 
-class TypeMaskStrategy implements SelectorConstraintsStrategy {
+class TypeMaskStrategy implements AbstractValueStrategy {
   const TypeMaskStrategy();
 
   @override
+  AbstractValueDomain createDomain(JClosedWorld closedWorld) {
+    return new CommonMasks(closedWorld);
+  }
+
+  @override
+  SelectorConstraintsStrategy createSelectorStrategy() {
+    return new TypeMaskSelectorStrategy();
+  }
+}
+
+class TypeMaskSelectorStrategy implements SelectorConstraintsStrategy {
+  const TypeMaskSelectorStrategy();
+
+  @override
   UniverseSelectorConstraints createSelectorConstraints(Selector selector) {
     return new IncreasingTypeMaskSet();
   }
+
+  @override
+  bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member,
+      covariant JClosedWorld world) {
+    Selector selector = dynamicUse.selector;
+    TypeMask mask = dynamicUse.receiverConstraint;
+    return selector.appliesUnnamed(member) &&
+        (mask == null || mask.canHit(member, selector, world));
+  }
 }
 
 /**
@@ -73,16 +96,16 @@
  * operations on it are not guaranteed to be precise and they may
  * yield conservative answers that contain too many classes.
  */
-abstract class TypeMask implements ReceiverConstraint, AbstractValue {
+abstract class TypeMask implements AbstractValue {
   factory TypeMask(
-      ClassEntity base, int kind, bool isNullable, ClosedWorld closedWorld) {
+      ClassEntity base, int kind, bool isNullable, JClosedWorld closedWorld) {
     return new FlatTypeMask.normalized(
         base, (kind << 1) | (isNullable ? 1 : 0), closedWorld);
   }
 
   const factory TypeMask.empty() = FlatTypeMask.empty;
 
-  factory TypeMask.exact(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.exact(ClassEntity base, JClosedWorld closedWorld) {
     assert(
         closedWorld.isInstantiated(base),
         failedAt(
@@ -92,12 +115,12 @@
     return new FlatTypeMask.exact(base);
   }
 
-  factory TypeMask.exactOrEmpty(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.exactOrEmpty(ClassEntity base, JClosedWorld closedWorld) {
     if (closedWorld.isInstantiated(base)) return new FlatTypeMask.exact(base);
     return const TypeMask.empty();
   }
 
-  factory TypeMask.subclass(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.subclass(ClassEntity base, JClosedWorld closedWorld) {
     assert(
         closedWorld.isInstantiated(base),
         failedAt(
@@ -114,7 +137,7 @@
     }
   }
 
-  factory TypeMask.subtype(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.subtype(ClassEntity base, JClosedWorld closedWorld) {
     ClassEntity topmost = closedWorld.getLubOfInstantiatedSubtypes(base);
     if (topmost == null) {
       return new TypeMask.empty();
@@ -131,7 +154,7 @@
 
   const factory TypeMask.nonNullEmpty() = FlatTypeMask.nonNullEmpty;
 
-  factory TypeMask.nonNullExact(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.nonNullExact(ClassEntity base, JClosedWorld closedWorld) {
     assert(
         closedWorld.isInstantiated(base),
         failedAt(
@@ -142,14 +165,14 @@
   }
 
   factory TypeMask.nonNullExactOrEmpty(
-      ClassEntity base, ClosedWorld closedWorld) {
+      ClassEntity base, JClosedWorld closedWorld) {
     if (closedWorld.isInstantiated(base)) {
       return new FlatTypeMask.nonNullExact(base);
     }
     return const TypeMask.nonNullEmpty();
   }
 
-  factory TypeMask.nonNullSubclass(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.nonNullSubclass(ClassEntity base, JClosedWorld closedWorld) {
     assert(
         closedWorld.isInstantiated(base),
         failedAt(
@@ -166,7 +189,7 @@
     }
   }
 
-  factory TypeMask.nonNullSubtype(ClassEntity base, ClosedWorld closedWorld) {
+  factory TypeMask.nonNullSubtype(ClassEntity base, JClosedWorld closedWorld) {
     ClassEntity topmost = closedWorld.getLubOfInstantiatedSubtypes(base);
     if (topmost == null) {
       return new TypeMask.nonNullEmpty();
@@ -181,7 +204,7 @@
     }
   }
 
-  factory TypeMask.unionOf(Iterable<TypeMask> masks, ClosedWorld closedWorld) {
+  factory TypeMask.unionOf(Iterable<TypeMask> masks, JClosedWorld closedWorld) {
     return UnionTypeMask.unionOf(masks, closedWorld);
   }
 
@@ -203,14 +226,15 @@
    * subclasses exist. We also normalize exact to empty if the corresponding
    * baseclass was never instantiated.
    */
-  static bool assertIsNormalized(TypeMask mask, ClosedWorld closedWorld) {
+  static bool assertIsNormalized(TypeMask mask, JClosedWorld closedWorld) {
     String reason = getNotNormalizedReason(mask, closedWorld);
     assert(reason == null,
         failedAt(NO_LOCATION_SPANNABLE, '$mask is not normalized: $reason'));
     return true;
   }
 
-  static String getNotNormalizedReason(TypeMask mask, ClosedWorld closedWorld) {
+  static String getNotNormalizedReason(
+      TypeMask mask, JClosedWorld closedWorld) {
     mask = nonForwardingMask(mask);
     if (mask is FlatTypeMask) {
       if (mask.isEmptyOrNull) return null;
@@ -293,11 +317,11 @@
   /// Returns `true` if this mask holds encodes an exact value within a type.
   bool get isValue;
 
-  bool containsOnlyInt(ClosedWorld closedWorld);
-  bool containsOnlyDouble(ClosedWorld closedWorld);
-  bool containsOnlyNum(ClosedWorld closedWorld);
-  bool containsOnlyBool(ClosedWorld closedWorld);
-  bool containsOnlyString(ClosedWorld closedWorld);
+  bool containsOnlyInt(JClosedWorld closedWorld);
+  bool containsOnlyDouble(JClosedWorld closedWorld);
+  bool containsOnlyNum(JClosedWorld closedWorld);
+  bool containsOnlyBool(JClosedWorld closedWorld);
+  bool containsOnlyString(JClosedWorld closedWorld);
   bool containsOnly(ClassEntity cls);
 
   /**
@@ -314,7 +338,7 @@
    * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
    * false negatives.
    */
-  bool isInMask(TypeMask other, ClosedWorld closedWorld);
+  bool isInMask(TypeMask other, JClosedWorld closedWorld);
 
   /**
    * If this returns `true`, [other] is guaranteed to be a subtype of this mask,
@@ -322,48 +346,53 @@
    * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
    * false negatives.
    */
-  bool containsMask(TypeMask other, ClosedWorld closedWorld);
+  bool containsMask(TypeMask other, JClosedWorld closedWorld);
 
   /**
    * Returns whether this type mask is an instance of [cls].
    */
-  bool satisfies(ClassEntity cls, ClosedWorld closedWorld);
+  bool satisfies(ClassEntity cls, JClosedWorld closedWorld);
 
   /**
    * Returns whether or not this type mask contains the given class [cls].
    */
-  bool contains(ClassEntity cls, ClosedWorld closedWorld);
+  bool contains(ClassEntity cls, JClosedWorld closedWorld);
 
   /// Returns whether or not this type mask contains all types.
-  bool containsAll(ClosedWorld closedWorld);
+  bool containsAll(JClosedWorld closedWorld);
 
   /// Returns the [ClassEntity] if this type represents a single class,
   /// otherwise returns `null`.  This method is conservative.
-  ClassEntity singleClass(ClosedWorld closedWorld);
+  ClassEntity singleClass(JClosedWorld closedWorld);
 
   /**
    * Returns a type mask representing the union of [this] and [other].
    */
-  TypeMask union(TypeMask other, ClosedWorld closedWorld);
+  TypeMask union(TypeMask other, JClosedWorld closedWorld);
 
   /// Returns whether the intersection of this and [other] is empty.
-  bool isDisjoint(TypeMask other, ClosedWorld closedWorld);
+  bool isDisjoint(TypeMask other, JClosedWorld closedWorld);
 
   /**
    * Returns a type mask representing the intersection of [this] and [other].
    */
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld);
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld);
 
   /**
    * Returns whether [element] is a potential target when being
    * invoked on this type mask. [selector] is used to ensure library
    * privacy is taken into account.
    */
-  bool canHit(MemberEntity element, Selector selector, ClosedWorld closedWorld);
+  bool canHit(
+      MemberEntity element, Selector selector, JClosedWorld closedWorld);
+
+  /// Returns whether this [TypeMask] applied to [selector] can hit a
+  /// [noSuchMethod].
+  bool needsNoSuchMethodHandling(Selector selector, JClosedWorld world);
 
   /**
    * Returns the [element] that is known to always be hit at runtime
    * on this mask. Returns null if there is none.
    */
-  MemberEntity locateSingleMember(Selector selector, ClosedWorld closedWorld);
+  MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld);
 }
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
similarity index 90%
rename from pkg/compiler/lib/src/types/union_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
index 178f878..6121c08 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
@@ -19,7 +19,7 @@
     assert(disjointMasks.every((TypeMask mask) => !mask.isUnion));
   }
 
-  static TypeMask unionOf(Iterable<TypeMask> masks, ClosedWorld closedWorld) {
+  static TypeMask unionOf(Iterable<TypeMask> masks, JClosedWorld closedWorld) {
     assert(
         masks.every((mask) => TypeMask.assertIsNormalized(mask, closedWorld)));
     List<FlatTypeMask> disjoint = <FlatTypeMask>[];
@@ -35,7 +35,7 @@
   }
 
   static void unionOfHelper(Iterable<TypeMask> masks,
-      List<FlatTypeMask> disjoint, ClosedWorld closedWorld) {
+      List<FlatTypeMask> disjoint, JClosedWorld closedWorld) {
     // TODO(johnniwinther): Impose an order on the mask to ensure subclass masks
     // are preferred to subtype masks.
     for (TypeMask mask in masks) {
@@ -87,7 +87,7 @@
     }
   }
 
-  static TypeMask flatten(List<FlatTypeMask> masks, ClosedWorld closedWorld) {
+  static TypeMask flatten(List<FlatTypeMask> masks, JClosedWorld closedWorld) {
     // TODO(johnniwinther): Move this computation to [ClosedWorld] and use the
     // class set structures.
     assert(masks.length > 1);
@@ -137,7 +137,7 @@
     return new TypeMask(bestElement, bestKind, isNullable, closedWorld);
   }
 
-  TypeMask union(dynamic other, ClosedWorld closedWorld) {
+  TypeMask union(dynamic other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return this;
 
@@ -151,7 +151,7 @@
     return new TypeMask.unionOf(newList, closedWorld);
   }
 
-  TypeMask intersection(dynamic other, ClosedWorld closedWorld) {
+  TypeMask intersection(dynamic other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return other;
     if (other.isUnion && this == other) return this;
@@ -173,7 +173,7 @@
     return new TypeMask.unionOf(intersections, closedWorld);
   }
 
-  bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
+  bool isDisjoint(TypeMask other, JClosedWorld closedWorld) {
     for (var current in disjointMasks) {
       if (!current.isDisjoint(other, closedWorld)) return false;
     }
@@ -216,7 +216,7 @@
    * - the cheap test matching against individual members of [disjointMasks]
    *   must have failed.
    */
-  bool slowContainsCheck(TypeMask other, ClosedWorld closedWorld) {
+  bool slowContainsCheck(TypeMask other, JClosedWorld closedWorld) {
     // Unions should never make it here.
     assert(!other.isUnion);
     // Ensure the cheap test fails.
@@ -245,7 +245,7 @@
     return members.every((ClassEntity cls) => this.contains(cls, closedWorld));
   }
 
-  bool isInMask(TypeMask other, ClosedWorld closedWorld) {
+  bool isInMask(TypeMask other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (isNullable && !other.isNullable) return false;
     if (other.isUnion) {
@@ -273,7 +273,7 @@
     return disjointMasks.every((mask) => mask.isInMask(other, closedWorld));
   }
 
-  bool containsMask(TypeMask other, ClosedWorld closedWorld) {
+  bool containsMask(TypeMask other, JClosedWorld closedWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (other.isNullable && !isNullable) return false;
     if (other.isUnion) return other.isInMask(this, closedWorld);
@@ -288,25 +288,25 @@
     return contained;
   }
 
-  bool containsOnlyInt(ClosedWorld closedWorld) {
+  bool containsOnlyInt(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyInt(closedWorld));
   }
 
-  bool containsOnlyDouble(ClosedWorld closedWorld) {
+  bool containsOnlyDouble(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyDouble(closedWorld));
   }
 
-  bool containsOnlyNum(ClosedWorld closedWorld) {
+  bool containsOnlyNum(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) {
       return mask.containsOnlyNum(closedWorld);
     });
   }
 
-  bool containsOnlyBool(ClosedWorld closedWorld) {
+  bool containsOnlyBool(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyBool(closedWorld));
   }
 
-  bool containsOnlyString(ClosedWorld closedWorld) {
+  bool containsOnlyString(JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.containsOnlyString(closedWorld));
   }
 
@@ -314,31 +314,31 @@
     return disjointMasks.every((mask) => mask.containsOnly(element));
   }
 
-  bool satisfies(ClassEntity cls, ClosedWorld closedWorld) {
+  bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
     return disjointMasks.every((mask) => mask.satisfies(cls, closedWorld));
   }
 
-  bool contains(ClassEntity cls, ClosedWorld closedWorld) {
+  bool contains(ClassEntity cls, JClosedWorld closedWorld) {
     return disjointMasks.any((e) => e.contains(cls, closedWorld));
   }
 
-  bool containsAll(ClosedWorld closedWorld) {
+  bool containsAll(JClosedWorld closedWorld) {
     return disjointMasks.any((mask) => mask.containsAll(closedWorld));
   }
 
-  ClassEntity singleClass(ClosedWorld closedWorld) => null;
+  ClassEntity singleClass(JClosedWorld closedWorld) => null;
 
-  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
+  bool needsNoSuchMethodHandling(Selector selector, JClosedWorld closedWorld) {
     return disjointMasks
         .any((e) => e.needsNoSuchMethodHandling(selector, closedWorld));
   }
 
   bool canHit(
-      MemberEntity element, Selector selector, ClosedWorld closedWorld) {
+      MemberEntity element, Selector selector, JClosedWorld closedWorld) {
     return disjointMasks.any((e) => e.canHit(element, selector, closedWorld));
   }
 
-  MemberEntity locateSingleMember(Selector selector, ClosedWorld closedWorld) {
+  MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld) {
     MemberEntity candidate;
     for (FlatTypeMask mask in disjointMasks) {
       MemberEntity current = mask.locateSingleMember(selector, closedWorld);
diff --git a/pkg/compiler/lib/src/types/value_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
similarity index 94%
rename from pkg/compiler/lib/src/types/value_type_mask.dart
rename to pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
index 8d4cc44..ebeda52 100644
--- a/pkg/compiler/lib/src/types/value_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/value_type_mask.dart
@@ -27,7 +27,7 @@
     return super.equalsDisregardNull(other) && value == other.value;
   }
 
-  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
     TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index 9a819e8..9893f5b 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -115,8 +115,7 @@
     }
   }
 
-  // TODO(28763): Remove `<dynamic>` when issue 28763 is fixed.
-  void countTokens(Node node) => node.accept<dynamic>(this);
+  void countTokens(Node node) => node.accept(this);
 }
 
 abstract class ReferenceCountedAstNode implements Node {
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 7a33482..b31697c 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -522,7 +522,8 @@
     List<js.Node> visited = nodes.take(lastTransformIndex).map((js.Node node) {
       return (node == null) ? null : _storeIfNecessary(visitExpression(node));
     }).toList();
-    visited.addAll(nodes.skip(lastTransformIndex).map((js.Node node) {
+    visited.addAll(
+        nodes.skip(lastTransformIndex).map<js.Expression>((js.Node node) {
       return (node == null) ? null : visitExpression(node);
     }));
     var result = fn(visited);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index f1c234f..c06c5f0 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -37,7 +37,6 @@
 import '../native/native.dart' as native;
 import '../ssa/ssa.dart' show SsaFunctionCompiler;
 import '../tracer.dart';
-import '../types/masks.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/class_hierarchy_builder.dart'
     show ClassHierarchyBuilder, ClassQueries;
@@ -47,7 +46,7 @@
 import '../universe/world_impact.dart'
     show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
 import '../util/util.dart';
-import '../world.dart' show ClosedWorld, ClosedWorldRefiner;
+import '../world.dart' show JClosedWorld;
 import 'annotations.dart' as optimizerHints;
 import 'backend_impact.dart';
 import 'backend_usage.dart';
@@ -71,7 +70,7 @@
   void onCodegenStart();
 
   /// Generates JavaScript code for `work.element`.
-  jsAst.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld);
+  jsAst.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld);
 
   Iterable get tasks;
 }
@@ -495,7 +494,7 @@
   }
 
   Namer determineNamer(
-      ClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder) {
+      JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder) {
     return compiler.options.enableMinification
         ? compiler.options.useFrequencyNamer
             ? new FrequencyBasedNamer(closedWorld, codegenWorldBuilder)
@@ -547,9 +546,8 @@
   }
 
   /// Called when the closed world from resolution has been computed.
-  void onResolutionClosedWorld(
-      ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) {
-    processAnnotations(closedWorldRefiner);
+  void onResolutionClosedWorld(JClosedWorld closedWorld) {
+    processAnnotations(closedWorld);
   }
 
   void onDeferredLoadComplete(OutputUnitData data) {
@@ -637,7 +635,7 @@
 
   /// Creates an [Enqueuer] for code generation specific to this backend.
   CodegenEnqueuer createCodegenEnqueuer(
-      CompilerTask task, Compiler compiler, ClosedWorld closedWorld) {
+      CompilerTask task, Compiler compiler, JClosedWorld closedWorld) {
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     CommonElements commonElements = closedWorld.commonElements;
     BackendImpacts impacts =
@@ -660,7 +658,9 @@
         compiler.options,
         const TreeShakingEnqueuerStrategy(),
         compiler.backendStrategy.createCodegenWorldBuilder(
-            closedWorld.nativeData, closedWorld, const TypeMaskStrategy()),
+            closedWorld.nativeData,
+            closedWorld,
+            compiler.abstractValueStrategy.createSelectorStrategy()),
         compiler.backendStrategy.createCodegenWorkItemBuilder(closedWorld),
         new CodegenEnqueuerListener(
             elementEnvironment,
@@ -675,7 +675,7 @@
   static bool cacheCodegenImpactForTesting = false;
   Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
 
-  WorldImpact codegen(CodegenWorkItem work, ClosedWorld closedWorld) {
+  WorldImpact codegen(CodegenWorkItem work, JClosedWorld closedWorld) {
     MemberEntity element = work.element;
     if (compiler.elementHasCompileTimeError(element)) {
       DiagnosticMessage message =
@@ -730,7 +730,7 @@
   }
 
   /// Generates the output and returns the total size of the generated code.
-  int assembleProgram(ClosedWorld closedWorld) {
+  int assembleProgram(JClosedWorld closedWorld) {
     int programSize = emitter.assembleProgram(namer, closedWorld);
     closedWorld.noSuchMethodData.emitDiagnostic(reporter);
     return programSize;
@@ -785,7 +785,7 @@
 
   /// Called when the compiler starts running the codegen enqueuer. The
   /// [WorldImpact] of enabled backend features is returned.
-  WorldImpact onCodegenStart(ClosedWorld closedWorld,
+  WorldImpact onCodegenStart(JClosedWorld closedWorld,
       CodegenWorldBuilder codegenWorldBuilder, Sorter sorter) {
     functionCompiler.onCodegenStart();
     _oneShotInterceptorData = new OneShotInterceptorData(
@@ -842,23 +842,20 @@
   /// Process backend specific annotations.
   // TODO(johnniwinther): Merge this with [AnnotationProcessor] and use
   // [ElementEnvironment.getMemberMetadata] in [AnnotationProcessor].
-  void processAnnotations(ClosedWorldRefiner closedWorldRefiner) {
-    ClosedWorld closedWorld = closedWorldRefiner.closedWorld;
+  void processAnnotations(JClosedWorld closedWorld) {
     // These methods are overwritten with generated versions.
     inlineCache.markAsNonInlinable(
         closedWorld.commonElements.getInterceptorMethod,
         insideLoop: true);
     for (MemberEntity entity in closedWorld.processedMembers) {
-      _processMemberAnnotations(closedWorld.elementEnvironment,
-          closedWorld.commonElements, entity, closedWorldRefiner);
+      _processMemberAnnotations(closedWorld, entity);
     }
   }
 
   void _processMemberAnnotations(
-      ElementEnvironment elementEnvironment,
-      CommonElements commonElements,
-      MemberEntity element,
-      ClosedWorldRefiner closedWorldRefiner) {
+      JClosedWorld closedWorld, MemberEntity element) {
+    ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
+    CommonElements commonElements = closedWorld.commonElements;
     bool hasNoInline = false;
     bool hasForceInline = false;
 
@@ -930,14 +927,14 @@
           reporter.reportHintMessage(
               method, MessageKind.GENERIC, {'text': "Cannot throw"});
         }
-        closedWorldRefiner.registerCannotThrow(method);
+        closedWorld.registerCannotThrow(method);
       } else if (cls == commonElements.noSideEffectsClass) {
         hasNoSideEffects = true;
         if (VERBOSE_OPTIMIZER_HINTS) {
           reporter.reportHintMessage(
               method, MessageKind.GENERIC, {'text': "Has no side effects"});
         }
-        closedWorldRefiner.registerSideEffectsFree(method);
+        closedWorld.registerSideEffectsFree(method);
       }
     }
     if (hasForceInline && hasNoInline) {
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index cb869ee..8b0d237 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -405,9 +405,7 @@
     ConstantValue argument = createString(text);
     // TODO(johnniwinther): Use type arguments when all uses no longer expect
     // a [FieldElement].
-    Map<dynamic, ConstantValue> fields = <dynamic, ConstantValue>{
-      field: argument
-    };
+    var fields = <FieldEntity, ConstantValue>{field: argument};
     return new ConstructedConstantValue(type, fields);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index cbb30a5..f7e8984 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -116,7 +116,7 @@
   }
 
   factory _FieldNamingScope.forClass(
-      ClassEntity cls, ClosedWorld world, _FieldNamingRegistry registry) {
+      ClassEntity cls, JClosedWorld world, _FieldNamingRegistry registry) {
     _FieldNamingScope result = registry.scopes[cls];
     if (result != null) return result;
 
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 9ce989c..343d440 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -30,7 +30,7 @@
       _staticsPropertyName ??= getFreshName(instanceScope, 'static');
 
   FrequencyBasedNamer(
-      ClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
+      JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
       : super(closedWorld, codegenWorldBuilder) {
     fieldRegistry = new _FieldNamingRegistry(this);
   }
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index 079aa91..3ef09f3 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -9,9 +9,9 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
-import '../types/masks.dart' show TypeMask;
+import '../types/abstract_value_domain.dart';
 import '../universe/selector.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'namer.dart';
 import 'native_data.dart';
 
@@ -25,7 +25,7 @@
   bool isInterceptedName(String name);
   bool isInterceptedSelector(Selector selector);
   bool isInterceptedMixinSelector(
-      Selector selector, TypeMask mask, ClosedWorld closedWorld);
+      Selector selector, AbstractValue mask, JClosedWorld closedWorld);
   Iterable<ClassEntity> get interceptedClasses;
   bool isMixedIntoInterceptedClass(ClassEntity element);
 
@@ -33,12 +33,12 @@
   ///
   /// Returns an empty set if there is no class. Do not modify the returned set.
   Set<ClassEntity> getInterceptedClassesOn(
-      String name, ClosedWorld closedWorld);
+      String name, JClosedWorld closedWorld);
 
   /// Whether the compiler can use the native `instanceof` check to test for
   /// instances of [type]. This is true for types that are not used as mixins or
   /// interfaces.
-  bool mayGenerateInstanceofCheck(DartType type, ClosedWorld closedWorld);
+  bool mayGenerateInstanceofCheck(DartType type, JClosedWorld closedWorld);
 }
 
 abstract class InterceptorDataBuilder {
@@ -117,7 +117,7 @@
   /// into an intercepted class.  These selectors are not eligible for the
   /// 'dummy explicit receiver' optimization.
   bool isInterceptedMixinSelector(
-      Selector selector, TypeMask mask, ClosedWorld closedWorld) {
+      Selector selector, AbstractValue mask, JClosedWorld closedWorld) {
     Set<MemberEntity> elements =
         _interceptedMixinElements.putIfAbsent(selector.name, () {
       Set<MemberEntity> elements = interceptedMembers[selector.name];
@@ -132,7 +132,8 @@
     if (elements.isEmpty) return false;
     return elements.any((element) {
       return selector.applies(element) &&
-          (mask == null || mask.canHit(element, selector, closedWorld));
+          (mask == null ||
+              closedWorld.abstractValueDomain.canHit(mask, element, selector));
     });
   }
 
@@ -152,7 +153,7 @@
   ///
   /// Returns an empty set if there is no class. Do not modify the returned set.
   Set<ClassEntity> getInterceptedClassesOn(
-      String name, ClosedWorld closedWorld) {
+      String name, JClosedWorld closedWorld) {
     Set<MemberEntity> intercepted = interceptedMembers[name];
     if (intercepted == null) return _noClasses;
     return _interceptedClassesCache.putIfAbsent(name, () {
@@ -177,7 +178,7 @@
   }
 
   Set<ClassEntity> nativeSubclassesOfMixin(
-      ClassEntity mixin, ClosedWorld closedWorld) {
+      ClassEntity mixin, JClosedWorld closedWorld) {
     Iterable<ClassEntity> uses = closedWorld.mixinUsesOf(mixin);
     Set<ClassEntity> result = null;
     for (ClassEntity use in uses) {
@@ -202,7 +203,7 @@
   bool isMixedIntoInterceptedClass(ClassEntity element) =>
       classesMixedIntoInterceptedClasses.contains(element);
 
-  bool mayGenerateInstanceofCheck(DartType type, ClosedWorld closedWorld) {
+  bool mayGenerateInstanceofCheck(DartType type, JClosedWorld closedWorld) {
     // We can use an instanceof check for raw types that have no subclass that
     // is mixed-in or in an implements clause.
 
@@ -311,7 +312,7 @@
       _specializedGetInterceptors[name];
 
   jsAst.Name registerOneShotInterceptor(
-      Selector selector, Namer namer, ClosedWorld closedWorld) {
+      Selector selector, Namer namer, JClosedWorld closedWorld) {
     Set<ClassEntity> classes =
         _interceptorData.getInterceptedClassesOn(selector.name, closedWorld);
     jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes);
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 723bca7..49078b9 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -12,7 +12,7 @@
         _MinifiedFieldNamer,
         _MinifyConstructorBodyNamer,
         _MinifiedOneShotInterceptorNamer {
-  MinifyNamer(ClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
+  MinifyNamer(JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
       : super(closedWorld, codegenWorldBuilder) {
     reserveBackendNames();
     fieldRegistry = new _FieldNamingRegistry(this);
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 1f202ed..0b4d5db 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -27,7 +27,7 @@
 import '../universe/selector.dart' show Selector, SelectorKind;
 import '../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../util/util.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'backend.dart';
 import 'constant_system_javascript.dart';
 import 'native_data.dart';
@@ -492,7 +492,7 @@
   static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
   static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]');
 
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final CodegenWorldBuilder _codegenWorldBuilder;
 
   RuntimeTypesEncoder _rtiEncoder;
@@ -1646,6 +1646,10 @@
 
   String get futureOrTypeTag => r'type';
 
+  // The name of the variable used to offset function signatures in deferred
+  // parts with the fast-startup emitter.
+  String get typesOffsetName => r'typesOffset';
+
   Map<FunctionType, jsAst.Name> functionTypeNameMap =
       new HashMap<FunctionType, jsAst.Name>();
 
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 1281eb9..d637cb1 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -15,7 +15,7 @@
 import '../options.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld, KClosedWorld;
 import 'backend_usage.dart';
 import 'namer.dart';
 import 'native_data.dart';
@@ -134,7 +134,7 @@
   /// Computes the [RuntimeTypesNeed] for the data registered with this builder.
   RuntimeTypesNeed computeRuntimeTypesNeed(
       ResolutionWorldBuilder resolutionWorldBuilder,
-      ClosedWorld closedWorld,
+      KClosedWorld closedWorld,
       CompilerOptions options);
 }
 
@@ -153,7 +153,7 @@
   @override
   RuntimeTypesNeed computeRuntimeTypesNeed(
       ResolutionWorldBuilder resolutionWorldBuilder,
-      ClosedWorld closedWorld,
+      KClosedWorld closedWorld,
       CompilerOptions options) {
     return const TrivialRuntimeTypesNeed();
   }
@@ -202,7 +202,7 @@
 }
 
 class TrivialRuntimeTypesChecksBuilder implements RuntimeTypesChecksBuilder {
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final TrivialRuntimeTypesSubstitutions _substitutions;
   bool rtiChecksBuilderClosed = false;
 
@@ -267,7 +267,7 @@
 
 abstract class RuntimeTypesSubstitutionsMixin
     implements RuntimeTypesSubstitutions {
-  ClosedWorld get _closedWorld;
+  JClosedWorld get _closedWorld;
   TypeChecks get _requiredChecks;
 
   ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
@@ -585,7 +585,7 @@
 }
 
 class TrivialRuntimeTypesSubstitutions extends RuntimeTypesSubstitutionsMixin {
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   TypeChecks _requiredChecks;
 
   TrivialRuntimeTypesSubstitutions(this._closedWorld);
@@ -789,7 +789,7 @@
   ///     }
   ///     main() => new B<int>().m(0);
   ///
-  Iterable<ClassEntity> get classTests =>
+  Iterable<ClassEntity> get classTestsForTesting =>
       _classes.values.where((n) => n.hasTest).map((n) => n.cls).toSet();
 
   /// Classes that explicitly use their type variables in is-tests.
@@ -801,7 +801,7 @@
   ///     }
   ///     main() => new A<int>().m(0);
   ///
-  Iterable<ClassEntity> get directClassTests =>
+  Iterable<ClassEntity> get directClassTestsForTesting =>
       _classes.values.where((n) => n.hasDirectTest).map((n) => n.cls).toSet();
 
   /// Methods that explicitly or implicitly use their type variables in
@@ -813,7 +813,7 @@
   ///     m2<S>(o) => m1<S>(o);
   ///     main() => m2<int>(0);
   ///
-  Iterable<Entity> get methodTests =>
+  Iterable<Entity> get methodTestsForTesting =>
       _methods.values.where((n) => n.hasTest).map((n) => n.function).toSet();
 
   /// Methods that explicitly use their type variables in is-tests.
@@ -823,7 +823,7 @@
   ///     m<T>(o) => o is T;
   ///     main() => m<int>(0);
   ///
-  Iterable<Entity> get directMethodTests => _methods.values
+  Iterable<Entity> get directMethodTestsForTesting => _methods.values
       .where((n) => n.hasDirectTest)
       .map((n) => n.function)
       .toSet();
@@ -1022,20 +1022,25 @@
 
   void _propagateTests(CommonElements commonElements,
       ElementEnvironment elementEnvironment, WorldBuilder worldBuilder) {
+    void processTypeVariableType(TypeVariableType type, {bool direct: true}) {
+      TypeVariableEntity variable = type.element;
+      if (variable.typeDeclaration is ClassEntity) {
+        _getClassNode(variable.typeDeclaration).markTest(direct: direct);
+      } else {
+        _getMethodNode(
+                elementEnvironment, worldBuilder, variable.typeDeclaration)
+            .markTest(direct: direct);
+      }
+    }
+
     void processType(DartType type, {bool direct: true}) {
-      if (type.isTypeVariable) {
-        TypeVariableType typeVariableType = type;
-        TypeVariableEntity variable = typeVariableType.element;
-        if (variable.typeDeclaration is ClassEntity) {
-          _getClassNode(variable.typeDeclaration).markTest(direct: direct);
-        } else {
-          _getMethodNode(
-                  elementEnvironment, worldBuilder, variable.typeDeclaration)
-              .markTest(direct: direct);
-        }
-      } else if (type is FutureOrType) {
+      if (type is FutureOrType) {
         _getClassNode(commonElements.futureClass).markIndirectTest();
         processType(type.typeArgument, direct: false);
+      } else {
+        type.forEachTypeVariable((TypeVariableType type) {
+          processTypeVariableType(type, direct: direct);
+        });
       }
     }
 
@@ -1357,7 +1362,7 @@
   @override
   RuntimeTypesNeed computeRuntimeTypesNeed(
       ResolutionWorldBuilder resolutionWorldBuilder,
-      ClosedWorld closedWorld,
+      KClosedWorld closedWorld,
       CompilerOptions options) {
     TypeVariableTests typeVariableTests = new TypeVariableTests(
         closedWorld.elementEnvironment,
@@ -1645,7 +1650,7 @@
 class RuntimeTypesImpl extends _RuntimeTypesBase
     with RuntimeTypesSubstitutionsMixin
     implements RuntimeTypesChecksBuilder {
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   // The set of type arguments tested against type variable bounds.
   final Set<DartType> checkedTypeArguments = new Set<DartType>();
@@ -2146,12 +2151,21 @@
 
   jsAst.Expression visitInterfaceType(InterfaceType type, Emitter emitter) {
     jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
-    if (_nativeData.isJsInteropClass(type.element)) {
-      return getJsInteropTypeArguments(type.typeArguments.length, name: name);
+    jsAst.Expression result;
+    if (type.treatAsRaw) {
+      result = name;
+    } else {
+      // Visit all type arguments. This is done even for jsinterop classes to
+      // enforce the invariant that [onVariable] is called for each type
+      // variable in the type.
+      result = visitList(type.typeArguments, emitter, head: name);
+      if (_nativeData.isJsInteropClass(type.element)) {
+        // Replace type arguments of generic jsinterop classes with 'any' type.
+        result =
+            getJsInteropTypeArguments(type.typeArguments.length, name: name);
+      }
     }
-    return type.treatAsRaw
-        ? name
-        : visitList(type.typeArguments, emitter, head: name);
+    return result;
   }
 
   jsAst.Expression visitList(List<DartType> types, Emitter emitter,
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 3240b46..93f1a0a 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -15,7 +15,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/world_builder.dart'
     show CodegenWorldBuilder, SelectorConstraints;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart';
 import 'model.dart';
@@ -23,7 +23,7 @@
 class ClassStubGenerator {
   final Namer _namer;
   final CodegenWorldBuilder _worldBuilder;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final bool enableMinification;
   final Emitter _emitter;
   final CommonElements _commonElements;
@@ -43,7 +43,7 @@
     //        [ constructorName, fields,
     //            fields.map(
     //                (name) => js('this.# = #', [name, name]))]));
-    var typeParameters = const <jsAst.Parameter>[];
+    dynamic typeParameters = const <jsAst.Parameter>[];
     dynamic typeInits = const <jsAst.Expression>[];
     if (hasRtiField) {
       dynamic rtiName = _namer.rtiFieldJsName;
@@ -211,7 +211,8 @@
           js.quoteName(enableMinification ? internalName : methodName),
       'internalName': js.quoteName(internalName),
       'type': js.number(type),
-      'arguments': new jsAst.ArrayInitializer(parameterNames.map(js).toList()),
+      'arguments': new jsAst.ArrayInitializer(
+          parameterNames.map<jsAst.Expression>(js).toList()),
       'namedArguments': new jsAst.ArrayInitializer(argNames),
       'typeArgumentCount': js.number(selector.typeArgumentCount)
     });
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 00bfaf7..b8d5263 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -15,7 +15,7 @@
 import '../js/js.dart' as jsAst;
 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
 import '../universe/world_builder.dart' show CodegenWorldBuilder;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'full_emitter/emitter.dart' as full_js_emitter;
 import 'program_builder/program_builder.dart';
 import 'startup_emitter/emitter.dart' as startup_js_emitter;
@@ -155,7 +155,7 @@
   }
 
   /// Creates the [Emitter] for this task.
-  void createEmitter(Namer namer, ClosedWorld closedWorld,
+  void createEmitter(Namer namer, JClosedWorld closedWorld,
       CodegenWorldBuilder codegenWorldBuilder, Sorter sorter) {
     measure(() {
       _nativeEmitter = new NativeEmitter(this, closedWorld, codegenWorldBuilder,
@@ -169,7 +169,7 @@
     });
   }
 
-  int assembleProgram(Namer namer, ClosedWorld closedWorld) {
+  int assembleProgram(Namer namer, JClosedWorld closedWorld) {
     return measure(() {
       _finalizeRti();
       ProgramBuilder programBuilder = new ProgramBuilder(
@@ -216,7 +216,7 @@
 
   /// Create the [Emitter] for the emitter [task] that uses the given [namer].
   Emitter createEmitter(CodeEmitterTask task, Namer namer,
-      ClosedWorld closedWorld, Sorter sorter);
+      JClosedWorld closedWorld, Sorter sorter);
 }
 
 abstract class Emitter {
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index 3a54cf6..a888d94 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -12,13 +12,13 @@
 import '../../js/js.dart' as jsAst;
 import '../../js/js.dart' show js;
 import '../../js_backend/js_backend.dart' show CompoundName, Namer;
-import '../../world.dart' show ClosedWorld;
+import '../../world.dart' show JClosedWorld;
 import '../js_emitter.dart' hide Emitter, EmitterFactory;
 import '../model.dart';
 import 'emitter.dart';
 
 class ClassEmitter extends CodeEmitterHelper {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
 
   ClassEmitter(this.closedWorld);
 
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index bdc35cd..34a538d 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -29,7 +29,7 @@
 import '../../universe/call_structure.dart' show CallStructure;
 import '../../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../../util/uri_extras.dart' show relativize;
-import '../../world.dart' show ClosedWorld;
+import '../../world.dart' show JClosedWorld;
 import '../constant_ordering.dart' show ConstantOrdering;
 import '../headers.dart';
 import '../js_emitter.dart' hide Emitter, EmitterFactory;
@@ -65,7 +65,7 @@
 
   @override
   Emitter createEmitter(CodeEmitterTask task, Namer namer,
-      ClosedWorld closedWorld, Sorter sorter) {
+      JClosedWorld closedWorld, Sorter sorter) {
     return new Emitter(
         task.compiler, namer, closedWorld, generateSourceMap, task, sorter);
   }
@@ -74,7 +74,7 @@
 class Emitter extends js_emitter.EmitterBase {
   final Compiler compiler;
   final CodeEmitterTask task;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   // The following fields will be set to copies of the program-builder's
   // collector.
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
index dab39d9..dc2f3c3 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
@@ -8,13 +8,13 @@
 import '../../elements/entities.dart';
 import '../../js/js.dart' as jsAst;
 import '../../js/js.dart' show js;
-import '../../world.dart' show ClosedWorld;
+import '../../world.dart' show JClosedWorld;
 import '../js_emitter.dart' hide Emitter, EmitterFactory;
 import '../model.dart';
 import 'emitter.dart';
 
 class InterceptorEmitter extends CodeEmitterHelper {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final Set<jsAst.Name> interceptorInvocationNames = new Set<jsAst.Name>();
 
   InterceptorEmitter(this.closedWorld);
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index 48af9c9..5e15f2a 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -11,13 +11,13 @@
 import '../../universe/selector.dart' show Selector;
 import 'package:front_end/src/fasta/scanner/characters.dart'
     show $$, $A, $HASH, $Z, $a, $z;
-import '../../world.dart' show ClosedWorld;
+import '../../world.dart' show JClosedWorld;
 import '../js_emitter.dart' hide Emitter, EmitterFactory;
 import '../model.dart';
 import 'emitter.dart';
 
 class NsmEmitter extends CodeEmitterHelper {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final List<Selector> trivialNsmHandlers = <Selector>[];
 
   NsmEmitter(this.closedWorld);
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index f5a6d47..b5492b7 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -32,7 +32,7 @@
     JavaScriptBackend backend,
     Namer namer,
     Emitter emitter,
-    ClosedWorld closedWorld) {
+    JClosedWorld closedWorld) {
   jsAst.Expression typeInformationAccess =
       emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION);
   jsAst.Expression staticsAccess =
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index 477ced0..2804e12 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -15,7 +15,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/world_builder.dart'
     show CodegenWorldBuilder, SelectorConstraints;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'model.dart';
 
@@ -27,7 +27,7 @@
   final CommonElements _commonElements;
   final Namer _namer;
   final CodegenWorldBuilder _codegenWorldBuilder;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   // ignore: UNUSED_FIELD
   final SourceInformationStrategy _sourceInformationStrategy;
 
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index eae6858..f5d7ab1 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -21,7 +21,7 @@
 import '../options.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/world_builder.dart' show CodegenWorldBuilder;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
 
@@ -34,7 +34,7 @@
   final OneShotInterceptorData _oneShotInterceptorData;
   final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;
   final CodegenWorldBuilder _codegenWorldBuilder;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   InterceptorStubGenerator(
       this._options,
@@ -451,7 +451,7 @@
         //     {"": A.A$, "foo": A.A$foo, "bar": A.A$bar}
         //
         // We expect most of the time the map will be a singleton.
-        var properties = [];
+        var properties = <jsAst.Property>[];
         for (ConstructorEntity member in analysis.constructors(classElement)) {
           properties.add(new jsAst.Property(
               js.string(member.name), _emitter.staticFunctionAccess(member)));
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index b0e6d88..cdf72cb 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -65,6 +65,8 @@
   }
 
   int compareTo(covariant _MetadataEntry other) => other._rc - this._rc;
+
+  String toString() => '_BoundMetadataEntry($hashCode,rc=$_rc,_value=$_value)';
 }
 
 class _MetadataList extends jsAst.DeferredExpression {
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 12110ab..b931c3b 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -14,14 +14,14 @@
 import '../js_backend/native_data.dart';
 import '../native/enqueue.dart' show NativeCodegenEnqueuer;
 import '../universe/world_builder.dart' show CodegenWorldBuilder;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart' show CodeEmitterTask;
 import 'model.dart';
 
 class NativeEmitter {
   final CodeEmitterTask _emitterTask;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final CodegenWorldBuilder _worldBuilder;
   final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
 
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 187729f..4b173c6 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -18,7 +18,7 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/world_builder.dart'
     show CodegenWorldBuilder, SelectorConstraints;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'model.dart';
 
@@ -33,7 +33,7 @@
   final NativeData _nativeData;
   final InterceptorData _interceptorData;
   final CodegenWorldBuilder _codegenWorldBuilder;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final SourceInformationStrategy _sourceInformationStrategy;
 
   ParameterStubGenerator(
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 615835e..4b4b1c4 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -23,7 +23,7 @@
   final NativeData _nativeData;
   final InterceptorData _interceptorData;
   final OneShotInterceptorData _oneShotInterceptorData;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final Set<ClassEntity> _rtiNeededClasses;
   final Map<MemberEntity, js.Expression> _generatedCode;
   final Sorter _sorter;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 7415a08..440fecd 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -32,7 +32,7 @@
   final CodegenWorldBuilder _codegenWorldBuilder;
   final NativeData _nativeData;
   final Namer _namer;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   FieldVisitor(
       this._options,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 905c3bd..22ca61f 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -36,7 +36,7 @@
 import '../../universe/selector.dart' show Selector;
 import '../../universe/world_builder.dart'
     show CodegenWorldBuilder, SelectorConstraints;
-import '../../world.dart' show ClosedWorld;
+import '../../world.dart' show JClosedWorld;
 import '../js_emitter.dart'
     show
         ClassStubGenerator,
@@ -82,7 +82,7 @@
   final Map<MemberEntity, js.Expression> _generatedCode;
   final Namer _namer;
   final CodeEmitterTask _task;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final SourceInformationStrategy _sourceInformationStrategy;
 
   /// The [Sorter] used for ordering elements in the generated JavaScript.
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index e76a39d..fbc15f5 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -149,6 +149,7 @@
       // potentially a subtype of a checked function. Currently we eagerly
       // generate a function type index or signature for all callable classes.
       jsAst.Expression functionTypeIndex;
+      bool isDeferred = false;
       if (!type.containsTypeVariables) {
         // TODO(sigmund): use output unit of [method] when the classes mentioned
         // in [type] aren't in the main output unit. (Issue #31032)
@@ -156,6 +157,12 @@
         if (_outputUnitVisitor.isTypeContainedIn(type, mainOutputUnit)) {
           functionTypeIndex =
               emitterTask.metadataCollector.reifyType(type, mainOutputUnit);
+        } else if (!storeFunctionTypeInMetadata) {
+          // TODO(johnniwinther): Support sharing deferred signatures with the
+          // full emitter.
+          isDeferred = true;
+          functionTypeIndex = emitterTask.metadataCollector
+              .reifyType(type, _outputUnitData.outputUnitForMember(method));
         }
       }
       if (storeFunctionTypeInMetadata && functionTypeIndex != null) {
@@ -168,7 +175,18 @@
             // The signature function isn't live.
             return;
           }
-          encoding = functionTypeIndex ?? encoding;
+          if (functionTypeIndex != null) {
+            if (isDeferred) {
+              // The function type index must be offset by the number of types
+              // already loaded.
+              encoding = new jsAst.Binary(
+                  '+',
+                  new jsAst.VariableUse(_namer.typesOffsetName),
+                  functionTypeIndex);
+            } else {
+              encoding = functionTypeIndex;
+            }
+          }
         } else if (encoding == null) {
           // Generate the signature on the fly. This is only supported for
           // Dart 1.
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 29fb797..0e3e5a4 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -14,7 +14,7 @@
 import '../../elements/entities.dart';
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
-import '../../world.dart' show ClosedWorld;
+import '../../world.dart' show JClosedWorld;
 import '../js_emitter.dart' show CodeEmitterTask, NativeEmitter;
 import '../js_emitter.dart' as emitterTask show EmitterBase, EmitterFactory;
 import '../model.dart';
@@ -32,7 +32,7 @@
 
   @override
   Emitter createEmitter(CodeEmitterTask task, Namer namer,
-      ClosedWorld closedWorld, Sorter sorter) {
+      JClosedWorld closedWorld, Sorter sorter) {
     return new Emitter(task.compiler, namer, task.nativeEmitter, closedWorld,
         sorter, task, generateSourceMap);
   }
@@ -40,7 +40,7 @@
 
 class Emitter extends emitterTask.EmitterBase {
   final Compiler _compiler;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final Namer namer;
   final ModelEmitter _emitter;
 
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 6996a89..72ea813 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -264,11 +264,12 @@
 // Updates the types embedded global.
 function updateTypes(newTypes) {
   var types = #embeddedTypes;
-  // This relies on the fact that types are added *after* the tear-offs have
-  // been installed. The tear-off function uses the types-length to figure
-  // out at which offset its types are located. If the types were added earlier
-  // the offset would be wrong.
+  var length = types.length;
+  // The tear-off function uses another 'typesOffset' value cached in
+  // [initializeDeferredHunk] so [updateTypes] can be called either before of
+  // after the tearoffs have been installed.
   types.push.apply(types, newTypes);
+  return length;
 }
 
 // Updates the given holder with the properties of the [newHolder].
@@ -401,7 +402,9 @@
 /// However, at specific moments they need to contribute their data.
 /// For example, once the holders have been created, they are included into
 /// the main holders.
-const String deferredBoilerplate = '''
+///
+/// This template is used for Dart 1.
+const String deferredBoilerplateDart1 = '''
 function(inherit, mixin, lazy, makeConstList, convertToFastObject,
          installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes,
          setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
@@ -443,6 +446,59 @@
 }''';
 
 /// Soft-deferred fragments are built similarly to the main fragment.
+
+/// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
+///
+/// However, at specific moments they need to contribute their data.
+/// For example, once the holders have been created, they are included into
+/// the main holders.
+///
+/// This template is used for Dart 2.
+const String deferredBoilerplateDart2 = '''
+function(inherit, mixin, lazy, makeConstList, convertToFastObject,
+         installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes,
+         setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
+         #embeddedGlobalsObject, holdersList, #staticState) {
+
+// Builds the holders. They only contain the data for new holders.
+#holders;
+
+// If the name is not set on the functions, do it now.
+setFunctionNamesIfNecessary(#deferredHoldersList);
+
+// Updates the holders of the main-fragment. Uses the provided holdersList to
+// access the main holders.
+// The local holders are replaced by the combined holders. This is necessary
+// for the inheritance setup below.
+#updateHolders;
+// Sets the prototypes of the new classes.
+#prototypes;
+// Add signature function types and compute the types offset in `init.types`.
+// These can only refer to regular classes and in Dart 2 only closures have
+// function types so the `typesOffset` has been safely computed before it's
+// referred in the signatures of the `closures` below.
+var #typesOffset = updateTypes(#types);
+#closures;
+// Sets aliases of methods (on the prototypes of classes).
+#aliases;
+// Installs the tear-offs of functions.
+#tearOffs;
+// Builds the inheritance structure.
+#inheritance;
+
+// Instantiates all constants of this deferred fragment.
+// Note that the constant-holder has been updated earlier and storing the
+// constant values in the constant-holder makes them available globally.
+#constants;
+// Initializes the static non-final fields (with their constant values).
+#staticNonFinalFields;
+// Creates lazy getters for statics that must run initializers on first access.
+#lazyStatics;
+
+// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
+#nativeSupport;
+}''';
+
 ///
 /// However, they don't contribute anything to global namespace, but just
 /// initialize existing classes. For example, they update the inheritance
@@ -478,7 +534,7 @@
   final JavaScriptBackend backend;
   final ConstantEmitter constantEmitter;
   final ModelEmitter modelEmitter;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   FragmentEmitter(this.compiler, this.namer, this.backend, this.constantEmitter,
       this.modelEmitter, this._closedWorld);
@@ -589,27 +645,51 @@
           '#holder = updateHolder(holdersList[#index], #holder)',
           {'index': js.number(i), 'holder': new js.VariableUse(holder.name)}));
     }
-
-    // TODO(floitsch): don't just reference 'init'.
-    return js.js(deferredBoilerplate, {
-      'embeddedGlobalsObject': new js.Parameter('init'),
-      'staticState': new js.Parameter(namer.staticStateHolder),
-      'holders': emitHolders(holders, fragment),
-      'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders
-          .map((holder) => js.js("#", holder.name))
-          .toList(growable: false)),
-      'updateHolders': new js.Block(updateHolderAssignments),
-      'prototypes': emitPrototypes(fragment),
-      'inheritance': emitInheritance(fragment),
-      'aliases': emitInstanceMethodAliases(fragment),
-      'tearOffs': emitInstallTearOffs(fragment),
-      'constants': emitConstants(fragment),
-      'staticNonFinalFields': emitStaticNonFinalFields(fragment),
-      'lazyStatics': emitLazilyInitializedStatics(fragment),
-      'types': deferredTypes,
-      // TODO(floitsch): only call emitNativeSupport if we need native.
-      'nativeSupport': emitNativeSupport(fragment),
-    });
+    if (compiler.options.strongMode) {
+      // TODO(floitsch): don't just reference 'init'.
+      return js.js(deferredBoilerplateDart2, {
+        'embeddedGlobalsObject': new js.Parameter('init'),
+        'staticState': new js.Parameter(namer.staticStateHolder),
+        'holders': emitHolders(holders, fragment),
+        'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders
+            .map((holder) => js.js("#", holder.name))
+            .toList(growable: false)),
+        'updateHolders': new js.Block(updateHolderAssignments),
+        'prototypes': emitPrototypes(fragment, includeClosures: false),
+        'closures': emitPrototypes(fragment, includeClosures: true),
+        'inheritance': emitInheritance(fragment),
+        'aliases': emitInstanceMethodAliases(fragment),
+        'tearOffs': emitInstallTearOffs(fragment),
+        'constants': emitConstants(fragment),
+        'staticNonFinalFields': emitStaticNonFinalFields(fragment),
+        'lazyStatics': emitLazilyInitializedStatics(fragment),
+        'types': deferredTypes,
+        // TODO(floitsch): only call emitNativeSupport if we need native.
+        'nativeSupport': emitNativeSupport(fragment),
+        'typesOffset': namer.typesOffsetName,
+      });
+    } else {
+      // TODO(floitsch): don't just reference 'init'.
+      return js.js(deferredBoilerplateDart1, {
+        'embeddedGlobalsObject': new js.Parameter('init'),
+        'staticState': new js.Parameter(namer.staticStateHolder),
+        'holders': emitHolders(holders, fragment),
+        'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders
+            .map((holder) => js.js("#", holder.name))
+            .toList(growable: false)),
+        'updateHolders': new js.Block(updateHolderAssignments),
+        'prototypes': emitPrototypes(fragment),
+        'inheritance': emitInheritance(fragment),
+        'aliases': emitInstanceMethodAliases(fragment),
+        'tearOffs': emitInstallTearOffs(fragment),
+        'constants': emitConstants(fragment),
+        'staticNonFinalFields': emitStaticNonFinalFields(fragment),
+        'lazyStatics': emitLazilyInitializedStatics(fragment),
+        'types': deferredTypes,
+        // TODO(floitsch): only call emitNativeSupport if we need native.
+        'nativeSupport': emitNativeSupport(fragment),
+      });
+    }
   }
 
   /// Emits all holders, except for the static-state holder.
@@ -766,11 +846,25 @@
   ///
   /// This section updates the prototype-property of all constructors in the
   /// global holders.
-  js.Statement emitPrototypes(Fragment fragment, {softDeferred = false}) {
+  ///
+  /// [softDeferred] determine whether prototypes for soft deferred classes are
+  /// generated.
+  ///
+  /// If [includeClosures] is `true` only prototypes for closure classes are
+  /// generated, if [includeClosures] is `false` only prototypes for non-closure
+  /// classes are generated. Otherwise prototypes for all classes are generated.
+  js.Statement emitPrototypes(Fragment fragment,
+      {bool softDeferred = false, bool includeClosures}) {
     List<js.Statement> assignments = fragment.libraries
         .expand((Library library) => library.classes)
-        .where((Class cls) => cls.isSoftDeferred == softDeferred)
-        .map((Class cls) {
+        .where((Class cls) {
+      if (includeClosures != null) {
+        if (cls.element.isClosure != includeClosures) {
+          return false;
+        }
+      }
+      return cls.isSoftDeferred == softDeferred;
+    }).map((Class cls) {
       var proto = js.js.statement(
           '#.prototype = #;', [classReference(cls), emitPrototype(cls)]);
       ClassEntity element = cls.element;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 9c3beac..f57321e 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -57,7 +57,7 @@
   ConstantEmitter constantEmitter;
   final NativeEmitter nativeEmitter;
   final bool shouldGenerateSourceMap;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final ConstantOrdering _constantOrdering;
 
   // The full code that is written to each hunk part-file.
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 9334b52..b1c32aa 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -17,7 +17,6 @@
 import '../options.dart';
 import '../ssa/type_builder.dart';
 import '../universe/selector.dart';
-import '../world.dart';
 import 'elements.dart';
 import 'closure_visitors.dart';
 import 'locals.dart';
@@ -99,16 +98,6 @@
       Measurer measurer, this._elementMap, this._globalLocalsMap, this._options)
       : super(measurer);
 
-  /// The combined steps of generating our intermediate representation of
-  /// closures that need to be rewritten and generating the element model.
-  /// Ultimately these two steps will be split apart with the second step
-  /// happening later in compilation just before codegen. These steps are
-  /// combined here currently to provide a consistent interface to the rest of
-  /// the compiler until we are ready to separate these phases.
-  @override
-  void convertClosures(Iterable<MemberEntity> processedEntities,
-      ClosedWorldRefiner closedWorldRefiner) {}
-
   void _updateScopeBasedOnRtiNeed(KernelScopeInfo scope, ClosureRtiNeed rtiNeed,
       MemberEntity outermostEntity) {
     bool includeForRti(Set<VariableUse> useSet) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index f624144..fac95b8 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -39,6 +39,7 @@
 import '../native/behavior.dart';
 import '../options.dart';
 import '../ssa/ssa.dart';
+import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/class_set.dart';
 import '../universe/selector.dart';
@@ -68,7 +69,7 @@
   GlobalLocalsMap get globalLocalsMapForTesting => _globalLocalsMap;
 
   @override
-  ClosedWorldRefiner createClosedWorldRefiner(ClosedWorld closedWorld) {
+  JClosedWorld createJClosedWorld(KClosedWorld closedWorld) {
     KernelFrontEndStrategy strategy = _compiler.frontendStrategy;
     _elementMap = new JsKernelToElementMap(
         _compiler.reporter,
@@ -80,7 +81,10 @@
     _closureDataLookup = new KernelClosureConversionTask(
         _compiler.measurer, _elementMap, _globalLocalsMap, _compiler.options);
     JsClosedWorldBuilder closedWorldBuilder = new JsClosedWorldBuilder(
-        _elementMap, _closureDataLookup, _compiler.options);
+        _elementMap,
+        _closureDataLookup,
+        _compiler.options,
+        _compiler.abstractValueStrategy);
     return closedWorldBuilder._convertClosedWorld(
         closedWorld, strategy.closureModels);
   }
@@ -187,14 +191,14 @@
   }
 
   @override
-  WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld) {
+  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld) {
     return new KernelCodegenWorkItemBuilder(_compiler.backend, closedWorld);
   }
 
   @override
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
-      ClosedWorld closedWorld,
+      JClosedWorld closedWorld,
       SelectorConstraintsStrategy selectorConstraintsStrategy) {
     return new KernelCodegenWorldBuilder(
         elementMap,
@@ -211,10 +215,10 @@
   }
 
   @override
-  TypesInferrer createTypesInferrer(ClosedWorldRefiner closedWorldRefiner,
+  TypesInferrer createTypesInferrer(JClosedWorld closedWorld,
       {bool disableTypeInference: false}) {
     return new KernelTypeGraphInferrer(_compiler, _elementMap, _globalLocalsMap,
-        _closureDataLookup, closedWorldRefiner.closedWorld, closedWorldRefiner,
+        _closureDataLookup, closedWorld,
         disableTypeInference: disableTypeInference);
   }
 }
@@ -226,15 +230,16 @@
   final Map<ClassEntity, ClassSet> _classSets = <ClassEntity, ClassSet>{};
   final KernelClosureConversionTask _closureConversionTask;
   final CompilerOptions _options;
+  final AbstractValueStrategy _abstractValueStrategy;
 
-  JsClosedWorldBuilder(
-      this._elementMap, this._closureConversionTask, this._options);
+  JsClosedWorldBuilder(this._elementMap, this._closureConversionTask,
+      this._options, this._abstractValueStrategy);
 
   ElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
   CommonElements get _commonElements => _elementMap.commonElements;
 
-  JsClosedWorld _convertClosedWorld(ClosedWorldBase closedWorld,
-      Map<MemberEntity, ScopeModel> closureModels) {
+  JsClosedWorld _convertClosedWorld(
+      KClosedWorld closedWorld, Map<MemberEntity, ScopeModel> closureModels) {
     JsToFrontendMap map = new JsToFrontendMapImpl(_elementMap);
 
     BackendUsage backendUsage =
@@ -390,7 +395,8 @@
         assignedInstanceMembers: assignedInstanceMembers,
         processedMembers: processedMembers,
         mixinUses: mixinUses,
-        typesImplementedBySubclasses: typesImplementedBySubclasses);
+        typesImplementedBySubclasses: typesImplementedBySubclasses,
+        abstractValueStrategy: _abstractValueStrategy);
   }
 
   BackendUsage _convertBackendUsage(
@@ -600,6 +606,7 @@
 class JsClosedWorld extends ClosedWorldBase with KernelClosedWorldMixin {
   final JsKernelToElementMap elementMap;
   final RuntimeTypesNeed rtiNeed;
+  AbstractValueDomain _abstractValueDomain;
 
   JsClosedWorld(this.elementMap,
       {ElementEnvironment elementEnvironment,
@@ -619,7 +626,8 @@
       Map<ClassEntity, Set<ClassEntity>> mixinUses,
       Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
       Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
-      Map<ClassEntity, ClassSet> classSets})
+      Map<ClassEntity, ClassSet> classSets,
+      AbstractValueStrategy abstractValueStrategy})
       : super(
             elementEnvironment,
             dartTypes,
@@ -637,7 +645,15 @@
             mixinUses,
             typesImplementedBySubclasses,
             classHierarchyNodes,
-            classSets);
+            classSets,
+            abstractValueStrategy) {
+    _abstractValueDomain = abstractValueStrategy.createDomain(this);
+  }
+
+  @override
+  AbstractValueDomain get abstractValueDomain {
+    return _abstractValueDomain;
+  }
 
   @override
   void registerClosureClass(ClassEntity cls) {
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 13adcc4..a293039 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -20,7 +20,7 @@
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../native/native.dart' as native;
 import '../ssa/type_builder.dart';
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
 import '../world.dart';
@@ -369,59 +369,56 @@
 /// Interface for type inference results for kernel IR nodes.
 abstract class KernelToTypeInferenceMap {
   /// Returns the inferred return type of [function].
-  TypeMask getReturnTypeOf(FunctionEntity function);
+  AbstractValue getReturnTypeOf(FunctionEntity function);
 
   /// Returns the inferred receiver type of the dynamic [invocation].
-  TypeMask receiverTypeOfInvocation(
-      ir.MethodInvocation invocation, ClosedWorld closedWorld);
+  AbstractValue receiverTypeOfInvocation(
+      ir.MethodInvocation invocation, AbstractValueDomain abstractValueDomain);
 
   /// Returns the inferred receiver type of the dynamic [read].
-  TypeMask receiverTypeOfGet(ir.PropertyGet read);
+  AbstractValue receiverTypeOfGet(ir.PropertyGet read);
 
   /// Returns the inferred receiver type of the direct [read].
-  TypeMask receiverTypeOfDirectGet(ir.DirectPropertyGet read);
+  AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet read);
 
   /// Returns the inferred receiver type of the dynamic [write].
-  TypeMask receiverTypeOfSet(ir.PropertySet write, ClosedWorld closedWorld);
+  AbstractValue receiverTypeOfSet(
+      ir.PropertySet write, AbstractValueDomain abstractValueDomain);
 
   /// Returns the inferred type of [listLiteral].
-  TypeMask typeOfListLiteral(covariant MemberEntity owner,
-      ir.ListLiteral listLiteral, ClosedWorld closedWorld);
+  AbstractValue typeOfListLiteral(MemberEntity owner,
+      ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain);
 
   /// Returns the inferred type of iterator in [forInStatement].
-  TypeMask typeOfIterator(ir.ForInStatement forInStatement);
+  AbstractValue typeOfIterator(ir.ForInStatement forInStatement);
 
   /// Returns the inferred type of `current` in [forInStatement].
-  TypeMask typeOfIteratorCurrent(ir.ForInStatement forInStatement);
+  AbstractValue typeOfIteratorCurrent(ir.ForInStatement forInStatement);
 
   /// Returns the inferred type of `moveNext` in [forInStatement].
-  TypeMask typeOfIteratorMoveNext(ir.ForInStatement forInStatement);
+  AbstractValue typeOfIteratorMoveNext(ir.ForInStatement forInStatement);
 
   /// Returns `true` if [forInStatement] is inferred to be a JavaScript
   /// indexable iterator.
-  bool isJsIndexableIterator(
-      ir.ForInStatement forInStatement, ClosedWorld closedWorld);
-
-  /// Returns `true` if [mask] is inferred to have a JavaScript `length`
-  /// property.
-  bool isFixedLength(TypeMask mask, ClosedWorld closedWorld);
+  bool isJsIndexableIterator(ir.ForInStatement forInStatement,
+      AbstractValueDomain abstractValueDomain);
 
   /// Returns the inferred index type of [forInStatement].
-  TypeMask inferredIndexType(ir.ForInStatement forInStatement);
+  AbstractValue inferredIndexType(ir.ForInStatement forInStatement);
 
   /// Returns the inferred type of [member].
-  TypeMask getInferredTypeOf(MemberEntity member);
+  AbstractValue getInferredTypeOf(MemberEntity member);
 
   /// Returns the inferred type of the [parameter].
-  TypeMask getInferredTypeOfParameter(Local parameter);
+  AbstractValue getInferredTypeOfParameter(Local parameter);
 
-  /// Returns the inferred type of a dynamic [selector] access on a receiver of
-  /// type [mask].
-  TypeMask selectorTypeOf(Selector selector, TypeMask mask);
+  /// Returns the inferred type of a dynamic [selector] access on the
+  /// [receiver].
+  AbstractValue selectorTypeOf(Selector selector, AbstractValue receiver);
 
   /// Returns the returned type annotation in the [nativeBehavior].
-  TypeMask typeFromNativeBehavior(
-      native.NativeBehavior nativeBehavior, ClosedWorld closedWorld);
+  AbstractValue typeFromNativeBehavior(
+      native.NativeBehavior nativeBehavior, JClosedWorld closedWorld);
 }
 
 /// Map from kernel IR nodes to local entities.
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 8154793..f6812f4 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -1971,7 +1971,6 @@
             elementMap.elementEnvironment,
             elementMap.types,
             elementMap.commonElements,
-            elementMap._constantEnvironment.constantSystem,
             nativeBasicData,
             nativeDataBuilder,
             interceptorDataBuilder,
@@ -2064,61 +2063,95 @@
       true;
 
   @override
-  bool checkClass(ClassEntity cls) => true;
-
-  @override
   bool checkEntity(Entity element) => true;
 }
 
-class KernelClosedWorld extends ClosedWorldBase
-    with KernelClosedWorldMixin, ClosedWorldRtiNeedMixin {
+class KClosedWorldImpl extends ClosedWorldRtiNeedMixin implements KClosedWorld {
   final KernelToElementMapForImpactImpl elementMap;
+  final ElementEnvironment elementEnvironment;
+  final DartTypes dartTypes;
+  final CommonElements commonElements;
+  final NativeData nativeData;
+  final InterceptorData interceptorData;
+  final BackendUsage backendUsage;
+  final NoSuchMethodData noSuchMethodData;
 
-  KernelClosedWorld(this.elementMap,
+  final Map<ClassEntity, Set<ClassEntity>> mixinUses;
+
+  final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
+
+  final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes;
+  final Map<ClassEntity, ClassSet> _classSets;
+
+  // TODO(johnniwinther): Can this be derived from [ClassSet]s?
+  final Set<ClassEntity> _implementedClasses;
+
+  final Iterable<MemberEntity> liveInstanceMembers;
+
+  /// Members that are written either directly or through a setter selector.
+  final Iterable<MemberEntity> assignedInstanceMembers;
+
+  final Iterable<ClassEntity> liveNativeClasses;
+
+  final Iterable<MemberEntity> processedMembers;
+
+  KClosedWorldImpl(this.elementMap,
       {CompilerOptions options,
-      ElementEnvironment elementEnvironment,
-      DartTypes dartTypes,
-      CommonElements commonElements,
-      ConstantSystem constantSystem,
-      NativeData nativeData,
-      InterceptorData interceptorData,
-      BackendUsage backendUsage,
-      NoSuchMethodData noSuchMethodData,
+      this.elementEnvironment,
+      this.dartTypes,
+      this.commonElements,
+      this.nativeData,
+      this.interceptorData,
+      this.backendUsage,
+      this.noSuchMethodData,
       ResolutionWorldBuilder resolutionWorldBuilder,
       RuntimeTypesNeedBuilder rtiNeedBuilder,
       Set<ClassEntity> implementedClasses,
-      Iterable<ClassEntity> liveNativeClasses,
-      Iterable<MemberEntity> liveInstanceMembers,
-      Iterable<MemberEntity> assignedInstanceMembers,
-      Iterable<MemberEntity> processedMembers,
-      Map<ClassEntity, Set<ClassEntity>> mixinUses,
-      Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
+      this.liveNativeClasses,
+      this.liveInstanceMembers,
+      this.assignedInstanceMembers,
+      this.processedMembers,
+      this.mixinUses,
+      this.typesImplementedBySubclasses,
       Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
       Map<ClassEntity, ClassSet> classSets})
-      : super(
-            elementEnvironment,
-            dartTypes,
-            commonElements,
-            constantSystem,
-            nativeData,
-            interceptorData,
-            backendUsage,
-            noSuchMethodData,
-            implementedClasses,
-            liveNativeClasses,
-            liveInstanceMembers,
-            assignedInstanceMembers,
-            processedMembers,
-            mixinUses,
-            typesImplementedBySubclasses,
-            classHierarchyNodes,
-            classSets) {
+      : _implementedClasses = implementedClasses,
+        _classHierarchyNodes = classHierarchyNodes,
+        _classSets = classSets {
     computeRtiNeed(resolutionWorldBuilder, rtiNeedBuilder, options);
   }
 
-  @override
-  void registerClosureClass(ClassEntity cls) {
-    throw new UnsupportedError('KernelClosedWorld.registerClosureClass');
+  /// Returns `true` if [cls] is implemented by an instantiated class.
+  bool isImplemented(ClassEntity cls) {
+    return _implementedClasses.contains(cls);
+  }
+
+  /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
+  /// of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [JClosedWorld].
+  ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
+    return _classHierarchyNodes[cls];
+  }
+
+  /// Returns [ClassSet] for [cls] used to model the extends and implements
+  /// relations of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [JClosedWorld].
+  ClassSet getClassSet(ClassEntity cls) {
+    return _classSets[cls];
+  }
+
+  /// Applies [f] to each live class that implements [cls] _not_ including [cls]
+  /// itself.
+  void forEachStrictSubtypeOf(
+      ClassEntity cls, IterationStep f(ClassEntity cls)) {
+    ClassSet classSet = _classSets[cls];
+    if (classSet == null) return;
+    classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
+        strict: true);
   }
 }
 
diff --git a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
index ae1b004..b77533f 100644
--- a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart
@@ -25,7 +25,7 @@
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
 import '../ssa/types.dart';
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/selector.dart';
 import '../universe/world_impact.dart';
@@ -43,7 +43,7 @@
 
 class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
   final JavaScriptBackend _backend;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
 
   KernelCodegenWorkItemBuilder(this._backend, this._closedWorld);
 
@@ -67,7 +67,7 @@
 
 class KernelCodegenWorkItem extends CodegenWorkItem {
   final JavaScriptBackend _backend;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final MemberEntity element;
   final CodegenRegistry registry;
 
@@ -92,7 +92,7 @@
       this.task, this._compiler, this._elementMap, this._globalLocalsMap);
 
   @override
-  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
+  HGraph build(CodegenWorkItem work, JClosedWorld closedWorld) {
     return task.measure(() {
       KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
           work.element,
@@ -125,94 +125,76 @@
       _globalInferenceResults
           .resultOfMember(e is ConstructorBodyEntity ? e.constructor : e);
 
-  TypeMask getReturnTypeOf(FunctionEntity function) {
-    return TypeMaskFactory.inferredReturnTypeForElement(
+  AbstractValue getReturnTypeOf(FunctionEntity function) {
+    return AbstractValueFactory.inferredReturnTypeForElement(
         function, _globalInferenceResults);
   }
 
-  TypeMask receiverTypeOfInvocation(
-      ir.MethodInvocation node, ClosedWorld closedWorld) {
+  AbstractValue receiverTypeOfInvocation(
+      ir.MethodInvocation node, AbstractValueDomain abstractValueDomain) {
     return _targetResults.typeOfSend(node);
   }
 
-  TypeMask receiverTypeOfGet(ir.PropertyGet node) {
+  AbstractValue receiverTypeOfGet(ir.PropertyGet node) {
     return _targetResults.typeOfSend(node);
   }
 
-  TypeMask receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
+  AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
     return _targetResults.typeOfSend(node);
   }
 
-  TypeMask receiverTypeOfSet(ir.PropertySet node, ClosedWorld closedWorld) {
+  AbstractValue receiverTypeOfSet(
+      ir.PropertySet node, AbstractValueDomain abstractValueDomain) {
     return _targetResults.typeOfSend(node);
   }
 
-  TypeMask typeOfListLiteral(
-      MemberEntity owner, ir.ListLiteral listLiteral, ClosedWorld closedWorld) {
+  AbstractValue typeOfListLiteral(MemberEntity owner,
+      ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain) {
     return _resultOf(owner).typeOfListLiteral(listLiteral) ??
-        closedWorld.abstractValueDomain.dynamicType;
+        abstractValueDomain.dynamicType;
   }
 
-  TypeMask typeOfIterator(ir.ForInStatement node) {
+  AbstractValue typeOfIterator(ir.ForInStatement node) {
     return _targetResults.typeOfIterator(node);
   }
 
-  TypeMask typeOfIteratorCurrent(ir.ForInStatement node) {
+  AbstractValue typeOfIteratorCurrent(ir.ForInStatement node) {
     return _targetResults.typeOfIteratorCurrent(node);
   }
 
-  TypeMask typeOfIteratorMoveNext(ir.ForInStatement node) {
+  AbstractValue typeOfIteratorMoveNext(ir.ForInStatement node) {
     return _targetResults.typeOfIteratorMoveNext(node);
   }
 
-  bool isJsIndexableIterator(ir.ForInStatement node, ClosedWorld closedWorld) {
-    TypeMask mask = typeOfIterator(node);
-    return mask != null &&
-        mask.satisfies(
-            closedWorld.commonElements.jsIndexableClass, closedWorld) &&
-        // String is indexable but not iterable.
-        !mask.satisfies(closedWorld.commonElements.jsStringClass, closedWorld);
+  bool isJsIndexableIterator(
+      ir.ForInStatement node, AbstractValueDomain abstractValueDomain) {
+    AbstractValue mask = typeOfIterator(node);
+    return abstractValueDomain.isJsIndexableAndIterable(mask);
   }
 
-  bool isFixedLength(covariant TypeMask mask, ClosedWorld closedWorld) {
-    if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
-      // A container on which we have inferred the length.
-      return true;
-    }
-    // TODO(sra): Recognize any combination of fixed length indexables.
-    if (mask.containsOnly(closedWorld.commonElements.jsFixedArrayClass) ||
-        mask.containsOnly(
-            closedWorld.commonElements.jsUnmodifiableArrayClass) ||
-        mask.containsOnlyString(closedWorld) ||
-        closedWorld.abstractValueDomain.isTypedArray(mask)) {
-      return true;
-    }
-    return false;
-  }
-
-  TypeMask inferredIndexType(ir.ForInStatement node) {
-    return TypeMaskFactory.inferredTypeForSelector(
+  AbstractValue inferredIndexType(ir.ForInStatement node) {
+    return AbstractValueFactory.inferredTypeForSelector(
         new Selector.index(), typeOfIterator(node), _globalInferenceResults);
   }
 
-  TypeMask getInferredTypeOf(MemberEntity member) {
-    return TypeMaskFactory.inferredTypeForMember(
+  AbstractValue getInferredTypeOf(MemberEntity member) {
+    return AbstractValueFactory.inferredTypeForMember(
         member, _globalInferenceResults);
   }
 
-  TypeMask getInferredTypeOfParameter(Local parameter) {
-    return TypeMaskFactory.inferredTypeForParameter(
+  AbstractValue getInferredTypeOfParameter(Local parameter) {
+    return AbstractValueFactory.inferredTypeForParameter(
         parameter, _globalInferenceResults);
   }
 
-  TypeMask selectorTypeOf(Selector selector, covariant TypeMask mask) {
-    return TypeMaskFactory.inferredTypeForSelector(
+  AbstractValue selectorTypeOf(Selector selector, AbstractValue mask) {
+    return AbstractValueFactory.inferredTypeForSelector(
         selector, mask, _globalInferenceResults);
   }
 
-  TypeMask typeFromNativeBehavior(
-      NativeBehavior nativeBehavior, ClosedWorld closedWorld) {
-    return TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld);
+  AbstractValue typeFromNativeBehavior(
+      NativeBehavior nativeBehavior, JClosedWorld closedWorld) {
+    return AbstractValueFactory.fromNativeBehavior(nativeBehavior, closedWorld);
   }
 }
 
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 65e1636..aed9b6c 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -31,7 +31,7 @@
 import '../kernel/element_map.dart';
 import '../kernel/kernel_backend_strategy.dart';
 import '../native/native.dart' as native;
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
@@ -69,7 +69,7 @@
   final MemberEntity targetElement;
   final MemberEntity initialTargetElement;
 
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final CodegenWorldBuilder _worldBuilder;
   final CodegenRegistry registry;
   final ClosureDataLookup closureDataLookup;
@@ -541,7 +541,7 @@
       }
 
       newObject = new HCreate(cls, constructorArguments,
-          new TypeMask.nonNullExact(cls, closedWorld), sourceInformation,
+          abstractValueDomain.createNonNullExact(cls), sourceInformation,
           instantiatedTypes: instantiatedTypes,
           hasRtiInput: needsTypeArguments);
 
@@ -926,10 +926,13 @@
     FunctionType functionType =
         _elementMap.getFunctionType(originalClosureNode);
     functionType.forEachTypeVariable((TypeVariableType typeVariableType) {
-      DartType result = localsHandler.substInContext(typeVariableType);
-      HInstruction argument =
-          typeBuilder.analyzeTypeArgument(result, sourceElement);
-      typeArguments.add(argument);
+      if (options.strongMode ||
+          typeVariableType.element.typeDeclaration is ClassEntity) {
+        DartType result = localsHandler.substInContext(typeVariableType);
+        HInstruction argument =
+            typeBuilder.analyzeTypeArgument(result, sourceElement);
+        typeArguments.add(argument);
+      }
     });
     push(new HTypeInfoExpression(
         TypeInfoExpressionKind.COMPLETE,
@@ -1206,7 +1209,7 @@
       String arguments = templateArguments.join(',');
 
       // TODO(sra): Use declared type or NativeBehavior type.
-      TypeMask typeMask = abstractValueDomain.dynamicType;
+      AbstractValue typeMask = abstractValueDomain.dynamicType;
       String template;
       if (targetElement.isGetter) {
         template = '${templateReceiver}$nativeName';
@@ -1245,7 +1248,7 @@
   }
 
   void openFunction(MemberEntity member, [ir.FunctionNode functionNode]) {
-    Map<Local, TypeMask> parameterMap = <Local, TypeMask>{};
+    Map<Local, AbstractValue> parameterMap = <Local, AbstractValue>{};
     if (functionNode != null) {
       void handleParameter(ir.VariableDeclaration node) {
         Local local = localsMap.getLocalVariable(node);
@@ -1494,7 +1497,8 @@
   void visitForInStatement(ir.ForInStatement node) {
     if (node.isAsync) {
       _buildAsyncForIn(node);
-    } else if (_typeInferenceMap.isJsIndexableIterator(node, closedWorld)) {
+    } else if (_typeInferenceMap.isJsIndexableIterator(
+        node, abstractValueDomain)) {
       // If the expression being iterated over is a JS indexable type, we can
       // generate an optimized version of for-in that uses indexing.
       _buildForInIndexable(node);
@@ -1561,7 +1565,7 @@
       node.iterable.accept(this);
       array = pop();
       isFixed =
-          _typeInferenceMap.isFixedLength(array.instructionType, closedWorld);
+          abstractValueDomain.isFixedLengthJsIndexable(array.instructionType);
       localsHandler.updateLocal(
           indexVariable, graph.addConstantInt(0, closedWorld),
           sourceInformation: sourceInformation);
@@ -1592,7 +1596,7 @@
       // array, as this is stronger than the iterator's `get current` type, for
       // example, `get current` includes null.
       // TODO(sra): The element type of a container type mask might be better.
-      TypeMask type = _typeInferenceMap.inferredIndexType(node);
+      AbstractValue type = _typeInferenceMap.inferredIndexType(node);
 
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildForInCurrent(node);
@@ -1657,7 +1661,7 @@
     HInstruction iterator;
 
     void buildInitializer() {
-      TypeMask mask = _typeInferenceMap.typeOfIterator(node);
+      AbstractValue mask = _typeInferenceMap.typeOfIterator(node);
       node.iterable.accept(this);
       HInstruction receiver = pop();
       _pushDynamicInvocation(
@@ -1671,7 +1675,7 @@
     }
 
     HInstruction buildCondition() {
-      TypeMask mask = _typeInferenceMap.typeOfIteratorMoveNext(node);
+      AbstractValue mask = _typeInferenceMap.typeOfIteratorMoveNext(node);
       _pushDynamicInvocation(
           node,
           mask,
@@ -1685,7 +1689,7 @@
     void buildBody() {
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildForInCurrent(node);
-      TypeMask mask = _typeInferenceMap.typeOfIteratorCurrent(node);
+      AbstractValue mask = _typeInferenceMap.typeOfIteratorCurrent(node);
       _pushDynamicInvocation(node, mask, Selectors.current, [iterator],
           const <DartType>[], sourceInformation);
 
@@ -1741,7 +1745,7 @@
     void buildInitializer() {}
 
     HInstruction buildCondition() {
-      TypeMask mask = _typeInferenceMap.typeOfIteratorMoveNext(node);
+      AbstractValue mask = _typeInferenceMap.typeOfIteratorMoveNext(node);
       _pushDynamicInvocation(
           node,
           mask,
@@ -1755,7 +1759,7 @@
     }
 
     void buildBody() {
-      TypeMask mask = _typeInferenceMap.typeOfIteratorCurrent(node);
+      AbstractValue mask = _typeInferenceMap.typeOfIteratorCurrent(node);
       _pushDynamicInvocation(
           node,
           mask,
@@ -2032,8 +2036,8 @@
     }
   }
 
-  void generateError(FunctionEntity function, String message, TypeMask typeMask,
-      SourceInformation sourceInformation) {
+  void generateError(FunctionEntity function, String message,
+      AbstractValue typeMask, SourceInformation sourceInformation) {
     HInstruction errorMessage = graph.addConstantString(message, closedWorld);
     _pushStaticInvocation(
         function, [errorMessage], typeMask, const <DartType>[],
@@ -2686,9 +2690,9 @@
           listInstruction, type, sourceInformation);
     }
 
-    TypeMask type =
-        _typeInferenceMap.typeOfListLiteral(targetElement, node, closedWorld);
-    if (!type.containsAll(closedWorld)) {
+    AbstractValue type = _typeInferenceMap.typeOfListLiteral(
+        targetElement, node, abstractValueDomain);
+    if (!abstractValueDomain.containsAll(type)) {
       listInstruction.instructionType = type;
     }
     stack.add(listInstruction);
@@ -2761,11 +2765,12 @@
     // type inference might discover a more specific type, or find nothing (in
     // dart2js unit tests).
 
-    TypeMask mapType = new TypeMask.nonNullSubtype(
-        _commonElements.mapLiteralClass, closedWorld);
-    TypeMask returnTypeMask = _typeInferenceMap.getReturnTypeOf(constructor);
-    TypeMask instructionType =
-        mapType.intersection(returnTypeMask, closedWorld);
+    AbstractValue mapType = abstractValueDomain
+        .createNonNullSubtype(_commonElements.mapLiteralClass);
+    AbstractValue returnTypeMask =
+        _typeInferenceMap.getReturnTypeOf(constructor);
+    AbstractValue instructionType =
+        abstractValueDomain.intersection(mapType, returnTypeMask);
 
     addImplicitInstantiation(type);
     _pushStaticInvocation(
@@ -2926,7 +2931,7 @@
 
     _pushDynamicInvocation(
         node,
-        _typeInferenceMap.receiverTypeOfSet(node, closedWorld),
+        _typeInferenceMap.receiverTypeOfSet(node, abstractValueDomain),
         new Selector.setter(_elementMap.getName(node.name)),
         <HInstruction>[receiver, value],
         const <DartType>[],
@@ -3248,7 +3253,7 @@
       return;
     }
 
-    TypeMask typeMask = _typeInferenceMap.getReturnTypeOf(function);
+    AbstractValue typeMask = _typeInferenceMap.getReturnTypeOf(function);
 
     List<DartType> typeArguments =
         _getStaticTypeArguments(function, node.arguments);
@@ -3278,7 +3283,7 @@
   void handleInvokeFactoryConstructor(
       ir.StaticInvocation invocation,
       ConstructorEntity function,
-      TypeMask typeMask,
+      AbstractValue typeMask,
       List<HInstruction> arguments,
       SourceInformation sourceInformation) {
     if (function.isExternal && function.isFromEnvironmentConstructor) {
@@ -3316,7 +3321,7 @@
       return;
     }
 
-    TypeMask resultType = typeMask;
+    AbstractValue resultType = typeMask;
 
     bool isJSArrayTypedConstructor =
         function == commonElements.jsArrayTypedConstructor;
@@ -3749,7 +3754,7 @@
         failedAt(_elementMap.getSpannable(targetElement, invocation),
             "No NativeBehavior for $invocation"));
 
-    TypeMask ssaType =
+    AbstractValue ssaType =
         _typeInferenceMap.typeFromNativeBehavior(nativeBehavior, closedWorld);
     push(new HForeignCode(expr, ssaType, const <HInstruction>[],
         nativeBehavior: nativeBehavior));
@@ -3796,7 +3801,7 @@
         failedAt(_elementMap.getSpannable(targetElement, invocation),
             "No NativeBehavior for $invocation"));
 
-    TypeMask ssaType =
+    AbstractValue ssaType =
         _typeInferenceMap.typeFromNativeBehavior(nativeBehavior, closedWorld);
     push(new HForeignCode(template, ssaType, inputs,
         nativeBehavior: nativeBehavior));
@@ -3892,7 +3897,7 @@
           MessageKind.JS_PLACEHOLDER_CAPTURE);
     }
 
-    TypeMask ssaType =
+    AbstractValue ssaType =
         _typeInferenceMap.typeFromNativeBehavior(nativeBehavior, closedWorld);
 
     SourceInformation sourceInformation = null;
@@ -3905,7 +3910,7 @@
     push(code);
 
     DartType type = _getDartTypeIfValid(invocation.arguments.types.single);
-    TypeMask trustedMask = typeBuilder.trustTypeMask(type);
+    AbstractValue trustedMask = typeBuilder.trustTypeMask(type);
 
     if (trustedMask != null) {
       // We only allow the type argument to narrow `dynamic`, which probably
@@ -3913,7 +3918,8 @@
       if (abstractValueDomain.containsAll(code.instructionType)) {
         // Overwrite the type with the narrower type.
         code.instructionType = trustedMask;
-      } else if (trustedMask.containsMask(code.instructionType, closedWorld)) {
+      } else if (abstractValueDomain.contains(
+          trustedMask, code.instructionType)) {
         // It is acceptable for the type parameter to be broader than the
         // specified type.
       } else {
@@ -3941,7 +3947,7 @@
   }
 
   void _pushStaticInvocation(MemberEntity target, List<HInstruction> arguments,
-      TypeMask typeMask, List<DartType> typeArguments,
+      AbstractValue typeMask, List<DartType> typeArguments,
       {SourceInformation sourceInformation, InterfaceType instanceType}) {
     // TODO(redemption): Pass current node if needed.
     if (_tryInlineMethod(target, null, null, arguments, null, sourceInformation,
@@ -3969,7 +3975,7 @@
 
   void _pushDynamicInvocation(
       ir.Node node,
-      TypeMask mask,
+      AbstractValue mask,
       Selector selector,
       List<HInstruction> arguments,
       List<DartType> typeArguments,
@@ -4034,7 +4040,7 @@
     }
     inputs.addAll(arguments);
 
-    TypeMask type = _typeInferenceMap.selectorTypeOf(selector, mask);
+    AbstractValue type = _typeInferenceMap.selectorTypeOf(selector, mask);
     if (selector.isGetter) {
       push(new HInvokeDynamicGetter(selector, mask, null, inputs, isIntercepted,
           type, sourceInformation));
@@ -4164,7 +4170,8 @@
           .add(localsHandler.readLocal(closureInfo.getLocalForField(field)));
     });
 
-    TypeMask type = new TypeMask.nonNullExact(closureClassEntity, closedWorld);
+    AbstractValue type =
+        abstractValueDomain.createNonNullExact(closureClassEntity);
     // TODO(efortuna): Add source information here.
     push(new HCreate(
         closureClassEntity, capturedVariables, type, sourceInformation,
@@ -4234,7 +4241,7 @@
         _fillDynamicTypeArguments(selector, node.arguments, typeArguments);
     _pushDynamicInvocation(
         node,
-        _typeInferenceMap.receiverTypeOfInvocation(node, closedWorld),
+        _typeInferenceMap.receiverTypeOfInvocation(node, abstractValueDomain),
         selector,
         <HInstruction>[receiver]..addAll(_visitArgumentsForDynamicTarget(
             selector, node.arguments, typeArguments)),
@@ -4337,7 +4344,7 @@
     inputs.add(receiver);
     inputs.addAll(arguments);
 
-    TypeMask typeMask;
+    AbstractValue typeMask;
     if (target is FunctionEntity) {
       typeMask = _typeInferenceMap.getReturnTypeOf(target);
     } else {
@@ -4536,7 +4543,7 @@
 
     ConstructorEntity constructor = _elementMap.getConstructor(target);
     ClassEntity cls = constructor.enclosingClass;
-    TypeMask typeMask = new TypeMask.nonNullExact(cls, closedWorld);
+    AbstractValue typeMask = abstractValueDomain.createNonNullExact(cls);
     InterfaceType instanceType = _elementMap.createInterfaceType(
         target.enclosingClass, node.arguments.types);
     instanceType = localsHandler.substInContext(instanceType);
@@ -4818,7 +4825,7 @@
   bool _tryInlineMethod(
       FunctionEntity function,
       Selector selector,
-      TypeMask mask,
+      AbstractValue mask,
       List<HInstruction> providedArguments,
       ir.Node currentNode,
       SourceInformation sourceInformation,
@@ -4856,7 +4863,8 @@
           failedAt(function, "Missing selector for inlining of $function."));
       if (selector != null) {
         if (!selector.applies(function)) return false;
-        if (mask != null && !mask.canHit(function, selector, closedWorld)) {
+        if (mask != null &&
+            !abstractValueDomain.canHit(mask, function, selector)) {
           return false;
         }
       }
@@ -4988,7 +4996,7 @@
       // NoSuchMethodError message as if we had called it.
       if (function.isInstanceMember &&
           function is! ConstructorBodyEntity &&
-          (mask == null || mask.isNullable)) {
+          (mask == null || abstractValueDomain.canBeNull(mask))) {
         add(new HFieldGet(
             null, providedArguments[0], abstractValueDomain.dynamicType,
             isAssignable: false)
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 4e299b0..3d08315 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -29,12 +29,11 @@
 import '../native/native.dart' as native;
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart'
     show ConstantUse, ConstrainedDynamicUse, StaticUse, TypeUse;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'codegen_helpers.dart';
 import 'nodes.dart';
 import 'variable_allocator.dart';
@@ -72,7 +71,7 @@
   }
 
   js.Expression generateCode(
-      CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
+      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
     if (work.element.isField) {
       return generateLazyInitializer(work, graph, closedWorld);
     } else {
@@ -81,7 +80,7 @@
   }
 
   js.Expression generateLazyInitializer(
-      CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
+      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
     return measure(() {
       backend.tracer.traceGraph("codegen", graph);
       SourceInformation sourceInformation = sourceInformationFactory
@@ -106,7 +105,7 @@
   }
 
   js.Expression generateMethod(
-      CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
+      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
     return measure(() {
       FunctionEntity element = work.element;
       if (element.asyncMarker != AsyncMarker.SYNC) {
@@ -132,8 +131,6 @@
   }
 }
 
-typedef void EntityAction(Entity element);
-
 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
   /**
    * Returned by [expressionType] to tell how code can be generated for
@@ -166,13 +163,14 @@
   final RuntimeTypesEncoder _rtiEncoder;
   final Namer _namer;
   final SuperMemberData _superMemberData;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final CodegenWorkItem _work;
 
   final Set<HInstruction> generateAtUseSite;
   final Set<HInstruction> controlFlowOperators;
-  final Map<Entity, EntityAction> breakAction;
-  final Map<Entity, EntityAction> continueAction;
+  final Set<JumpTarget> breakAction;
+  final Set<LabelDefinition> continueAction;
+  final Set<JumpTarget> implicitContinueAction;
   final List<js.Parameter> parameters;
 
   js.Block currentContainer;
@@ -233,8 +231,9 @@
         oldContainerStack = <js.Block>[],
         generateAtUseSite = new Set<HInstruction>(),
         controlFlowOperators = new Set<HInstruction>(),
-        breakAction = new Map<Entity, EntityAction>(),
-        continueAction = new Map<Entity, EntityAction>();
+        breakAction = new Set<JumpTarget>(),
+        continueAction = new Set<LabelDefinition>(),
+        implicitContinueAction = new Set<JumpTarget>();
 
   CodegenRegistry get _registry => _work.registry;
 
@@ -365,8 +364,8 @@
         .visitGraph(graph);
     new SsaTypeKnownRemover().visitGraph(graph);
     new SsaTrustedCheckRemover(_options).visitGraph(graph);
-    new SsaInstructionMerger(_closedWorld.abstractValueDomain,
-            generateAtUseSite, _superMemberData)
+    new SsaInstructionMerger(
+            _abstractValueDomain, generateAtUseSite, _superMemberData)
         .visitGraph(graph);
     new SsaConditionMerger(generateAtUseSite, controlFlowOperators)
         .visitGraph(graph);
@@ -1131,7 +1130,7 @@
         if (label.isContinueTarget) {
           String labelName = _namer.continueLabelName(label);
           result = new js.LabeledStatement(labelName, result);
-          continueAction[label] = continueAsBreak;
+          continueAction.add(label);
           continueOverrides = continueOverrides.prepend(label);
         }
       }
@@ -1141,7 +1140,7 @@
       JumpTarget target = labeledBlockInfo.target;
       String labelName = _namer.implicitContinueLabelName(target);
       result = new js.LabeledStatement(labelName, result);
-      continueAction[target] = implicitContinueAsBreak;
+      implicitContinueAction.add(target);
       continueOverrides = continueOverrides.prepend(target);
     } else {
       for (LabelDefinition label in labeledBlockInfo.labels) {
@@ -1158,7 +1157,7 @@
       // so that case code can break.
       String labelName = _namer.implicitBreakLabelName(target);
       result = new js.LabeledStatement(labelName, result);
-      breakAction[target] = implicitBreakWithLabel;
+      breakAction.add(target);
     }
 
     currentContainer = body;
@@ -1167,6 +1166,7 @@
     if (labeledBlockInfo.isContinue) {
       while (!continueOverrides.isEmpty) {
         continueAction.remove(continueOverrides.head);
+        implicitContinueAction.remove(continueOverrides.head);
         continueOverrides = continueOverrides.tail;
       }
     } else {
@@ -1191,14 +1191,14 @@
         if (label.isContinueTarget) {
           String labelName = _namer.continueLabelName(label);
           result = new js.LabeledStatement(labelName, result);
-          continueAction[label] = continueAsBreak;
+          continueAction.add(label);
         }
       }
       String labelName = _namer.implicitContinueLabelName(target);
       result = new js.LabeledStatement(labelName, result);
-      continueAction[info.target] = implicitContinueAsBreak;
+      implicitContinueAction.add(info.target);
       visitBodyIgnoreLabels(info);
-      continueAction.remove(info.target);
+      implicitContinueAction.remove(info.target);
       for (LabelDefinition label in info.labels) {
         if (label.isContinueTarget) {
           continueAction.remove(label);
@@ -1556,29 +1556,21 @@
     }
   }
 
-  /**
-   * Checks if [map] contains an [EntityAction] for [entity], and
-   * if so calls that action and returns true.
-   * Otherwise returns false.
-   */
-  bool tryCallAction(Map<Entity, EntityAction> map, Entity entity) {
-    EntityAction action = map[entity];
-    if (action == null) return false;
-    action(entity);
-    return true;
-  }
-
   visitBreak(HBreak node) {
     assert(node.block.successors.length == 1);
     if (node.label != null) {
       LabelDefinition label = node.label;
-      if (!tryCallAction(breakAction, label)) {
+      if (breakAction.contains(label.target)) {
+        implicitBreakWithLabel(label.target);
+      } else {
         pushStatement(new js.Break(_namer.breakLabelName(label))
             .withSourceInformation(node.sourceInformation));
       }
     } else {
       JumpTarget target = node.target;
-      if (!tryCallAction(breakAction, target)) {
+      if (breakAction.contains(target)) {
+        implicitBreakWithLabel(target);
+      } else {
         if (node.breakSwitchContinueLoop) {
           pushStatement(new js.Break(_namer.implicitContinueLabelName(target))
               .withSourceInformation(node.sourceInformation));
@@ -1594,14 +1586,18 @@
     assert(node.block.successors.length == 1);
     if (node.label != null) {
       LabelDefinition label = node.label;
-      if (!tryCallAction(continueAction, label)) {
+      if (continueAction.contains(label)) {
+        continueAsBreak(label);
+      } else {
         // TODO(floitsch): should this really be the breakLabelName?
         pushStatement(new js.Continue(_namer.breakLabelName(label))
             .withSourceInformation(node.sourceInformation));
       }
     } else {
       JumpTarget target = node.target;
-      if (!tryCallAction(continueAction, target)) {
+      if (implicitContinueAction.contains(target)) {
+        implicitContinueAsBreak(target);
+      } else {
         if (target.isSwitch) {
           pushStatement(
               new js.Continue(_namer.implicitContinueLabelName(target))
@@ -1831,8 +1827,8 @@
     _registry.registerUseInterceptor();
   }
 
-  TypeMask getOptimizedSelectorFor(
-      HInvokeDynamic node, Selector selector, TypeMask mask) {
+  AbstractValue getOptimizedSelectorFor(
+      HInvokeDynamic node, Selector selector, AbstractValue mask) {
     if (node.element != null) {
       // Create an artificial type mask to make sure only
       // [node.element] will be enqueued. We're not using the receiver
@@ -1840,7 +1836,7 @@
       // invoke dynamic knows more than the receiver.
       ClassEntity enclosing = node.element.enclosingClass;
       if (_closedWorld.isInstantiated(enclosing)) {
-        return _closedWorld.abstractValueDomain.createNonNullExact(enclosing);
+        return _abstractValueDomain.createNonNullExact(enclosing);
       } else {
         // The element is mixed in so a non-null subtype mask is the most
         // precise we have.
@@ -1850,7 +1846,7 @@
                 node,
                 "Element ${node.element} from $enclosing expected "
                 "to be mixed in."));
-        return _closedWorld.abstractValueDomain.createNonNullSubtype(enclosing);
+        return _abstractValueDomain.createNonNullSubtype(enclosing);
       }
     }
     // If [JSInvocationMirror._invokeOn] is enabled, and this call
@@ -1883,7 +1879,7 @@
       _registry.registerStaticUse(new StaticUse.directInvoke(
           target, selector.callStructure, node.typeArguments));
     } else {
-      TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
+      AbstractValue mask = getOptimizedSelectorFor(node, selector, node.mask);
       _registry.registerDynamicUse(
           new ConstrainedDynamicUse(selector, mask, node.typeArguments));
     }
@@ -1898,7 +1894,7 @@
       _registry.registerStaticUse(new StaticUse.directSet(node.element));
     } else {
       Selector selector = node.selector;
-      TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
+      AbstractValue mask = getOptimizedSelectorFor(node, selector, node.mask);
       _registry.registerDynamicUse(
           new ConstrainedDynamicUse(selector, mask, node.typeArguments));
     }
@@ -1915,7 +1911,7 @@
       _registry.registerStaticUse(new StaticUse.directGet(node.element));
     } else {
       Selector selector = node.selector;
-      TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
+      AbstractValue mask = getOptimizedSelectorFor(node, selector, node.mask);
       _registry.registerDynamicUse(
           new ConstrainedDynamicUse(selector, mask, node.typeArguments));
     }
@@ -2932,19 +2928,18 @@
 
   js.Expression generateReceiverOrArgumentTypeTest(HTypeConversion node) {
     HInstruction input = node.checkedInput;
-    TypeMask inputType = node.inputType ?? input.instructionType;
-    TypeMask checkedType = node.checkedType;
+    AbstractValue inputType = node.inputType ?? input.instructionType;
+    AbstractValue checkedType = node.checkedType;
     // This path is no longer used for indexable primitive types.
-    assert(
-        !checkedType.satisfies(_commonElements.jsIndexableClass, _closedWorld));
+    assert(!_abstractValueDomain.isJsIndexable(checkedType));
     // Figure out if it is beneficial to use a null check.  V8 generally prefers
     // 'typeof' checks, but for integers we cannot compile this test into a
     // single typeof check so the null check is cheaper.
-    bool isIntCheck = checkedType.containsOnlyInt(_closedWorld);
+    bool isIntCheck = _abstractValueDomain.isIntegerOrNull(checkedType);
     bool turnIntoNumCheck =
-        isIntCheck && inputType.containsOnlyInt(_closedWorld);
+        isIntCheck && _abstractValueDomain.isIntegerOrNull(inputType);
     bool turnIntoNullCheck = !turnIntoNumCheck &&
-        (checkedType.nullable() == inputType) &&
+        (_abstractValueDomain.includeNull(checkedType) == inputType) &&
         isIntCheck;
 
     if (turnIntoNullCheck) {
@@ -2955,15 +2950,16 @@
       // input is !int
       checkBigInt(input, '!==', input.sourceInformation);
       return pop();
-    } else if (turnIntoNumCheck || checkedType.containsOnlyNum(_closedWorld)) {
+    } else if (turnIntoNumCheck ||
+        _abstractValueDomain.isNumberOrNull(checkedType)) {
       // input is !num
       checkNum(input, '!==', input.sourceInformation);
       return pop();
-    } else if (checkedType.containsOnlyBool(_closedWorld)) {
+    } else if (_abstractValueDomain.isBooleanOrNull(checkedType)) {
       // input is !bool
       checkBool(input, '!==', input.sourceInformation);
       return pop();
-    } else if (checkedType.containsOnlyString(_closedWorld)) {
+    } else if (_abstractValueDomain.isStringOrNull(checkedType)) {
       // input is !string
       checkString(input, '!==', input.sourceInformation);
       return pop();
@@ -3096,6 +3092,7 @@
   }
 
   void visitTypeInfoExpression(HTypeInfoExpression node) {
+    DartType type = node.dartType;
     List<js.Expression> arguments = <js.Expression>[];
     for (HInstruction input in node.inputs) {
       use(input);
@@ -3107,19 +3104,19 @@
         int index = 0;
         js.Expression result = _rtiEncoder.getTypeRepresentation(
             _emitter.emitter,
-            node.dartType,
+            type,
             (TypeVariableType variable) => arguments[index++]);
         assert(
             index == node.inputs.length,
-            "Not all input is read for type ${node.dartType}: "
+            "Not all input is read for type ${type}: "
             "$index of ${node.inputs}.");
         push(result);
         return;
 
       case TypeInfoExpressionKind.INSTANCE:
         // We expect only flat types for the INSTANCE representation.
-        assert((node.dartType as InterfaceType).typeArguments.length ==
-            arguments.length);
+        assert(
+            (type as InterfaceType).typeArguments.length == arguments.length);
         _registry.registerInstantiatedClass(_commonElements.listClass);
         push(new js.ArrayInitializer(arguments)
             .withSourceInformation(node.sourceInformation));
@@ -3127,14 +3124,15 @@
   }
 
   bool typeVariableAccessNeedsSubstitution(
-      TypeVariableEntity element, TypeMask receiverMask) {
+      TypeVariableEntity element, AbstractValue receiverMask) {
     ClassEntity cls = element.typeDeclaration;
 
     // See if the receiver type narrows the set of classes to ones that can be
     // indexed.
     // TODO(sra): Currently the only convenient query is [singleClass]. We
     // should iterate over all the concrete classes in [receiverMask].
-    ClassEntity receiverClass = receiverMask.singleClass(_closedWorld);
+    ClassEntity receiverClass =
+        _abstractValueDomain.getExactClass(receiverMask);
     if (receiverClass != null) {
       if (_rtiSubstitutions.isTrivialSubstitution(receiverClass, cls)) {
         return false;
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index bfa7fb2..ca08263 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -8,9 +8,8 @@
 import '../js_backend/interceptor_data.dart';
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
 
 /**
@@ -18,7 +17,7 @@
  * Caches codegen information on nodes.
  */
 class SsaInstructionSelection extends HBaseVisitor {
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final InterceptorData _interceptorData;
   HGraph graph;
 
@@ -71,8 +70,8 @@
     if (node.kind == HIs.RAW_CHECK) {
       HInstruction interceptor = node.interceptor;
       if (interceptor != null) {
-        return new HIsViaInterceptor(node.typeExpression, interceptor,
-            _closedWorld.abstractValueDomain.boolType);
+        return new HIsViaInterceptor(
+            node.typeExpression, interceptor, _abstractValueDomain.boolType);
       }
     }
     return node;
@@ -86,9 +85,10 @@
   String simpleOp(HInstruction left, HInstruction right) {
     // Returns the single identity comparison (== or ===) or null if a more
     // complex expression is required.
-    TypeMask leftType = left.instructionType;
-    TypeMask rightType = right.instructionType;
-    if (leftType.isNullable && rightType.isNullable) {
+    AbstractValue leftType = left.instructionType;
+    AbstractValue rightType = right.instructionType;
+    if (_abstractValueDomain.canBeNull(leftType) &&
+        _abstractValueDomain.canBeNull(rightType)) {
       if (left.isConstantNull() ||
           right.isConstantNull() ||
           (left.isPrimitive(_abstractValueDomain) && leftType == rightType)) {
@@ -108,14 +108,14 @@
 
   HInstruction visitInvokeSuper(HInvokeSuper node) {
     if (node.isInterceptedCall) {
-      TypeMask mask = node.getDartReceiver(_closedWorld).instructionType;
+      AbstractValue mask = node.getDartReceiver(_closedWorld).instructionType;
       tryReplaceInterceptorWithDummy(node, node.selector, mask);
     }
     return node;
   }
 
   void tryReplaceInterceptorWithDummy(
-      HInvoke node, Selector selector, TypeMask mask) {
+      HInvoke node, Selector selector, AbstractValue mask) {
     // Calls of the form
     //
     //     a.foo$1(a, x)
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 6dc7c0a..e67eeb4 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -24,9 +24,8 @@
 import '../js_emitter/code_emitter_task.dart';
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../types/types.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'jump_handler.dart';
 import 'locals_handler.dart';
 import 'nodes.dart';
@@ -54,7 +53,7 @@
 
   CodegenRegistry get registry;
 
-  ClosedWorld get closedWorld;
+  JClosedWorld get closedWorld;
 
   AbstractValueDomain get abstractValueDomain =>
       closedWorld.abstractValueDomain;
@@ -131,7 +130,7 @@
   /// Pushes a boolean checking [expression] against null.
   pushCheckNull(HInstruction expression) {
     push(new HIdentity(expression, graph.addConstantNull(closedWorld), null,
-        closedWorld.abstractValueDomain.boolType));
+        abstractValueDomain.boolType));
   }
 
   void dup() {
@@ -215,7 +214,7 @@
     current.add(instruction);
   }
 
-  HParameterValue addParameter(Entity parameter, TypeMask type) {
+  HParameterValue addParameter(Entity parameter, AbstractValue type) {
     HParameterValue result = new HParameterValue(parameter, type);
     if (lastAddedParameter == null) {
       graph.entry.addBefore(graph.entry.first, result);
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index a3ec846..a9be144 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -3,14 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common_elements.dart' show CommonElements;
-import '../constants/constant_system.dart';
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../js_backend/interceptor_data.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
@@ -37,23 +35,21 @@
 class SsaSimplifyInterceptors extends HBaseVisitor
     implements OptimizationPhase {
   final String name = "SsaSimplifyInterceptors";
-  final ClosedWorld closedWorld;
-  final ClassEntity enclosingClass;
-  HGraph graph;
+  final JClosedWorld _closedWorld;
+  final ClassEntity _enclosingClass;
+  HGraph _graph;
 
-  SsaSimplifyInterceptors(this.closedWorld, this.enclosingClass);
+  SsaSimplifyInterceptors(this._closedWorld, this._enclosingClass);
 
-  CommonElements get _commonElements => closedWorld.commonElements;
+  CommonElements get _commonElements => _closedWorld.commonElements;
 
-  ConstantSystem get constantSystem => closedWorld.constantSystem;
-
-  InterceptorData get interceptorData => closedWorld.interceptorData;
+  InterceptorData get _interceptorData => _closedWorld.interceptorData;
 
   AbstractValueDomain get _abstractValueDomain =>
-      closedWorld.abstractValueDomain;
+      _closedWorld.abstractValueDomain;
 
   void visitGraph(HGraph graph) {
-    this.graph = graph;
+    this._graph = graph;
     visitDominatorTree(graph);
   }
 
@@ -110,18 +106,16 @@
 
     // All intercepted classes extend `Interceptor`, so if the receiver can't be
     // a class extending `Interceptor` then it can be called directly.
-    return new TypeMask.nonNullSubclass(
-            _commonElements.jsInterceptorClass, closedWorld)
-        .isDisjoint(receiver.instructionType, closedWorld);
+    return !_abstractValueDomain.canBeInterceptor(receiver.instructionType);
   }
 
   HInstruction tryComputeConstantInterceptor(
       HInstruction input, Set<ClassEntity> interceptedClasses) {
-    if (input == graph.explicitReceiverParameter) {
+    if (input == _graph.explicitReceiverParameter) {
       // If `explicitReceiverParameter` is set it means the current method is an
       // interceptor method, and `this` is the interceptor.  The caller just did
       // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
-      return graph.thisInstruction;
+      return _graph.thisInstruction;
     }
 
     ClassEntity constantInterceptor = tryComputeConstantInterceptorFromType(
@@ -131,32 +125,32 @@
 
     // If we just happen to be in an instance method of the constant
     // interceptor, `this` is a shorter alias.
-    if (constantInterceptor == enclosingClass &&
-        graph.thisInstruction != null) {
-      return graph.thisInstruction;
+    if (constantInterceptor == _enclosingClass &&
+        _graph.thisInstruction != null) {
+      return _graph.thisInstruction;
     }
 
     ConstantValue constant = new InterceptorConstantValue(constantInterceptor);
-    return graph.addConstant(constant, closedWorld);
+    return _graph.addConstant(constant, _closedWorld);
   }
 
   ClassEntity tryComputeConstantInterceptorFromType(
-      TypeMask type, Set<ClassEntity> interceptedClasses) {
-    if (type.isNullable) {
-      if (type.isNull) {
+      AbstractValue type, Set<ClassEntity> interceptedClasses) {
+    if (_abstractValueDomain.canBeNull(type)) {
+      if (_abstractValueDomain.isNull(type)) {
         return _commonElements.jsNullClass;
       }
-    } else if (type.containsOnlyInt(closedWorld)) {
+    } else if (_abstractValueDomain.isIntegerOrNull(type)) {
       return _commonElements.jsIntClass;
-    } else if (type.containsOnlyDouble(closedWorld)) {
+    } else if (_abstractValueDomain.isDoubleOrNull(type)) {
       return _commonElements.jsDoubleClass;
-    } else if (type.containsOnlyBool(closedWorld)) {
+    } else if (_abstractValueDomain.isBooleanOrNull(type)) {
       return _commonElements.jsBoolClass;
-    } else if (type.containsOnlyString(closedWorld)) {
+    } else if (_abstractValueDomain.isStringOrNull(type)) {
       return _commonElements.jsStringClass;
-    } else if (type.satisfies(_commonElements.jsArrayClass, closedWorld)) {
+    } else if (_abstractValueDomain.isArray(type)) {
       return _commonElements.jsArrayClass;
-    } else if (type.containsOnlyNum(closedWorld) &&
+    } else if (_abstractValueDomain.isNumberOrNull(type) &&
         !interceptedClasses.contains(_commonElements.jsIntClass) &&
         !interceptedClasses.contains(_commonElements.jsDoubleClass)) {
       // If the method being intercepted is not defined in [int] or [double] we
@@ -175,8 +169,8 @@
       // for a subclass or call methods defined on a subclass.  Provided the
       // code is completely insensitive to the specific instance subclasses, we
       // can use the non-leaf class directly.
-      ClassEntity element = type.singleClass(closedWorld);
-      if (element != null && closedWorld.nativeData.isNativeClass(element)) {
+      ClassEntity element = _abstractValueDomain.getExactClass(type);
+      if (element != null && _closedWorld.nativeData.isNativeClass(element)) {
         return element;
       }
     }
@@ -223,11 +217,11 @@
     // If there is a call that dominates all other uses, we can use just the
     // selector of that instruction.
     if (dominator is HInvokeDynamic &&
-        dominator.isCallOnInterceptor(closedWorld) &&
+        dominator.isCallOnInterceptor(_closedWorld) &&
         node == dominator.receiver &&
         useCount(dominator, node) == 1) {
-      interceptedClasses = interceptorData.getInterceptedClassesOn(
-          dominator.selector.name, closedWorld);
+      interceptedClasses = _interceptorData.getInterceptedClassesOn(
+          dominator.selector.name, _closedWorld);
 
       // If we found that we need number, we must still go through all
       // uses to check if they require int, or double.
@@ -237,8 +231,8 @@
         Set<ClassEntity> required;
         for (HInstruction user in node.usedBy) {
           if (user is! HInvoke) continue;
-          Set<ClassEntity> intercepted = interceptorData
-              .getInterceptedClassesOn(user.selector.name, closedWorld);
+          Set<ClassEntity> intercepted = _interceptorData
+              .getInterceptedClassesOn(user.selector.name, _closedWorld);
           if (intercepted.contains(_commonElements.jsIntClass)) {
             // TODO(johnniwinther): Use type argument when all uses of
             // intercepted classes expect entities instead of elements.
@@ -252,7 +246,8 @@
             required.add(_commonElements.jsDoubleClass);
           }
         }
-        // Don't modify the result of [interceptorData.getInterceptedClassesOn].
+        // Don't modify the result of
+        // [_interceptorData.getInterceptedClassesOn].
         if (required != null) {
           interceptedClasses = interceptedClasses.union(required);
         }
@@ -263,21 +258,21 @@
       interceptedClasses = new Set<ClassEntity>();
       for (HInstruction user in node.usedBy) {
         if (user is HInvokeDynamic &&
-            user.isCallOnInterceptor(closedWorld) &&
+            user.isCallOnInterceptor(_closedWorld) &&
             node == user.receiver &&
             useCount(user, node) == 1) {
-          interceptedClasses.addAll(interceptorData.getInterceptedClassesOn(
-              user.selector.name, closedWorld));
+          interceptedClasses.addAll(_interceptorData.getInterceptedClassesOn(
+              user.selector.name, _closedWorld));
         } else if (user is HInvokeSuper &&
-            user.isCallOnInterceptor(closedWorld) &&
+            user.isCallOnInterceptor(_closedWorld) &&
             node == user.receiver &&
             useCount(user, node) == 1) {
-          interceptedClasses.addAll(interceptorData.getInterceptedClassesOn(
-              user.selector.name, closedWorld));
+          interceptedClasses.addAll(_interceptorData.getInterceptedClassesOn(
+              user.selector.name, _closedWorld));
         } else {
           // Use a most general interceptor for other instructions, example,
           // is-checks and escaping interceptors.
-          interceptedClasses.addAll(interceptorData.interceptedClasses);
+          interceptedClasses.addAll(_interceptorData.interceptedClasses);
           break;
         }
       }
@@ -326,8 +321,8 @@
               _abstractValueDomain.excludeNull(receiver.instructionType),
               interceptedClasses);
           if (interceptorClass != null) {
-            HInstruction constantInstruction = graph.addConstant(
-                new InterceptorConstantValue(interceptorClass), closedWorld);
+            HInstruction constantInstruction = _graph.addConstant(
+                new InterceptorConstantValue(interceptorClass), _closedWorld);
             node.conditionalConstantInterceptor = constantInstruction;
             constantInstruction.usedBy.add(node);
             return false;
@@ -355,8 +350,8 @@
       // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite
       // "getInterceptor(x).$isT" to "x instanceof T".
       if (node == user.interceptor) {
-        if (interceptorData.mayGenerateInstanceofCheck(
-            user.typeExpression, closedWorld)) {
+        if (_interceptorData.mayGenerateInstanceofCheck(
+            user.typeExpression, _closedWorld)) {
           HInstruction instanceofCheck = new HIs.instanceOf(user.typeExpression,
               user.expression, user.instructionType, user.sourceInformation);
           instanceofCheck.sourceElement = user.sourceElement;
@@ -366,11 +361,11 @@
     } else if (user is HInvokeDynamic) {
       if (node == user.inputs[0]) {
         // Replace the user with a [HOneShotInterceptor].
-        HConstant nullConstant = graph.addConstantNull(closedWorld);
+        HConstant nullConstant = _graph.addConstantNull(_closedWorld);
         List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
         inputs[0] = nullConstant;
         HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor(
-            closedWorld.abstractValueDomain,
+            _abstractValueDomain,
             user.selector,
             user.mask,
             inputs,
@@ -409,7 +404,7 @@
     if (constant == null) return false;
 
     Selector selector = node.selector;
-    TypeMask mask = node.mask;
+    AbstractValue mask = node.mask;
     HInstruction instruction;
     if (selector.isGetter) {
       instruction = new HInvokeDynamicGetter(
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index e5b0003..43e9c67 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -8,11 +8,11 @@
 import '../elements/entities.dart';
 import '../elements/names.dart';
 import '../options.dart';
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
 import 'types.dart';
 
@@ -25,12 +25,12 @@
 class InvokeDynamicSpecializer {
   const InvokeDynamicSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
-    return TypeMaskFactory.inferredTypeForSelector(
+      JClosedWorld closedWorld) {
+    return AbstractValueFactory.inferredTypeForSelector(
         instruction.selector, instruction.mask, results);
   }
 
@@ -40,7 +40,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return null;
   }
 
@@ -122,7 +122,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction receiver = instruction.inputs[1];
     HInstruction index = instruction.inputs[2];
     if (!receiver.isMutableIndexable(closedWorld.abstractValueDomain))
@@ -151,7 +151,7 @@
       HInstruction receiver,
       HInstruction value,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     // Handle typed arrays by recognizing the exact implementation of `[]=` and
     // checking if [value] has the appropriate type.
     if (instruction.element != null) {
@@ -184,7 +184,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (!instruction.inputs[1]
         .isIndexablePrimitive(closedWorld.abstractValueDomain)) return null;
     if (!instruction.inputs[2].isInteger(closedWorld.abstractValueDomain) &&
@@ -192,9 +192,9 @@
       // We want the right checked mode error.
       return null;
     }
-    TypeMask receiverType =
+    AbstractValue receiverType =
         instruction.getDartReceiver(closedWorld).instructionType;
-    TypeMask type = TypeMaskFactory.inferredTypeForSelector(
+    AbstractValue type = AbstractValueFactory.inferredTypeForSelector(
         instruction.selector, receiverType, results);
     return new HIndex(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, type);
@@ -208,11 +208,11 @@
     return constantSystem.bitNot;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
     if (instruction.inputs[1]
@@ -229,7 +229,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld.abstractValueDomain)) {
       return new HBitNot(
@@ -249,11 +249,11 @@
     return constantSystem.negate;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction operand = instruction.inputs[1];
     if (operand.isNumberOrNull(closedWorld.abstractValueDomain)) {
       // We have integer subclasses that represent ranges, so widen any int
@@ -276,7 +276,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld.abstractValueDomain)) {
       return new HNegate(
@@ -296,11 +296,11 @@
     return constantSystem.abs;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumberOrNull(closedWorld.abstractValueDomain)) {
       return closedWorld.abstractValueDomain.excludeNull(input.instructionType);
@@ -315,7 +315,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld.abstractValueDomain)) {
       return new HAbs(
@@ -331,11 +331,11 @@
 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
   const BinaryArithmeticSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isIntegerOrNull(closedWorld.abstractValueDomain) &&
@@ -353,7 +353,7 @@
         .computeTypeFromInputTypes(instruction, results, options, closedWorld);
   }
 
-  bool isBuiltin(HInvokeDynamic instruction, ClosedWorld closedWorld) {
+  bool isBuiltin(HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return instruction.inputs[1].isNumber(closedWorld.abstractValueDomain) &&
         instruction.inputs[2].isNumber(closedWorld.abstractValueDomain);
   }
@@ -364,7 +364,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (isBuiltin(instruction, closedWorld)) {
       HInstruction builtin =
           newBuiltinVariant(instruction, results, options, closedWorld);
@@ -378,14 +378,14 @@
   }
 
   bool inputsArePositiveIntegers(
-      HInstruction instruction, ClosedWorld closedWorld) {
+      HInstruction instruction, JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     return left.isPositiveIntegerOrNull(closedWorld.abstractValueDomain) &&
         right.isPositiveIntegerOrNull(closedWorld.abstractValueDomain);
   }
 
-  bool inputsAreUInt31(HInstruction instruction, ClosedWorld closedWorld) {
+  bool inputsAreUInt31(HInstruction instruction, JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     return left.isUInt31(closedWorld.abstractValueDomain) &&
@@ -396,17 +396,17 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld);
+      JClosedWorld closedWorld);
 }
 
 class AddSpecializer extends BinaryArithmeticSpecializer {
   const AddSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (inputsAreUInt31(instruction, closedWorld)) {
       return closedWorld.abstractValueDomain.uint32Type;
     }
@@ -425,7 +425,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HAdd(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -441,11 +441,11 @@
     return constantSystem.divide;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInstruction instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     if (left.isNumberOrNull(closedWorld.abstractValueDomain)) {
       return closedWorld.abstractValueDomain.doubleType;
@@ -458,7 +458,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HDivide(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.doubleType);
   }
@@ -467,11 +467,11 @@
 class ModuloSpecializer extends BinaryArithmeticSpecializer {
   const ModuloSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (inputsArePositiveIntegers(instruction, closedWorld)) {
       return closedWorld.abstractValueDomain.positiveIntType;
     }
@@ -487,7 +487,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     // Modulo cannot be mapped to the native operator (different semantics).
 
     // We can use HRemainder if both inputs are non-negative and the receiver
@@ -553,11 +553,11 @@
 class RemainderSpecializer extends BinaryArithmeticSpecializer {
   const RemainderSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (inputsArePositiveIntegers(instruction, closedWorld)) {
       return closedWorld.abstractValueDomain.positiveIntType;
     }
@@ -573,7 +573,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HRemainder(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -589,11 +589,11 @@
     return constantSystem.multiply;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (inputsArePositiveIntegers(instruction, closedWorld)) {
       return closedWorld.abstractValueDomain.positiveIntType;
     }
@@ -605,7 +605,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HMultiply(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -625,7 +625,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HSubtract(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -641,11 +641,11 @@
     return constantSystem.truncatingDivide;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (hasUint31Result(instruction, closedWorld)) {
       return closedWorld.abstractValueDomain.uint31Type;
     }
@@ -672,7 +672,7 @@
     return count >= BigInt.two;
   }
 
-  bool hasUint31Result(HInstruction instruction, ClosedWorld closedWorld) {
+  bool hasUint31Result(HInstruction instruction, JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (right.isPositiveInteger(closedWorld.abstractValueDomain)) {
@@ -693,7 +693,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction right = instruction.inputs[2];
     if (isBuiltin(instruction, closedWorld)) {
       if (right.isPositiveInteger(closedWorld.abstractValueDomain) &&
@@ -715,7 +715,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HTruncatingDivide(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -727,11 +727,11 @@
 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
   const BinaryBitOpSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
     HInstruction left = instruction.inputs[1];
@@ -764,7 +764,7 @@
     return false;
   }
 
-  bool isPositive(HInstruction instruction, ClosedWorld closedWorld) {
+  bool isPositive(HInstruction instruction, JClosedWorld closedWorld) {
     // TODO: We should use the value range analysis. Currently, ranges
     // are discarded just after the analysis.
     return instruction.isPositiveInteger(closedWorld.abstractValueDomain);
@@ -784,7 +784,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber(closedWorld.abstractValueDomain)) {
@@ -807,7 +807,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HShiftLeft(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -819,11 +819,11 @@
 class ShiftRightSpecializer extends BinaryBitOpSpecializer {
   const ShiftRightSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     if (left.isUInt32(closedWorld.abstractValueDomain))
       return left.instructionType;
@@ -837,7 +837,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber(closedWorld.abstractValueDomain)) {
@@ -867,7 +867,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HShiftRight(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -887,11 +887,11 @@
     return constantSystem.bitOr;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isUInt31(closedWorld.abstractValueDomain) &&
@@ -906,7 +906,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HBitOr(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -922,11 +922,11 @@
     return constantSystem.bitAnd;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isPrimitiveOrNull(closedWorld.abstractValueDomain) &&
@@ -942,7 +942,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HBitAnd(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -958,11 +958,11 @@
     return constantSystem.bitXor;
   }
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isUInt31(closedWorld.abstractValueDomain) &&
@@ -977,7 +977,7 @@
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     return new HBitXor(
         instruction.inputs[1],
         instruction.inputs[2],
@@ -989,11 +989,11 @@
 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
   const RelationalSpecializer();
 
-  TypeMask computeTypeFromInputTypes(
+  AbstractValue computeTypeFromInputTypes(
       HInvokeDynamic instruction,
       GlobalTypeInferenceResults results,
       CompilerOptions options,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     if (instruction.inputs[1]
         .isPrimitiveOrNull(closedWorld.abstractValueDomain)) {
       return closedWorld.abstractValueDomain.boolType;
@@ -1008,7 +1008,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber(closedWorld.abstractValueDomain) &&
@@ -1019,7 +1019,7 @@
   }
 
   HInstruction newBuiltinVariant(
-      HInvokeDynamic instruction, ClosedWorld closedWorld);
+      HInvokeDynamic instruction, JClosedWorld closedWorld);
 }
 
 class EqualsSpecializer extends RelationalSpecializer {
@@ -1031,10 +1031,10 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
-    TypeMask instructionType = left.instructionType;
+    AbstractValue instructionType = left.instructionType;
     if (right.isConstantNull() ||
         left.isPrimitiveOrNull(closedWorld.abstractValueDomain)) {
       return newBuiltinVariant(instruction, closedWorld);
@@ -1060,7 +1060,7 @@
   }
 
   HInstruction newBuiltinVariant(
-      HInvokeDynamic instruction, ClosedWorld closedWorld) {
+      HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HIdentity(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
@@ -1074,7 +1074,7 @@
   }
 
   HInstruction newBuiltinVariant(
-      HInvokeDynamic instruction, ClosedWorld closedWorld) {
+      HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HLess(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
@@ -1088,7 +1088,7 @@
   }
 
   HInstruction newBuiltinVariant(
-      HInvokeDynamic instruction, ClosedWorld closedWorld) {
+      HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HGreater(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
@@ -1102,7 +1102,7 @@
   }
 
   HInstruction newBuiltinVariant(
-      HInvokeDynamic instruction, ClosedWorld closedWorld) {
+      HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
@@ -1116,7 +1116,7 @@
   }
 
   HInstruction newBuiltinVariant(
-      HInvokeDynamic instruction, ClosedWorld closedWorld) {
+      HInvokeDynamic instruction, JClosedWorld closedWorld) {
     return new HLessEqual(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
@@ -1135,7 +1135,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index
     // bounds checking optimizations as for HIndex.
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
@@ -1163,7 +1163,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     // `compareTo` has no side-effect (other than throwing) and can be GVN'ed
     // for some known types.
@@ -1195,7 +1195,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     if (receiver.isStringOrNull(closedWorld.abstractValueDomain)) {
       // String.xxx does not have any side effect (other than throwing), and it
@@ -1223,7 +1223,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     HInstruction pattern = instruction.inputs[2];
     if (receiver.isStringOrNull(closedWorld.abstractValueDomain) &&
@@ -1249,7 +1249,7 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       CommonElements commonElements,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     if (receiver.isNumberOrNull(closedWorld.abstractValueDomain)) {
       // Even if there is no builtin equivalent instruction, we know the
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 8e731b7..950aa78 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -510,7 +510,7 @@
     List<DartType> typeArguments = _visitArguments(node.arguments);
     // TODO(johnniwinther): Restrict the dynamic use to only match the known
     // target.
-    ReceiverConstraint constraint;
+    Object constraint;
     MemberEntity member = elementMap.getMember(node.target);
     if (_options.strongMode && useStrongModeWorldStrategy) {
       // TODO(johnniwinther): Restrict this to subclasses?
@@ -610,7 +610,7 @@
       }
     } else {
       visitNode(node.receiver);
-      ReceiverConstraint constraint;
+      Object constraint;
       if (_options.strongMode && useStrongModeWorldStrategy) {
         DartType receiverType = elementMap.getStaticType(node.receiver);
         if (receiverType is InterfaceType) {
@@ -626,7 +626,7 @@
   @override
   void visitPropertyGet(ir.PropertyGet node) {
     visitNode(node.receiver);
-    ReceiverConstraint constraint;
+    Object constraint;
     if (_options.strongMode && useStrongModeWorldStrategy) {
       DartType receiverType = elementMap.getStaticType(node.receiver);
       if (receiverType is InterfaceType) {
@@ -642,7 +642,7 @@
   void visitPropertySet(ir.PropertySet node) {
     visitNode(node.receiver);
     visitNode(node.value);
-    ReceiverConstraint constraint;
+    Object constraint;
     if (_options.strongMode && useStrongModeWorldStrategy) {
       DartType receiverType = elementMap.getStaticType(node.receiver);
       if (receiverType is InterfaceType) {
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index bf5b34b..f0a914c 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -12,9 +12,8 @@
 import '../js_model/closure.dart' show JRecordField, JClosureField;
 import '../js_model/locals.dart' show JLocal;
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../types/types.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'graph_builder.dart';
 import 'nodes.dart';
@@ -66,7 +65,7 @@
   LocalsHandler(this.builder, this.executableContext, this.memberContext,
       this.instanceType, this._nativeData, this._interceptorData);
 
-  ClosedWorld get closedWorld => builder.closedWorld;
+  JClosedWorld get closedWorld => builder.closedWorld;
 
   AbstractValueDomain get _abstractValueDomain =>
       closedWorld.abstractValueDomain;
@@ -196,12 +195,12 @@
       MemberEntity element,
       ScopeInfo scopeInfo,
       CapturedScope scopeData,
-      Map<Local, TypeMask> parameters,
+      Map<Local, AbstractValue> parameters,
       SourceInformation sourceInformation,
       {bool isGenerativeConstructorBody}) {
     this.scopeInfo = scopeInfo;
 
-    parameters.forEach((Local local, TypeMask typeMask) {
+    parameters.forEach((Local local, AbstractValue typeMask) {
       if (isGenerativeConstructorBody) {
         if (scopeData.isBoxed(local)) {
           // The parameter will be a field in the box passed as the
@@ -275,8 +274,8 @@
       SyntheticLocal parameter = createLocal('receiver');
       // Unlike `this`, receiver is nullable since direct calls to generative
       // constructor call the constructor with `null`.
-      HParameterValue value =
-          new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld));
+      HParameterValue value = new HParameterValue(
+          parameter, closedWorld.abstractValueDomain.createNullableExact(cls));
       builder.graph.explicitReceiverParameter = value;
       builder.graph.entry.addAtEntry(value);
       if (builder.lastAddedParameter == null) {
@@ -341,7 +340,7 @@
       ClosureRepresentationInfo closureData = scopeInfo;
       FieldEntity redirect = redirectionMapping[local];
       HInstruction receiver = readLocal(closureData.closureEntity);
-      TypeMask type = local is BoxLocal
+      AbstractValue type = local is BoxLocal
           ? _abstractValueDomain.nonNullType
           : getTypeOfCapturedVariable(redirect);
       HInstruction fieldGet = new HFieldGet(redirect, receiver, type);
@@ -643,10 +642,10 @@
     return this;
   }
 
-  TypeMask cachedTypeOfThis;
+  AbstractValue cachedTypeOfThis;
 
-  TypeMask getTypeOfThis() {
-    TypeMask result = cachedTypeOfThis;
+  AbstractValue getTypeOfThis() {
+    AbstractValue result = cachedTypeOfThis;
     if (result == null) {
       ThisLocal local = scopeInfo.thisLocal;
       ClassEntity cls = local.enclosingClass;
@@ -655,21 +654,21 @@
         // of the class that mixins the enclosing class. These two
         // classes do not have a subclass relationship, so, for
         // simplicity, we mark the type as an interface type.
-        result = new TypeMask.nonNullSubtype(cls, closedWorld);
+        result = _abstractValueDomain.createNonNullSubtype(cls);
       } else {
-        result = new TypeMask.nonNullSubclass(cls, closedWorld);
+        result = _abstractValueDomain.createNonNullSubclass(cls);
       }
       cachedTypeOfThis = result;
     }
     return result;
   }
 
-  Map<FieldEntity, TypeMask> cachedTypesOfCapturedVariables =
-      new Map<FieldEntity, TypeMask>();
+  Map<FieldEntity, AbstractValue> cachedTypesOfCapturedVariables =
+      new Map<FieldEntity, AbstractValue>();
 
-  TypeMask getTypeOfCapturedVariable(FieldEntity element) {
+  AbstractValue getTypeOfCapturedVariable(FieldEntity element) {
     return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
-      return TypeMaskFactory.inferredTypeForMember(
+      return AbstractValueFactory.inferredTypeForMember(
           element, _globalInferenceResults);
     });
   }
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index cb3258d..59ac3b2 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -18,11 +18,10 @@
 import '../js_backend/js_backend.dart';
 import '../native/native.dart' as native;
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart' show TypeMask;
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'invoke_dynamic_specializers.dart';
 import 'validate.dart';
 
@@ -263,7 +262,7 @@
     return result;
   }
 
-  HConstant addConstant(ConstantValue constant, ClosedWorld closedWorld,
+  HConstant addConstant(ConstantValue constant, JClosedWorld closedWorld,
       {SourceInformation sourceInformation}) {
     HConstant result = constants[constant];
     // TODO(johnniwinther): Support source information per constant reference.
@@ -290,44 +289,44 @@
       OutputUnit unit,
       SourceInformation sourceInformation,
       Compiler compiler,
-      ClosedWorld closedWorld) {
+      JClosedWorld closedWorld) {
     ConstantValue wrapper = new DeferredGlobalConstantValue(constant, unit);
     compiler.backend.outputUnitData.registerConstantDeferredUse(wrapper, unit);
     return addConstant(wrapper, closedWorld,
         sourceInformation: sourceInformation);
   }
 
-  HConstant addConstantInt(int i, ClosedWorld closedWorld) {
+  HConstant addConstantInt(int i, JClosedWorld closedWorld) {
     return addConstant(
         closedWorld.constantSystem.createIntFromInt(i), closedWorld);
   }
 
-  HConstant addConstantDouble(double d, ClosedWorld closedWorld) {
+  HConstant addConstantDouble(double d, JClosedWorld closedWorld) {
     return addConstant(closedWorld.constantSystem.createDouble(d), closedWorld);
   }
 
-  HConstant addConstantString(String str, ClosedWorld closedWorld) {
+  HConstant addConstantString(String str, JClosedWorld closedWorld) {
     return addConstant(
         closedWorld.constantSystem.createString(str), closedWorld);
   }
 
-  HConstant addConstantStringFromName(js.Name name, ClosedWorld closedWorld) {
+  HConstant addConstantStringFromName(js.Name name, JClosedWorld closedWorld) {
     return addConstant(
         new SyntheticConstantValue(
             SyntheticConstantKind.NAME, js.quoteName(name)),
         closedWorld);
   }
 
-  HConstant addConstantBool(bool value, ClosedWorld closedWorld) {
+  HConstant addConstantBool(bool value, JClosedWorld closedWorld) {
     return addConstant(
         closedWorld.constantSystem.createBool(value), closedWorld);
   }
 
-  HConstant addConstantNull(ClosedWorld closedWorld) {
+  HConstant addConstantNull(JClosedWorld closedWorld) {
     return addConstant(closedWorld.constantSystem.createNull(), closedWorld);
   }
 
-  HConstant addConstantUnreachable(ClosedWorld closedWorld) {
+  HConstant addConstantUnreachable(JClosedWorld closedWorld) {
     // A constant with an empty type used as the HInstruction of an expression
     // in an unreachable context.
     return addConstant(
@@ -1011,9 +1010,8 @@
   /// Does this node potentially affect control flow.
   bool isControlFlow() => false;
 
-  bool isExact(AbstractValueDomain domain) => domain.isExact(instructionType);
-
-  bool isValue(AbstractValueDomain domain) => domain.isValue(instructionType);
+  bool isValue(AbstractValueDomain domain) =>
+      domain.isPrimitiveValue(instructionType);
 
   bool canBeNull(AbstractValueDomain domain) =>
       domain.canBeNull(instructionType);
@@ -1104,7 +1102,7 @@
   AbstractValue instructionType;
 
   Selector get selector => null;
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => null;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => null;
   bool onlyThrowsNSM() => false;
 
   bool isInBasicBlock() => block != null;
@@ -1236,7 +1234,7 @@
   bool isConstantFalse() => false;
   bool isConstantTrue() => false;
 
-  bool isInterceptor(ClosedWorld closedWorld) => false;
+  bool isInterceptor(JClosedWorld closedWorld) => false;
 
   bool isValid() {
     HValidator validator = new HValidator();
@@ -1262,7 +1260,7 @@
     return false;
   }
 
-  HInstruction convertType(ClosedWorld closedWorld, DartType type, int kind) {
+  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
     if (type == null) return this;
     type = type.unaliased;
     // Only the builder knows how to create [HTypeConversion]
@@ -1445,7 +1443,7 @@
   HInstruction get value => inputs[0];
 
   @override
-  HInstruction convertType(ClosedWorld closedWorld, DartType type, int kind) {
+  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
     HInstruction converted = value.convertType(closedWorld, type, kind);
     if (converted == value) return this;
     HTypeConversion conversion = converted;
@@ -1630,7 +1628,7 @@
   }
   toString() => 'invoke dynamic: selector=$selector, mask=$mask';
   HInstruction get receiver => inputs[0];
-  HInstruction getDartReceiver(ClosedWorld closedWorld) {
+  HInstruction getDartReceiver(JClosedWorld closedWorld) {
     return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
   }
 
@@ -1640,7 +1638,7 @@
   /**
    * Returns whether this call is on an interceptor object.
    */
-  bool isCallOnInterceptor(ClosedWorld closedWorld) {
+  bool isCallOnInterceptor(JClosedWorld closedWorld) {
     return isInterceptedCall && receiver.isInterceptor(closedWorld);
   }
 
@@ -1799,14 +1797,14 @@
   }
 
   HInstruction get receiver => inputs[0];
-  HInstruction getDartReceiver(ClosedWorld closedWorld) {
+  HInstruction getDartReceiver(JClosedWorld closedWorld) {
     return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
   }
 
   /**
    * Returns whether this call is on an interceptor object.
    */
-  bool isCallOnInterceptor(ClosedWorld closedWorld) {
+  bool isCallOnInterceptor(JClosedWorld closedWorld) {
     return isInterceptedCall && receiver.isInterceptor(closedWorld);
   }
 
@@ -1881,7 +1879,7 @@
     }
   }
 
-  bool isInterceptor(ClosedWorld closedWorld) {
+  bool isInterceptor(JClosedWorld closedWorld) {
     if (sourceElement == null) return false;
     // In case of a closure inside an interceptor class, [:this:] is
     // stored in the generated closure class, and accessed through a
@@ -1896,7 +1894,7 @@
 
   bool canThrow(AbstractValueDomain domain) => receiver.canBeNull(domain);
 
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => receiver;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
   bool onlyThrowsNSM() => true;
   bool get isNullCheck => element == null;
 
@@ -1919,7 +1917,7 @@
 
   bool canThrow(AbstractValueDomain domain) => receiver.canBeNull(domain);
 
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => receiver;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
   bool onlyThrowsNSM() => true;
 
   HInstruction get value => inputs[1];
@@ -1947,7 +1945,7 @@
 
   bool canThrow(AbstractValueDomain domain) => receiver.canBeNull(domain);
 
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => receiver;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
   bool onlyThrowsNSM() => true;
 
   accept(HVisitor visitor) => visitor.visitGetLength(this);
@@ -2000,7 +1998,7 @@
 
   bool canThrow(AbstractValueDomain domain) => receiver.canBeNull(domain);
 
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => receiver;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
   bool onlyThrowsNSM() => true;
 
   HInstruction get value => inputs[1];
@@ -2512,7 +2510,7 @@
   bool isConstantFalse() => constant.isFalse;
   bool isConstantTrue() => constant.isTrue;
 
-  bool isInterceptor(ClosedWorld closedWorld) => constant.isInterceptor;
+  bool isInterceptor(JClosedWorld closedWorld) => constant.isInterceptor;
 
   // Maybe avoid this if the literal is big?
   bool isCodeMotionInvariant() => true;
@@ -2583,7 +2581,7 @@
 
   bool isCodeMotionInvariant() => true;
 
-  bool isInterceptor(ClosedWorld closedWorld) {
+  bool isInterceptor(JClosedWorld closedWorld) {
     return closedWorld.interceptorData
         .isInterceptedClass(sourceElement.enclosingClass);
   }
@@ -2799,7 +2797,7 @@
     inputs.add(constant);
   }
 
-  bool isInterceptor(ClosedWorld closedWorld) => true;
+  bool isInterceptor(JClosedWorld closedWorld) => true;
 
   int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
   bool typeEquals(other) => other is HInterceptor;
@@ -2835,7 +2833,7 @@
     assert(inputs[0].isNull(domain));
     assert(selector.callStructure.typeArgumentCount == typeArguments.length);
   }
-  bool isCallOnInterceptor(ClosedWorld closedWorld) => true;
+  bool isCallOnInterceptor(JClosedWorld closedWorld) => true;
 
   String toString() => 'one shot interceptor: selector=$selector, mask=$mask';
   accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
@@ -2915,7 +2913,7 @@
   // TODO(27272): Make HIndex dependent on bounds checking.
   bool get isMovable => false;
 
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => receiver;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
   bool onlyThrowsNSM() => true;
   bool canThrow(AbstractValueDomain domain) => receiver.canBeNull(domain);
 
@@ -2948,7 +2946,7 @@
   // TODO(27272): Make HIndex dependent on bounds checking.
   bool get isMovable => false;
 
-  HInstruction getDartReceiver(ClosedWorld closedWorld) => receiver;
+  HInstruction getDartReceiver(JClosedWorld closedWorld) => receiver;
   bool onlyThrowsNSM() => true;
   bool canThrow(AbstractValueDomain domain) => receiver.canBeNull(domain);
 }
@@ -3136,7 +3134,7 @@
 
   HInstruction get checkedInput => super.checkedInput;
 
-  HInstruction convertType(ClosedWorld closedWorld, DartType type, int kind) {
+  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
     if (typeExpression == type) {
       // Don't omit a boolean conversion (which doesn't allow `null`) unless
       // this type conversion is already a boolean conversion.
@@ -3172,7 +3170,7 @@
         receiverTypeCheckSelector == other.receiverTypeCheckSelector;
   }
 
-  bool isRedundant(ClosedWorld closedWorld) {
+  bool isRedundant(JClosedWorld closedWorld) {
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
     DartType type = typeExpression;
     if (type != null) {
@@ -3204,8 +3202,8 @@
     }
     // Type is refined from `dynamic`, so it might become non-redundant.
     if (abstractValueDomain.containsAll(checkedType)) return false;
-    TypeMask inputType = checkedInput.instructionType;
-    return inputType.isInMask(checkedType, closedWorld);
+    AbstractValue inputType = checkedInput.instructionType;
+    return abstractValueDomain.isIn(inputType, checkedType);
   }
 
   String toString() => 'HTypeConversion(type=$typeExpression, kind=$kind, '
@@ -3250,11 +3248,11 @@
         instructionType == other.instructionType;
   }
 
-  bool isRedundant(ClosedWorld closedWorld) {
+  bool isRedundant(JClosedWorld closedWorld) {
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
     if (abstractValueDomain.containsAll(knownType)) return false;
-    TypeMask inputType = checkedInput.instructionType;
-    return inputType.isInMask(knownType, closedWorld);
+    AbstractValue inputType = checkedInput.instructionType;
+    return abstractValueDomain.isIn(inputType, knownType);
   }
 }
 
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 0b25f85..f8313e8 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -18,13 +18,12 @@
 import '../native/native.dart' as native;
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../universe/use.dart' show StaticUse;
 import '../util/util.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'interceptor_simplifier.dart';
 import 'nodes.dart';
 import 'types.dart';
@@ -54,7 +53,7 @@
 
   RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions;
 
-  void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
+  void optimize(CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
     void runPhase(OptimizationPhase phase) {
       measureSubtask(phase.name, () => phase.visitGraph(graph));
       _backend.tracer.traceGraph(phase.name, graph);
@@ -156,7 +155,7 @@
 /// cannot change.  The current implementation is conservative for the purpose
 /// of identifying gvn-able lengths and mis-identifies some unions of fixed
 /// length indexables (see TODO) as not fixed length.
-bool isFixedLength(mask, ClosedWorld closedWorld) {
+bool isFixedLength(mask, JClosedWorld closedWorld) {
   if (mask.isContainer && mask.length != null) {
     // A container on which we have inferred the length.
     return true;
@@ -186,7 +185,7 @@
   final GlobalTypeInferenceResults _globalInferenceResults;
   final CompilerOptions _options;
   final RuntimeTypesSubstitutions _rtiSubstitutions;
-  final ClosedWorld _closedWorld;
+  final JClosedWorld _closedWorld;
   final CodegenRegistry _registry;
   HGraph _graph;
 
@@ -224,7 +223,7 @@
             instruction.isNumberOrNull(_abstractValueDomain))) {
           // If we can replace [instruction] with [replacement], then
           // [replacement]'s type can be narrowed.
-          TypeMask newType = _abstractValueDomain.intersection(
+          AbstractValue newType = _abstractValueDomain.intersection(
               replacement.instructionType, instruction.instructionType);
           replacement.instructionType = newType;
         }
@@ -256,9 +255,10 @@
   ConstantValue getConstantFromType(HInstruction node) {
     if (node.isValue(_abstractValueDomain) &&
         !node.canBeNull(_abstractValueDomain)) {
-      ValueTypeMask valueMask = node.instructionType;
-      if (valueMask.value.isBool) {
-        return valueMask.value;
+      ConstantValue value =
+          _abstractValueDomain.getPrimitiveValue(node.instructionType);
+      if (value.isBool) {
+        return value;
       }
       // TODO(het): consider supporting other values (short strings?)
     }
@@ -314,8 +314,8 @@
     if (_abstractValueDomain.isEmpty(input.instructionType)) return input;
 
     // All values that cannot be 'true' are boolified to false.
-    TypeMask mask = input.instructionType;
-    if (!mask.contains(commonElements.jsBoolClass, _closedWorld)) {
+    AbstractValue mask = input.instructionType;
+    if (!_abstractValueDomain.containsType(mask, commonElements.jsBoolClass)) {
       return _graph.addConstantBool(false, _closedWorld);
     }
     return node;
@@ -364,13 +364,13 @@
       }
       bool isFixed =
           isFixedLength(actualReceiver.instructionType, _closedWorld);
-      TypeMask actualType = node.instructionType;
-      TypeMask resultType = _abstractValueDomain.positiveIntType;
+      AbstractValue actualType = node.instructionType;
+      AbstractValue resultType = _abstractValueDomain.positiveIntType;
       // If we already have computed a more specific type, keep that type.
-      if (_abstractValueDomain.isInstanceOf(
+      if (_abstractValueDomain.isInstanceOfOrNull(
           actualType, commonElements.jsUInt31Class)) {
         resultType = _abstractValueDomain.uint31Type;
-      } else if (_abstractValueDomain.isInstanceOf(
+      } else if (_abstractValueDomain.isInstanceOfOrNull(
           actualType, commonElements.jsUInt32Class)) {
         resultType = _abstractValueDomain.uint32Type;
       }
@@ -406,12 +406,13 @@
     if (instruction != null) return instruction;
 
     Selector selector = node.selector;
-    TypeMask mask = node.mask;
+    AbstractValue mask = node.mask;
     HInstruction input = node.inputs[1];
 
     bool applies(MemberEntity element) {
       return selector.applies(element) &&
-          (mask == null || mask.canHit(element, selector, _closedWorld));
+          (mask == null ||
+              _abstractValueDomain.canHit(mask, element, selector));
     }
 
     if (selector.isCall || selector.isOperator) {
@@ -428,7 +429,7 @@
         }
       } else if (input.isStringOrNull(_abstractValueDomain)) {
         if (commonElements.appliesToJsStringSplit(
-            selector, mask, _closedWorld)) {
+            selector, mask, _abstractValueDomain)) {
           return handleStringSplit(node);
         } else if (applies(commonElements.jsStringOperatorAdd)) {
           // `operator+` is turned into a JavaScript '+' so we need to
@@ -486,7 +487,7 @@
     //     t4 = setRuntimeTypeInfo(t1, t3);
     //
 
-    TypeMask resultMask = _abstractValueDomain.growableListType;
+    AbstractValue resultMask = _abstractValueDomain.growableListType;
 
     HInvokeDynamicMethod splitInstruction = new HInvokeDynamicMethod(
         node.selector,
@@ -541,7 +542,8 @@
       if (folded != node) return folded;
     }
 
-    TypeMask receiverType = node.getDartReceiver(_closedWorld).instructionType;
+    AbstractValue receiverType =
+        node.getDartReceiver(_closedWorld).instructionType;
     MemberEntity element =
         _closedWorld.locateSingleMember(node.selector, receiverType);
     // TODO(ngeoffray): Also fold if it's a getter or variable.
@@ -579,7 +581,7 @@
       if (!_nativeData.isNativeMember(field) &&
           !node.isCallOnInterceptor(_closedWorld)) {
         HInstruction receiver = node.getDartReceiver(_closedWorld);
-        TypeMask type = TypeMaskFactory.inferredTypeForMember(
+        AbstractValue type = AbstractValueFactory.inferredTypeForMember(
             // ignore: UNNECESSARY_CAST
             field as Entity,
             _globalInferenceResults);
@@ -651,8 +653,8 @@
     // dependent instructions.
     native.NativeBehavior nativeBehavior =
         _nativeData.getNativeMethodBehavior(method);
-    TypeMask returnType =
-        TypeMaskFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
+    AbstractValue returnType =
+        AbstractValueFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
     HInvokeDynamicMethod result = new HInvokeDynamicMethod(
         node.selector,
         node.mask,
@@ -745,8 +747,8 @@
   HInstruction handleIdentityCheck(HRelational node) {
     HInstruction left = node.left;
     HInstruction right = node.right;
-    TypeMask leftType = left.instructionType;
-    TypeMask rightType = right.instructionType;
+    AbstractValue leftType = left.instructionType;
+    AbstractValue rightType = right.instructionType;
 
     HInstruction makeTrue() => _graph.addConstantBool(true, _closedWorld);
     HInstruction makeFalse() => _graph.addConstantBool(false, _closedWorld);
@@ -755,7 +757,7 @@
     // we don't optimize on numbers to preserve the runtime semantics.
     if (!(left.isNumberOrNull(_abstractValueDomain) &&
         right.isNumberOrNull(_abstractValueDomain))) {
-      if (leftType.isDisjoint(rightType, _closedWorld)) {
+      if (_abstractValueDomain.areDisjoint(leftType, rightType)) {
         return makeFalse();
       }
     }
@@ -910,14 +912,12 @@
       // a class [:A<T>:], is currently always considered to have the
       // raw type.
     } else if (!RuntimeTypesSubstitutions.hasTypeArguments(type)) {
-      TypeMask expressionMask = expression.instructionType;
-      assert(TypeMask.assertIsNormalized(expressionMask, _closedWorld));
-      TypeMask typeMask = (element == commonElements.nullClass)
-          ? new TypeMask.subtype(element, _closedWorld)
-          : new TypeMask.nonNullSubtype(element, _closedWorld);
-      if (expressionMask.union(typeMask, _closedWorld) == typeMask) {
+      AbstractValue expressionMask = expression.instructionType;
+      AbstractBool isInstanceOf =
+          _abstractValueDomain.isInstanceOf(expressionMask, element);
+      if (isInstanceOf == AbstractBool.True) {
         return _graph.addConstantBool(true, _closedWorld);
-      } else if (expressionMask.isDisjoint(typeMask, _closedWorld)) {
+      } else if (isInstanceOf == AbstractBool.False) {
         return _graph.addConstantBool(false, _closedWorld);
       }
     }
@@ -934,7 +934,7 @@
 
   FieldEntity findConcreteFieldForDynamicAccess(
       HInstruction receiver, Selector selector) {
-    TypeMask receiverType = receiver.instructionType;
+    AbstractValue receiverType = receiver.instructionType;
     return _closedWorld.locateSingleField(selector, receiverType);
   }
 
@@ -1043,12 +1043,12 @@
   HInstruction directFieldGet(HInstruction receiver, FieldEntity field) {
     bool isAssignable = !_closedWorld.fieldNeverChanges(field);
 
-    TypeMask type;
+    AbstractValue type;
     if (_nativeData.isNativeClass(field.enclosingClass)) {
-      type = TypeMaskFactory.fromNativeBehavior(
+      type = AbstractValueFactory.fromNativeBehavior(
           _nativeData.getNativeFieldLoadBehavior(field), _closedWorld);
     } else {
-      type = TypeMaskFactory.inferredTypeForMember(
+      type = AbstractValueFactory.inferredTypeForMember(
           // ignore: UNNECESSARY_CAST
           field as Entity,
           _globalInferenceResults);
@@ -1274,14 +1274,15 @@
       if (input.canBePrimitive(_abstractValueDomain)) return null;
       if (input.canBeNull(_abstractValueDomain)) return null;
       Selector selector = Selectors.toString_;
-      TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector(
+      AbstractValue toStringType = AbstractValueFactory.inferredTypeForSelector(
           selector, input.instructionType, _globalInferenceResults);
-      if (!toStringType.containsOnlyString(_closedWorld)) return null;
+      if (!_abstractValueDomain.containsOnlyType(
+          toStringType, _closedWorld.commonElements.jsStringClass)) {
+        return null;
+      }
       // All intercepted classes extend `Interceptor`, so if the receiver can't
       // be a class extending `Interceptor` then it can be called directly.
-      if (new TypeMask.nonNullSubclass(
-              commonElements.jsInterceptorClass, _closedWorld)
-          .isDisjoint(input.instructionType, _closedWorld)) {
+      if (!_abstractValueDomain.canBeInterceptor(input.instructionType)) {
         var inputs = <HInstruction>[input, input]; // [interceptor, receiver].
         HInstruction result = new HInvokeDynamicMethod(
             selector,
@@ -1488,9 +1489,7 @@
       // be a class extending `Interceptor` then the substitution methods can be
       // called directly. (We don't care about Null since contexts reading class
       // type variables originate from instance methods.)
-      if (new TypeMask.nonNullSubclass(
-              commonElements.jsInterceptorClass, _closedWorld)
-          .isDisjoint(object.instructionType, _closedWorld)) {
+      if (!_abstractValueDomain.canBeInterceptor(object.instructionType)) {
         return new HTypeInfoReadVariable.noInterceptor(
             variable, object, node.instructionType);
       }
@@ -1503,7 +1502,7 @@
 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
   final Set<HInstruction> boundsChecked;
   final bool trustPrimitives;
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final String name = "SsaCheckInserter";
   HGraph graph;
 
@@ -1539,7 +1538,7 @@
         isAssignable: !isFixedLength(array.instructionType, closedWorld));
     indexNode.block.addBefore(indexNode, length);
 
-    TypeMask type = indexArgument.isPositiveInteger(_abstractValueDomain)
+    AbstractValue type = indexArgument.isPositiveInteger(_abstractValueDomain)
         ? indexArgument.instructionType
         : closedWorld.abstractValueDomain.positiveIntType;
     HBoundsCheck check = new HBoundsCheck(indexArgument, length, array, type)
@@ -1589,7 +1588,7 @@
 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
   final String name = "SsaDeadCodeEliminator";
 
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final SsaOptimizerTask optimizer;
   HGraph _graph;
   SsaLiveBlockAnalyzer analyzer;
@@ -1607,7 +1606,7 @@
     if (zapInstructionCache == null) {
       // A constant with no type does not pollute types at phi nodes.
       ConstantValue constant = new SyntheticConstantValue(
-          SyntheticConstantKind.EMPTY_VALUE, const TypeMask.nonNullEmpty());
+          SyntheticConstantKind.EMPTY_VALUE, _abstractValueDomain.emptyType);
       zapInstructionCache = analyzer.graph.addConstant(constant, closedWorld);
     }
     return zapInstructionCache;
@@ -1935,7 +1934,7 @@
   final Set<HBasicBlock> live = new Set<HBasicBlock>();
   final List<HBasicBlock> worklist = <HBasicBlock>[];
   final SsaOptimizerTask optimizer;
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
 
   SsaLiveBlockAnalyzer(this.graph, this.closedWorld, this.optimizer);
 
@@ -2443,7 +2442,7 @@
 class SsaTypeConversionInserter extends HBaseVisitor
     implements OptimizationPhase {
   final String name = "SsaTypeconversionInserter";
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
 
   SsaTypeConversionInserter(this.closedWorld);
 
@@ -2459,7 +2458,7 @@
   // on the control flow, we mark the inserted [HTypeKnown] nodes as
   // non-movable.
   void insertTypePropagationForDominatedUsers(
-      HBasicBlock dominator, HInstruction input, TypeMask convertedType) {
+      HBasicBlock dominator, HInstruction input, AbstractValue convertedType) {
     DominatedUses dominatedUses = DominatedUses.of(input, dominator.first);
     if (dominatedUses.isEmpty) return;
 
@@ -2498,7 +2497,8 @@
 
     if (trueTargets.isEmpty && falseTargets.isEmpty) return;
 
-    TypeMask convertedType = new TypeMask.nonNullSubtype(cls, closedWorld);
+    AbstractValue convertedType =
+        _abstractValueDomain.createNonNullSubtype(cls);
     HInstruction input = instruction.expression;
 
     for (HBasicBlock block in trueTargets) {
@@ -2531,7 +2531,7 @@
 
     if (trueTargets.isEmpty && falseTargets.isEmpty) return;
 
-    TypeMask nonNullType =
+    AbstractValue nonNullType =
         _abstractValueDomain.excludeNull(input.instructionType);
 
     for (HBasicBlock block in falseTargets) {
@@ -2585,7 +2585,7 @@
  */
 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
   final Compiler compiler;
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final String name = "SsaLoadElimination";
   MemorySet memorySet;
   List<MemorySet> memories;
@@ -2843,7 +2843,7 @@
 /// confuse aliasing.  Values stored into a memory place keep the type
 /// refinements to help further optimizations.
 class MemorySet {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
 
   /// Maps a field to a map of receivers to their current field values.
   ///
@@ -3083,7 +3083,7 @@
         }
       }
     }
-    TypeMask phiType = _abstractValueDomain.union(
+    AbstractValue phiType = _abstractValueDomain.union(
         second.instructionType, first.instructionType);
     if (first is HPhi && first.block == block) {
       HPhi phi = first;
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index f757a85..c006997 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -13,7 +13,7 @@
 import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
 import '../universe/call_structure.dart';
 import '../universe/use.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
 import 'codegen.dart';
 import 'nodes.dart';
@@ -38,7 +38,7 @@
 
   /// Generates JavaScript code for `work.element`.
   /// Using the ssa builder, optimizer and codegenerator.
-  js.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld) {
+  js.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld) {
     HGraph graph = _builder.build(work, closedWorld);
     if (graph == null) return null;
     optimizer.optimize(work, graph, closedWorld);
@@ -68,7 +68,7 @@
 abstract class SsaBuilder {
   /// Creates the [HGraph] for [work] or returns `null` if no code is needed
   /// for [work].
-  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld);
+  HGraph build(CodegenWorkItem work, JClosedWorld closedWorld);
 }
 
 class SsaBuilderTask extends CompilerTask {
@@ -88,7 +88,7 @@
 
   /// Creates the [HGraph] for [work] or returns `null` if no code is needed
   /// for [work].
-  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
+  HGraph build(CodegenWorkItem work, JClosedWorld closedWorld) {
     return _builder.build(work, closedWorld);
   }
 }
@@ -105,8 +105,8 @@
   ///
   /// If the field is constant, no code is needed for the field and the method
   /// returns `true`.
-  bool handleConstantField(
-      MemberEntity element, CodegenRegistry registry, ClosedWorld closedWorld) {
+  bool handleConstantField(MemberEntity element, CodegenRegistry registry,
+      JClosedWorld closedWorld) {
     if (element.isField) {
       ConstantValue initialValue = getFieldInitialConstantValue(element);
       if (initialValue != null) {
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 413c044..f72cc6b 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -9,7 +9,7 @@
 import '../js_backend/namer.dart' show Namer;
 import '../types/abstract_value_domain.dart';
 import '../tracer.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
 
 /**
@@ -18,7 +18,7 @@
  * to enable it.
  */
 class HTracer extends HGraphVisitor with TracerUtil {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final Namer namer;
   final OutputSink output;
 
@@ -113,7 +113,7 @@
 }
 
 class HInstructionStringifier implements HVisitor<String> {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final Namer namer;
   final HBasicBlock currentBlock;
 
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 6e4c5bb..95cb53e 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -7,7 +7,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../io/source_information.dart';
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../universe/use.dart' show TypeUse;
 
 /// Enum that defines how a member has access to the current type variables.
@@ -40,7 +40,7 @@
 
   /// Create a type mask for 'trusting' a DartType. Returns `null` if there is
   /// no approximating type mask (i.e. the type mask would be `dynamic`).
-  TypeMask trustTypeMask(DartType type) {
+  AbstractValue trustTypeMask(DartType type) {
     if (type == null) return null;
     type = builder.localsHandler.substInContext(type);
     type = type.unaliased;
@@ -49,13 +49,13 @@
     if (type == builder.commonElements.objectType) return null;
     // The type element is either a class or the void element.
     ClassEntity element = (type as InterfaceType).element;
-    return new TypeMask.subtype(element, builder.closedWorld);
+    return builder.abstractValueDomain.createNullableSubtype(element);
   }
 
   /// Create an instruction to simply trust the provided type.
   HInstruction _trustType(HInstruction original, DartType type) {
     assert(type != null);
-    TypeMask mask = trustTypeMask(type);
+    AbstractValue mask = trustTypeMask(type);
     if (mask == null) return original;
     return new HTypeKnown.pinned(mask, original);
   }
@@ -273,8 +273,8 @@
     type = type.unaliased;
     if (type.isInterfaceType && !type.treatAsRaw) {
       InterfaceType interfaceType = type;
-      TypeMask subtype =
-          new TypeMask.subtype(interfaceType.element, builder.closedWorld);
+      AbstractValue subtype = builder.abstractValueDomain
+          .createNullableSubtype(interfaceType.element);
       HInstruction representations = buildTypeArgumentRepresentations(
           type, builder.sourceElement, sourceInformation);
       builder.add(representations);
@@ -282,7 +282,7 @@
           type, kind, subtype, original, representations)
         ..sourceInformation = sourceInformation;
     } else if (type.isTypeVariable) {
-      TypeMask subtype = original.instructionType;
+      AbstractValue subtype = original.instructionType;
       HInstruction typeVariable =
           addTypeVariableReference(type, builder.sourceElement);
       return new HTypeConversion.withTypeRepresentation(
@@ -292,7 +292,7 @@
       HInstruction reifiedType =
           analyzeTypeArgument(type, builder.sourceElement);
       // TypeMasks don't encode function types or FutureOr types.
-      TypeMask refinedMask = original.instructionType;
+      AbstractValue refinedMask = original.instructionType;
       return new HTypeConversion.withTypeRepresentation(
           type, kind, refinedMask, original, reifiedType)
         ..sourceInformation = sourceInformation;
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index 9e938c4..f9b3752 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -5,63 +5,66 @@
 import '../common_elements.dart' show CommonElements;
 import '../elements/entities.dart';
 import '../native/native.dart' as native;
-import '../types/masks.dart';
+import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 
-class TypeMaskFactory {
-  static TypeMask inferredReturnTypeForElement(
+class AbstractValueFactory {
+  static AbstractValue inferredReturnTypeForElement(
       FunctionEntity element, GlobalTypeInferenceResults results) {
     return results.resultOfMember(element).returnType ??
         results.closedWorld.abstractValueDomain.dynamicType;
   }
 
-  static TypeMask inferredTypeForMember(
+  static AbstractValue inferredTypeForMember(
       MemberEntity element, GlobalTypeInferenceResults results) {
     return results.resultOfMember(element).type ??
         results.closedWorld.abstractValueDomain.dynamicType;
   }
 
-  static TypeMask inferredTypeForParameter(
+  static AbstractValue inferredTypeForParameter(
       Local element, GlobalTypeInferenceResults results) {
     return results.resultOfParameter(element).type ??
         results.closedWorld.abstractValueDomain.dynamicType;
   }
 
-  static TypeMask inferredTypeForSelector(
-      Selector selector, TypeMask mask, GlobalTypeInferenceResults results) {
-    return results.typeOfSelector(selector, mask) ??
+  static AbstractValue inferredTypeForSelector(Selector selector,
+      AbstractValue receiver, GlobalTypeInferenceResults results) {
+    return results.typeOfSelector(selector, receiver) ??
         results.closedWorld.abstractValueDomain.dynamicType;
   }
 
-  static TypeMask fromNativeBehavior(
-      native.NativeBehavior nativeBehavior, ClosedWorld closedWorld) {
-    CommonMasks commonMasks = closedWorld.abstractValueDomain;
+  static AbstractValue fromNativeBehavior(
+      native.NativeBehavior nativeBehavior, JClosedWorld closedWorld) {
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
     var typesReturned = nativeBehavior.typesReturned;
-    if (typesReturned.isEmpty) return commonMasks.dynamicType;
+    if (typesReturned.isEmpty) return abstractValueDomain.dynamicType;
 
     CommonElements commonElements = closedWorld.commonElements;
 
     // [type] is either an instance of [DartType] or special objects
     // like [native.SpecialType.JsObject].
-    TypeMask fromNativeType(dynamic type) {
+    AbstractValue fromNativeType(dynamic type) {
       if (type == native.SpecialType.JsObject) {
-        return new TypeMask.nonNullExact(
-            commonElements.objectClass, closedWorld);
+        return abstractValueDomain
+            .createNonNullExact(commonElements.objectClass);
+      } else if (type.isVoid) {
+        return abstractValueDomain.nullType;
+      } else if (type.isDynamic) {
+        return abstractValueDomain.dynamicType;
+      } else if (type == commonElements.nullType) {
+        return abstractValueDomain.nullType;
+      } else if (type.treatAsDynamic) {
+        return abstractValueDomain.dynamicType;
+      } else {
+        return abstractValueDomain.createNonNullSubtype(type.element);
       }
-
-      if (type.isVoid) return commonMasks.nullType;
-      if (type.isDynamic) return commonMasks.dynamicType;
-      if (type.element == commonElements.nullClass) return commonMasks.nullType;
-      if (type.treatAsDynamic) return commonMasks.dynamicType;
-      return new TypeMask.nonNullSubtype(type.element, closedWorld);
     }
 
-    TypeMask result = typesReturned
-        .map(fromNativeType)
-        .reduce((t1, t2) => t1.union(t2, closedWorld));
-    assert(!result.isEmpty);
+    AbstractValue result =
+        abstractValueDomain.unionOfMany(typesReturned.map(fromNativeType));
+    assert(!abstractValueDomain.isEmpty(result));
     return result;
   }
 }
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index d0a0f44..14d25b9 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -6,10 +6,9 @@
 import '../elements/entities.dart';
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
-import '../types/masks.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
@@ -38,7 +37,7 @@
   final GlobalTypeInferenceResults results;
   final CompilerOptions options;
   final CommonElements commonElements;
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   String get name => 'SsaTypePropagator';
 
   SsaTypePropagator(
@@ -47,7 +46,7 @@
   AbstractValueDomain get abstractValueDomain =>
       closedWorld.abstractValueDomain;
 
-  TypeMask computeType(HInstruction instruction) {
+  AbstractValue computeType(HInstruction instruction) {
     return instruction.accept(this);
   }
 
@@ -55,8 +54,8 @@
   // whether or not the type was changed.
   bool updateType(HInstruction instruction) {
     // Compute old and new types.
-    TypeMask oldType = instruction.instructionType;
-    TypeMask newType = computeType(instruction);
+    AbstractValue oldType = instruction.instructionType;
+    AbstractValue newType = computeType(instruction);
     assert(newType != null);
     // We unconditionally replace the propagated type with the new type. The
     // computeType must make sure that we eventually reach a stable state.
@@ -127,109 +126,111 @@
     }
   }
 
-  TypeMask visitBinaryArithmetic(HBinaryArithmetic instruction) {
+  AbstractValue visitBinaryArithmetic(HBinaryArithmetic instruction) {
     HInstruction left = instruction.left;
     HInstruction right = instruction.right;
-    if (left.isInteger(closedWorld.abstractValueDomain) &&
-        right.isInteger(closedWorld.abstractValueDomain)) {
-      return closedWorld.abstractValueDomain.intType;
+    if (left.isInteger(abstractValueDomain) &&
+        right.isInteger(abstractValueDomain)) {
+      return abstractValueDomain.intType;
     }
-    if (left.isDouble(closedWorld.abstractValueDomain)) {
-      return closedWorld.abstractValueDomain.doubleType;
+    if (left.isDouble(abstractValueDomain)) {
+      return abstractValueDomain.doubleType;
     }
-    return closedWorld.abstractValueDomain.numType;
+    return abstractValueDomain.numType;
   }
 
-  TypeMask checkPositiveInteger(HBinaryArithmetic instruction) {
+  AbstractValue checkPositiveInteger(HBinaryArithmetic instruction) {
     HInstruction left = instruction.left;
     HInstruction right = instruction.right;
-    if (left.isPositiveInteger(closedWorld.abstractValueDomain) &&
-        right.isPositiveInteger(closedWorld.abstractValueDomain)) {
-      return closedWorld.abstractValueDomain.positiveIntType;
+    if (left.isPositiveInteger(abstractValueDomain) &&
+        right.isPositiveInteger(abstractValueDomain)) {
+      return abstractValueDomain.positiveIntType;
     }
     return visitBinaryArithmetic(instruction);
   }
 
-  TypeMask visitMultiply(HMultiply instruction) {
+  AbstractValue visitMultiply(HMultiply instruction) {
     return checkPositiveInteger(instruction);
   }
 
-  TypeMask visitAdd(HAdd instruction) {
+  AbstractValue visitAdd(HAdd instruction) {
     return checkPositiveInteger(instruction);
   }
 
-  TypeMask visitDivide(HDivide instruction) {
+  AbstractValue visitDivide(HDivide instruction) {
     // Always double, as initialized.
     return instruction.instructionType;
   }
 
-  TypeMask visitTruncatingDivide(HTruncatingDivide instruction) {
+  AbstractValue visitTruncatingDivide(HTruncatingDivide instruction) {
     // Always as initialized.
     return instruction.instructionType;
   }
 
-  TypeMask visitRemainder(HRemainder instruction) {
+  AbstractValue visitRemainder(HRemainder instruction) {
     // Always as initialized.
     return instruction.instructionType;
   }
 
-  TypeMask visitNegate(HNegate instruction) {
+  AbstractValue visitNegate(HNegate instruction) {
     HInstruction operand = instruction.operand;
     // We have integer subclasses that represent ranges, so widen any int
     // subclass to full integer.
-    if (operand.isInteger(closedWorld.abstractValueDomain)) {
-      return closedWorld.abstractValueDomain.intType;
+    if (operand.isInteger(abstractValueDomain)) {
+      return abstractValueDomain.intType;
     }
     return instruction.operand.instructionType;
   }
 
-  TypeMask visitAbs(HAbs instruction) {
+  AbstractValue visitAbs(HAbs instruction) {
     // TODO(sra): Can narrow to non-negative type for integers.
     return instruction.operand.instructionType;
   }
 
-  TypeMask visitInstruction(HInstruction instruction) {
+  AbstractValue visitInstruction(HInstruction instruction) {
     assert(instruction.instructionType != null);
     return instruction.instructionType;
   }
 
-  TypeMask visitPhi(HPhi phi) {
-    TypeMask candidateType = closedWorld.abstractValueDomain.emptyType;
+  AbstractValue visitPhi(HPhi phi) {
+    AbstractValue candidateType = abstractValueDomain.emptyType;
     for (int i = 0, length = phi.inputs.length; i < length; i++) {
-      TypeMask inputType = phi.inputs[i].instructionType;
-      candidateType = candidateType.union(inputType, closedWorld);
+      AbstractValue inputType = phi.inputs[i].instructionType;
+      candidateType = abstractValueDomain.union(candidateType, inputType);
     }
     return candidateType;
   }
 
-  TypeMask visitTypeConversion(HTypeConversion instruction) {
+  AbstractValue visitTypeConversion(HTypeConversion instruction) {
     HInstruction input = instruction.checkedInput;
-    TypeMask inputType = input.instructionType;
-    TypeMask checkedType = instruction.checkedType;
+    AbstractValue inputType = input.instructionType;
+    AbstractValue checkedType = instruction.checkedType;
     if (instruction.isArgumentTypeCheck || instruction.isReceiverTypeCheck) {
       // We must make sure a type conversion for receiver or argument check
       // does not try to do an int check, because an int check is not enough.
       // We only do an int check if the input is integer or null.
-      if (checkedType.containsOnlyNum(closedWorld) &&
-          !checkedType.containsOnlyDouble(closedWorld) &&
-          input.isIntegerOrNull(closedWorld.abstractValueDomain)) {
-        instruction.checkedType = closedWorld.abstractValueDomain.intType;
-      } else if (checkedType.containsOnlyInt(closedWorld) &&
-          !input.isIntegerOrNull(closedWorld.abstractValueDomain)) {
-        instruction.checkedType = closedWorld.abstractValueDomain.numType;
+      if (abstractValueDomain.isNumberOrNull(checkedType) &&
+          !abstractValueDomain.isDoubleOrNull(checkedType) &&
+          input.isIntegerOrNull(abstractValueDomain)) {
+        instruction.checkedType = abstractValueDomain.intType;
+      } else if (abstractValueDomain.isIntegerOrNull(checkedType) &&
+          !input.isIntegerOrNull(abstractValueDomain)) {
+        instruction.checkedType = abstractValueDomain.numType;
       }
     }
 
-    TypeMask outputType = checkedType.intersection(inputType, closedWorld);
-    if (outputType.isEmpty) {
+    AbstractValue outputType =
+        abstractValueDomain.intersection(checkedType, inputType);
+    if (abstractValueDomain.isEmpty(outputType)) {
       // Intersection of double and integer conflicts (is empty), but JS numbers
       // can be both int and double at the same time.  For example, the input
       // can be a literal double '8.0' that is marked as an integer (because 'is
       // int' will return 'true').  What we really need to do is make the
       // overlap between int and double values explicit in the TypeMask system.
-      if (inputType.containsOnlyInt(closedWorld) &&
-          checkedType.containsOnlyDouble(closedWorld)) {
-        if (inputType.isNullable && checkedType.isNullable) {
+      if (abstractValueDomain.isIntegerOrNull(inputType) &&
+          abstractValueDomain.isDoubleOrNull(checkedType)) {
+        if (abstractValueDomain.canBeNull(inputType) &&
+            abstractValueDomain.canBeNull(checkedType)) {
           outputType =
               abstractValueDomain.includeNull(abstractValueDomain.doubleType);
         } else {
@@ -255,10 +256,10 @@
     return outputType;
   }
 
-  TypeMask visitTypeKnown(HTypeKnown instruction) {
+  AbstractValue visitTypeKnown(HTypeKnown instruction) {
     HInstruction input = instruction.checkedInput;
-    TypeMask inputType = input.instructionType;
-    TypeMask outputType =
+    AbstractValue inputType = input.instructionType;
+    AbstractValue outputType =
         abstractValueDomain.intersection(instruction.knownType, inputType);
     if (inputType != outputType) {
       input.replaceAllUsersDominatedBy(instruction.next, instruction);
@@ -266,8 +267,8 @@
     return outputType;
   }
 
-  void convertInput(
-      HInvokeDynamic instruction, HInstruction input, TypeMask type, int kind) {
+  void convertInput(HInvokeDynamic instruction, HInstruction input,
+      AbstractValue type, int kind) {
     Selector selector = (kind == HTypeConversion.RECEIVER_TYPE_CHECK)
         ? instruction.selector
         : null;
@@ -278,15 +279,15 @@
     input.replaceAllUsersDominatedBy(instruction, converted);
   }
 
-  bool isCheckEnoughForNsmOrAe(HInstruction instruction, TypeMask type) {
+  bool isCheckEnoughForNsmOrAe(HInstruction instruction, AbstractValue type) {
     // In some cases, we want the receiver to be an integer,
     // but that does not mean we will get a NoSuchMethodError
     // if it's not: the receiver could be a double.
-    if (type.containsOnlyInt(closedWorld)) {
+    if (abstractValueDomain.isIntegerOrNull(type)) {
       // If the instruction's type is integer or null, the codegen
       // will emit a null check, which is enough to know if it will
       // hit a noSuchMethod.
-      return instruction.isIntegerOrNull(closedWorld.abstractValueDomain);
+      return instruction.isIntegerOrNull(abstractValueDomain);
     }
     return true;
   }
@@ -297,12 +298,12 @@
   bool checkReceiver(HInvokeDynamic instruction) {
     assert(instruction.isInterceptedCall);
     HInstruction receiver = instruction.inputs[1];
-    if (receiver.isNumber(closedWorld.abstractValueDomain)) return false;
-    if (receiver.isNumberOrNull(closedWorld.abstractValueDomain)) {
+    if (receiver.isNumber(abstractValueDomain)) return false;
+    if (receiver.isNumberOrNull(abstractValueDomain)) {
       convertInput(
           instruction,
           receiver,
-          closedWorld.abstractValueDomain.excludeNull(receiver.instructionType),
+          abstractValueDomain.excludeNull(receiver.instructionType),
           HTypeConversion.RECEIVER_TYPE_CHECK);
       return true;
     } else if (instruction.element == null) {
@@ -315,10 +316,10 @@
       if (targets.length == 1) {
         MemberEntity target = targets.first;
         ClassEntity cls = target.enclosingClass;
-        TypeMask type = new TypeMask.nonNullSubclass(cls, closedWorld);
+        AbstractValue type = abstractValueDomain.createNonNullSubclass(cls);
         // We currently only optimize on some primitive types.
-        if (!type.containsOnlyNum(closedWorld) &&
-            !type.containsOnlyBool(closedWorld)) {
+        if (!abstractValueDomain.isNumberOrNull(type) &&
+            !abstractValueDomain.isBooleanOrNull(type)) {
           return false;
         }
         if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
@@ -341,11 +342,11 @@
     HInstruction right = instruction.inputs[2];
 
     Selector selector = instruction.selector;
-    if (selector.isOperator && left.isNumber(closedWorld.abstractValueDomain)) {
-      if (right.isNumber(closedWorld.abstractValueDomain)) return false;
-      TypeMask type = right.isIntegerOrNull(closedWorld.abstractValueDomain)
-          ? closedWorld.abstractValueDomain.excludeNull(right.instructionType)
-          : closedWorld.abstractValueDomain.numType;
+    if (selector.isOperator && left.isNumber(abstractValueDomain)) {
+      if (right.isNumber(abstractValueDomain)) return false;
+      AbstractValue type = right.isIntegerOrNull(abstractValueDomain)
+          ? abstractValueDomain.excludeNull(right.instructionType)
+          : abstractValueDomain.numType;
       // TODO(ngeoffray): Some number operations don't have a builtin
       // variant and will do the check in their method anyway. We
       // still add a check because it allows to GVN these operations,
@@ -376,7 +377,7 @@
     });
   }
 
-  TypeMask visitInvokeDynamic(HInvokeDynamic instruction) {
+  AbstractValue visitInvokeDynamic(HInvokeDynamic instruction) {
     if (instruction.isInterceptedCall) {
       // We cannot do the following optimization now, because we have to wait
       // for the type propagation to be stable. The receiver of [instruction]
@@ -403,7 +404,7 @@
     }
 
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
-    TypeMask receiverType = receiver.instructionType;
+    AbstractValue receiverType = receiver.instructionType;
     instruction.mask = receiverType;
 
     // Try to specialize the receiver after this call by inserting a refinement
@@ -414,11 +415,11 @@
     // we try to do the least expensive test first.
     const int _MAX_QUICK_USERS = 50;
     if (!instruction.selector.isClosureCall) {
-      TypeMask newType;
-      TypeMask computeNewType() {
+      AbstractValue newType;
+      AbstractValue computeNewType() {
         newType = closedWorld.computeReceiverType(
             instruction.selector, instruction.mask);
-        newType = newType.intersection(receiverType, closedWorld);
+        newType = abstractValueDomain.intersection(newType, receiverType);
         return newType;
       }
 
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 71f4e24..0038d5b 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -5,7 +5,7 @@
 import '../constant_system_dart.dart';
 import '../constants/constant_system.dart';
 import '../constants/values.dart';
-import '../world.dart' show ClosedWorld;
+import '../world.dart' show JClosedWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
@@ -600,13 +600,13 @@
    */
   final Map<HInstruction, Range> ranges = new Map<HInstruction, Range>();
 
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final ValueRangeInfo info;
   final SsaOptimizerTask optimizer;
 
   HGraph graph;
 
-  SsaValueRangeAnalyzer(ClosedWorld closedWorld, this.optimizer)
+  SsaValueRangeAnalyzer(JClosedWorld closedWorld, this.optimizer)
       : info = new ValueRangeInfo(closedWorld.constantSystem),
         this.closedWorld = closedWorld;
 
@@ -1064,7 +1064,7 @@
  * Tries to find a range for the update instruction of a loop phi.
  */
 class LoopUpdateRecognizer extends HBaseVisitor {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final Map<HInstruction, Range> ranges;
   final ValueRangeInfo info;
   LoopUpdateRecognizer(this.closedWorld, this.ranges, this.info);
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index cdebb1c..9a8f51c 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -9,7 +9,7 @@
 import 'ssa/nodes.dart' as ssa show HGraph;
 import 'ssa/ssa_tracer.dart' show HTracer;
 import 'util/util.dart' show Indentation;
-import 'world.dart' show ClosedWorld;
+import 'world.dart' show JClosedWorld;
 
 /**
  * If non-null, we only trace methods whose name match the regexp defined by the
@@ -27,7 +27,7 @@
  * readable by IR Hydra.
  */
 class Tracer extends TracerUtil {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final Namer namer;
   bool traceActive = false;
   final api.OutputSink output;
diff --git a/pkg/compiler/lib/src/types/abstract_value_domain.dart b/pkg/compiler/lib/src/types/abstract_value_domain.dart
index de04b3d..37ff14d 100644
--- a/pkg/compiler/lib/src/types/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/types/abstract_value_domain.dart
@@ -4,9 +4,23 @@
 
 library dart2js.abstract_value_domain;
 
-import '../constants/values.dart' show ConstantValue;
+import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
 import '../elements/entities.dart';
 import '../universe/selector.dart';
+import '../universe/world_builder.dart';
+import '../world.dart';
+
+enum AbstractBool { True, False, Maybe }
+
+/// Strategy for the abstraction of runtime values used by the global type
+/// inference.
+abstract class AbstractValueStrategy {
+  /// Creates the abstract value domain for [closedWorld].
+  AbstractValueDomain createDomain(JClosedWorld closedWorld);
+
+  /// Creates the [SelectorConstraintsStrategy] used by the backend enqueuer.
+  SelectorConstraintsStrategy createSelectorStrategy();
+}
 
 /// A value in an abstraction of runtime values.
 abstract class AbstractValue {}
@@ -89,12 +103,32 @@
   /// The [AbstractValue] that represents the empty set of runtime values.
   AbstractValue get emptyType;
 
-  /// Creates an [AbstractValue] for non-null exact instance of [cls].
+  /// The [AbstractValue] that represents a non-null instance at runtime of the
+  /// `Iterable` class used for the `sync*` implementation.
+  AbstractValue get syncStarIterableType;
+
+  /// The [AbstractValue] that represents a non-null instance at runtime of the
+  /// `Future` class used for the `async` implementation.
+  AbstractValue get asyncFutureType;
+
+  /// The [AbstractValue] that represents a non-null instance at runtime of the
+  /// `Stream` class used for the `async*` implementation.
+  AbstractValue get asyncStarStreamType;
+
+  /// Creates an [AbstractValue] for a non-null exact instance of [cls].
   AbstractValue createNonNullExact(ClassEntity cls);
 
-  /// Creates an [AbstractValue] for non-null instance that implements [cls].
+  /// Creates an [AbstractValue] for a potentially null exact instance of [cls].
+  AbstractValue createNullableExact(ClassEntity cls);
+
+  /// Creates an [AbstractValue] for a non-null instance that extends [cls].
+  AbstractValue createNonNullSubclass(ClassEntity cls);
+
+  /// Creates an [AbstractValue] for a non-null instance that implements [cls].
   AbstractValue createNonNullSubtype(ClassEntity cls);
 
+  /// Creates an [AbstractValue] for a potentially null instance that implements
+  /// [cls].
   AbstractValue createNullableSubtype(ClassEntity cls);
 
   /// Returns `true` if [value] is a native typed array or `null` at runtime.
@@ -117,16 +151,31 @@
   bool containsOnlyType(covariant AbstractValue value, ClassEntity cls);
 
   /// Returns `true` if [value] is an instance of [cls] or `null` at runtime.
-  bool isInstanceOf(covariant AbstractValue value, ClassEntity cls);
+  // TODO(johnniwinther): Merge this with [isInstanceOf].
+  bool isInstanceOfOrNull(covariant AbstractValue value, ClassEntity cls);
+
+  /// Returns an [AbstractBool] that describes how [value] is known to be an
+  /// instance of [cls] at runtime.
+  ///
+  /// If the returned value is `Abstract.True`, [value] is known _always_ to be
+  /// an instance of [cls]. If the returned value is `Abstract.False`, [value]
+  /// is known _never_ to be an instance of [cls]. If the returned value is
+  /// `Abstract.Maybe` [value] might or might not be an instance of [cls] at
+  /// runtime.
+  AbstractBool isInstanceOf(AbstractValue value, ClassEntity cls);
 
   /// Returns `true` if [value] is empty set of runtime values.
   bool isEmpty(covariant AbstractValue value);
 
-  /// Returns `true` if [value] is an exact class or `null` at runtime.
+  /// Returns `true` if [value] is a non-null exact class at runtime.
   bool isExact(covariant AbstractValue value);
 
-  /// Returns `true` if [value] a known primitive JavaScript value at runtime.
-  bool isValue(covariant AbstractValue value);
+  /// Returns `true` if [value] is an exact class or `null` at runtime.
+  bool isExactOrNull(covariant AbstractValue value);
+
+  /// Returns the [ClassEntity] if this [value] is a non-null instance of an
+  /// exact class at runtime, and `null` otherwise.
+  ClassEntity getExactClass(covariant AbstractValue value);
 
   /// Returns `true` if [value] can be `null` at runtime.
   bool canBeNull(covariant AbstractValue value);
@@ -174,6 +223,9 @@
   /// Returns `true` if [value] could be a JavaScript string at runtime.
   bool canBePrimitiveString(covariant AbstractValue value);
 
+  /// Return `true` if [value] could be an interceptor at runtime.
+  bool canBeInterceptor(covariant AbstractValue value);
+
   /// Returns `true` if [value] is a non-null integer value at runtime.
   bool isInteger(covariant AbstractValue value);
 
@@ -233,7 +285,7 @@
 
   /// Returns [AbstractValue] for the runtime values contained in at least one
   /// of [values].
-  AbstractValue unionOfMany(List<AbstractValue> values);
+  AbstractValue unionOfMany(Iterable<AbstractValue> values);
 
   /// Returns [AbstractValue] for the runtime values that [a] and [b] have in
   /// common.
@@ -249,14 +301,120 @@
   /// Computes the [AbstractValue] corresponding to the constant [value].
   AbstractValue computeAbstractValueForConstant(ConstantValue value);
 
+  /// Returns `true` if [value] represents a container value at runtime.
+  bool isContainer(covariant AbstractValue value);
+
+  /// Creates a container value specialization of [originalValue] with the
+  /// inferred [element] runtime value and inferred runtime [length].
+  ///
+  /// The [allocationNode] is used to identify this particular map allocation.
+  /// The [allocationElement] is used only for debugging.
+  AbstractValue createContainerValue(
+      AbstractValue originalValue,
+      Object allocationNode,
+      MemberEntity allocationElement,
+      AbstractValue elementType,
+      int length);
+
   /// Returns the element type of [value] if it represents a container value
   /// at runtime. Returns [dynamicType] otherwise.
   AbstractValue getContainerElementType(AbstractValue value);
 
+  /// Return the known length of [value] if it represents a container value
+  /// at runtime. Returns `null` if the length is unknown or if [value] doesn't
+  /// represent a container value at runtime.
+  int getContainerLength(AbstractValue value);
+
+  /// Returns `true` if [value] represents a map value at runtime.
+  bool isMap(covariant AbstractValue value);
+
+  /// Creates a map value specialization of [originalValue] with the inferred
+  /// [key] and [value] runtime values.
+  ///
+  /// The [allocationNode] is used to identify this particular map allocation.
+  /// The [allocationElement] is used only for debugging.
+  AbstractValue createMapValue(
+      AbstractValue originalValue,
+      Object allocationNode,
+      MemberEntity allocationElement,
+      AbstractValue key,
+      AbstractValue value);
+
+  /// Returns the key type of [value] if it represents a map value at runtime.
+  /// Returns [dynamicType] otherwise.
+  AbstractValue getMapKeyType(AbstractValue value);
+
   /// Returns the value type of [value] if it represents a map value at runtime.
   /// Returns [dynamicType] otherwise.
   AbstractValue getMapValueType(AbstractValue value);
 
+  /// Returns `true` if [value] represents a dictionary value, that is, a map
+  /// with strings as keys, at runtime.
+  bool isDictionary(covariant AbstractValue value);
+
+  /// Creates a dictionary value specialization of [originalValue] with the
+  /// inferred [key] and [value] runtime values.
+  ///
+  /// The [allocationNode] is used to identify this particular map allocation.
+  /// The [allocationElement] is used only for debugging.
+  AbstractValue createDictionaryValue(
+      AbstractValue originalValue,
+      Object allocationNode,
+      MemberEntity allocationElement,
+      AbstractValue key,
+      AbstractValue value,
+      Map<String, AbstractValue> mappings);
+
+  /// Returns `true` if [value] is a dictionary value which contains [key] as
+  /// a key.
+  bool containsDictionaryKey(AbstractValue value, String key);
+
+  /// Returns the value type for [key] in [value] if it represents a dictionary
+  /// value at runtime. Returns [dynamicType] otherwise.
+  AbstractValue getDictionaryValueForKey(AbstractValue value, String key);
+
+  /// Returns `true` if [specialization] is a specialization of
+  /// [generalization].
+  ///
+  /// Specializations are created through [createPrimitiveValue],
+  /// [createMapValue], [createDictionaryValue] and [createContainerValue].
+  bool isSpecializationOf(
+      AbstractValue specialization, AbstractValue generalization);
+
+  /// Returns the value of which [value] is a specialization. Return `null` if
+  /// [value] is not a specialization.
+  ///
+  /// Specializations are created through [createPrimitiveValue],
+  /// [createMapValue], [createDictionaryValue] and [createContainerValue].
+  AbstractValue getGeneralization(AbstractValue value);
+
+  /// Return the object identifying the allocation of [value] if it is an
+  /// allocation based specialization. Otherwise returns `null`.
+  ///
+  /// Allocation based specializations are created through [createMapValue],
+  /// [createDictionaryValue] and [createContainerValue]
+  Object getAllocationNode(AbstractValue value);
+
+  /// Return the allocation element of [value] if it is an allocation based
+  /// specialization. Otherwise returns `null`.
+  ///
+  /// Allocation based specializations are created through [createMapValue],
+  /// [createDictionaryValue] and [createContainerValue]
+  MemberEntity getAllocationElement(AbstractValue value);
+
+  /// Returns `true` if [value] a known primitive JavaScript value at runtime.
+  bool isPrimitiveValue(covariant AbstractValue value);
+
+  /// Creates a primitive value specialization of [originalValue] with the
+  /// inferred primitive constant [value].
+  AbstractValue createPrimitiveValue(
+      AbstractValue originalValue, PrimitiveConstantValue value);
+
+  /// Returns the primitive JavaScript value of [value] if it represents a
+  /// primitive JavaScript value at runtime, value at runtime. Returns `null`
+  /// otherwise.
+  PrimitiveConstantValue getPrimitiveValue(covariant AbstractValue value);
+
   /// Compute the type of all potential receivers of the set of live [members].
   AbstractValue computeReceiver(Iterable<MemberEntity> members);
 
@@ -273,9 +431,29 @@
   /// of runtime values of [superset].
   bool contains(AbstractValue superset, AbstractValue subset);
 
+  /// Returns `true` if the set of runtime values of [subset] are all in the set
+  /// of runtime values of [superset].
+  bool isIn(AbstractValue subset, AbstractValue superset);
+
   /// Returns the [MemberEntity] that is known to always be hit at runtime
   /// [receiver].
   ///
   /// Returns `null` if 0 or more than 1 member can be hit at runtime.
   MemberEntity locateSingleMember(AbstractValue receiver, Selector selector);
+
+  /// Returns `true` if [value] is an indexable JavaScript value at runtime.
+  bool isJsIndexable(covariant AbstractValue value);
+
+  /// Returns `true` if [value] is an indexable and iterable JavaScript value at
+  /// runtime.
+  ///
+  /// JavaScript arrays are both indexable and iterable whereas JavaScript
+  /// strings are indexable but not iterable.
+  bool isJsIndexableAndIterable(AbstractValue value);
+
+  /// Returns `true` if [value] is an JavaScript indexable of fixed length.
+  bool isFixedLengthJsIndexable(AbstractValue value);
+
+  /// Returns compact a textual representation for [value] used for debugging.
+  String getCompactText(AbstractValue value);
 }
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index 704157c..a182ee7 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -10,7 +10,7 @@
 import '../elements/entities.dart';
 import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClosedWorld, ClosedWorldRefiner;
+import '../world.dart' show JClosedWorld;
 import 'abstract_value_domain.dart';
 
 /// Results about a single element (e.g. a method, parameter, or field)
@@ -188,7 +188,7 @@
 abstract class GlobalTypeInferenceResults<T> {
   // TODO(sigmund): store relevant data & drop reference to inference engine.
   final TypeGraphInferrer<T> _inferrer;
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final Map<MemberEntity, GlobalTypeInferenceMemberResult<T>> _memberResults =
       <MemberEntity, GlobalTypeInferenceMemberResult<T>>{};
   final Map<Local, GlobalTypeInferenceParameterResult<T>> _parameterResults =
@@ -258,11 +258,11 @@
         super(compiler.measurer);
 
   /// Runs the global type-inference algorithm once.
-  void runGlobalTypeInference(FunctionEntity mainElement,
-      ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) {
+  void runGlobalTypeInference(
+      FunctionEntity mainElement, JClosedWorld closedWorld) {
     measure(() {
       typesInferrerInternal ??= compiler.backendStrategy.createTypesInferrer(
-          closedWorldRefiner,
+          closedWorld,
           disableTypeInference: compiler.disableTypeInference);
       typesInferrerInternal.analyzeMain(mainElement);
       typesInferrerInternal.clear();
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 2476b2b..bd9dca0 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -45,9 +45,9 @@
   ConstantValue getConstantFieldInitializer(covariant FieldEntity field);
 
   /// Returns `true` if [member] is invoked as a setter.
-  bool hasInvokedSetter(MemberEntity member, ClosedWorld world);
+  bool hasInvokedSetter(MemberEntity member, JClosedWorld world);
 
-  bool hasInvokedGetter(MemberEntity member, ClosedWorld world);
+  bool hasInvokedGetter(MemberEntity member, JClosedWorld world);
 
   Map<Selector, SelectorConstraints> invocationsByName(String name);
 
@@ -83,7 +83,7 @@
     implements CodegenWorldBuilder {
   final ElementEnvironment _elementEnvironment;
   final NativeBasicData _nativeBasicData;
-  final ClosedWorld _world;
+  final JClosedWorld _world;
 
   /// The set of all directly instantiated classes, that is, classes with a
   /// generative constructor that has been called directly and not only through
@@ -222,7 +222,7 @@
   }
 
   bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
-      MemberEntity member, ClosedWorld world) {
+      MemberEntity member, JClosedWorld world) {
     if (selectors == null) return false;
     for (Selector selector in selectors.keys) {
       if (selector.appliesUnnamed(member)) {
@@ -235,16 +235,16 @@
     return false;
   }
 
-  bool hasInvocation(MemberEntity member, ClosedWorld world) {
+  bool hasInvocation(MemberEntity member, JClosedWorld world) {
     return _hasMatchingSelector(_invokedNames[member.name], member, world);
   }
 
-  bool hasInvokedGetter(MemberEntity member, ClosedWorld world) {
+  bool hasInvokedGetter(MemberEntity member, JClosedWorld world) {
     return _hasMatchingSelector(_invokedGetters[member.name], member, world) ||
         member.isFunction && methodsNeedingSuperGetter.contains(member);
   }
 
-  bool hasInvokedSetter(MemberEntity member, ClosedWorld world) {
+  bool hasInvokedSetter(MemberEntity member, JClosedWorld world) {
     return _hasMatchingSelector(_invokedSetters[member.name], member, world);
   }
 
@@ -256,7 +256,8 @@
     void _process(Map<String, Set<_MemberUsage>> memberMap,
         EnumSet<MemberUse> action(_MemberUsage usage)) {
       _processSet(memberMap, methodName, (_MemberUsage usage) {
-        if (dynamicUse.appliesUnnamed(usage.entity, _world)) {
+        if (selectorConstraintsStrategy.appliedUnnamed(
+            dynamicUse, usage.entity, _world)) {
           memberUsed(usage.entity, action(usage));
           return true;
         }
@@ -294,14 +295,14 @@
       Map<String, Map<Selector, SelectorConstraints>> selectorMap) {
     Selector selector = dynamicUse.selector;
     String name = selector.name;
-    ReceiverConstraint mask = dynamicUse.mask;
+    Object constraint = dynamicUse.receiverConstraint;
     Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
         name, () => new Maplet<Selector, SelectorConstraints>());
     UniverseSelectorConstraints constraints =
         selectors.putIfAbsent(selector, () {
       return selectorConstraintsStrategy.createSelectorConstraints(selector);
     });
-    return constraints.addReceiverConstraint(mask);
+    return constraints.addReceiverConstraint(constraint);
   }
 
   Map<Selector, SelectorConstraints> _asUnmodifiable(
@@ -646,7 +647,7 @@
       this._globalLocalsMap,
       ElementEnvironment elementEnvironment,
       NativeBasicData nativeBasicData,
-      ClosedWorld world,
+      JClosedWorld world,
       SelectorConstraintsStrategy selectorConstraintsStrategy)
       : super(elementEnvironment, nativeBasicData, world,
             selectorConstraintsStrategy);
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index f408104..f90d4a6 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -54,7 +54,7 @@
   /// The closed world computed by this world builder.
   ///
   /// This is only available after the world builder has been closed.
-  ClosedWorld get closedWorldForTesting;
+  KClosedWorld get closedWorldForTesting;
 
   void registerClass(ClassEntity cls);
 }
@@ -363,7 +363,6 @@
   final ElementEnvironment _elementEnvironment;
   final DartTypes _dartTypes;
   final CommonElements _commonElements;
-  final ConstantSystem _constantSystem;
 
   final NativeBasicData _nativeBasicData;
   final NativeDataBuilder _nativeDataBuilder;
@@ -381,7 +380,7 @@
   bool hasFunctionApplySupport = false;
 
   bool _closed = false;
-  ClosedWorld _closedWorldCache;
+  KClosedWorld _closedWorldCache;
   final Set<MemberEntity> _liveInstanceMembers = new Set<MemberEntity>();
 
   final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
@@ -397,7 +396,6 @@
       this._elementEnvironment,
       this._dartTypes,
       this._commonElements,
-      this._constantSystem,
       this._nativeBasicData,
       this._nativeDataBuilder,
       this._interceptorDataBuilder,
@@ -446,7 +444,7 @@
 
   Iterable<MemberEntity> get processedMembers => _processedMembers;
 
-  ClosedWorld get closedWorldForTesting {
+  KClosedWorld get closedWorldForTesting {
     if (!_closed) {
       failedAt(
           NO_LOCATION_SPANNABLE, "The world builder has not yet been closed.");
@@ -600,7 +598,8 @@
     void _process(Map<String, Set<_MemberUsage>> memberMap,
         EnumSet<MemberUse> action(_MemberUsage usage)) {
       _processSet(memberMap, methodName, (_MemberUsage usage) {
-        if (dynamicUse.appliesUnnamed(usage.entity, this)) {
+        if (selectorConstraintsStrategy.appliedUnnamed(
+            dynamicUse, usage.entity, this)) {
           memberUsed(usage.entity, action(usage));
           return true;
         }
@@ -634,7 +633,7 @@
       Map<String, Map<Selector, SelectorConstraints>> selectorMap) {
     Selector selector = dynamicUse.selector;
     String name = selector.name;
-    ReceiverConstraint constraint = dynamicUse.mask;
+    Object constraint = dynamicUse.receiverConstraint;
     Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
         name, () => new Maplet<Selector, SelectorConstraints>());
     UniverseSelectorConstraints constraints =
@@ -892,11 +891,6 @@
     }
   }
 
-  ClosedWorld get closedWorldCache {
-    assert(isClosed);
-    return _closedWorldCache;
-  }
-
   @override
   bool isMemberUsed(MemberEntity member) {
     return _memberUsage[member]?.hasUse ?? false;
@@ -995,7 +989,6 @@
       ElementEnvironment elementEnvironment,
       DartTypes dartTypes,
       CommonElements commonElements,
-      ConstantSystem constantSystem,
       NativeBasicData nativeBasicData,
       NativeDataBuilder nativeDataBuilder,
       InterceptorDataBuilder interceptorDataBuilder,
@@ -1011,7 +1004,6 @@
             elementEnvironment,
             dartTypes,
             commonElements,
-            constantSystem,
             nativeBasicData,
             nativeDataBuilder,
             interceptorDataBuilder,
@@ -1024,7 +1016,7 @@
             classQueries);
 
   @override
-  ClosedWorld closeWorld() {
+  KClosedWorld closeWorld() {
     Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
         populateHierarchyNodes();
 
@@ -1040,7 +1032,7 @@
         "ClassHierarchyNode/ClassSet mismatch: "
         "${classHierarchyBuilder.classHierarchyNodes} vs "
         "${classHierarchyBuilder.classSets}");
-    return _closedWorldCache = new KernelClosedWorld(elementMap,
+    return _closedWorldCache = new KClosedWorldImpl(elementMap,
         options: _options,
         elementEnvironment: _elementEnvironment,
         dartTypes: _dartTypes,
@@ -1051,7 +1043,6 @@
         noSuchMethodData: _noSuchMethodRegistry.close(),
         resolutionWorldBuilder: this,
         rtiNeedBuilder: _rtiNeedBuilder,
-        constantSystem: _constantSystem,
         implementedClasses: _implementedClasses,
         liveNativeClasses: _nativeResolutionEnqueuer.liveNativeClasses,
         liveInstanceMembers: _liveInstanceMembers,
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 0fcec7e..8788342 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -22,10 +22,8 @@
 import '../elements/entities.dart';
 import '../js_model/closure.dart';
 import '../util/util.dart' show equalElements, Hashing;
-import '../world.dart' show World;
 import 'call_structure.dart' show CallStructure;
 import 'selector.dart' show Selector;
-import 'world_builder.dart' show ReceiverConstraint;
 
 enum DynamicUseKind {
   INVOKE,
@@ -34,7 +32,7 @@
 }
 
 /// The use of a dynamic property. [selector] defined the name and kind of the
-/// property and [mask] defines the known constraint for the object on which
+/// property and [receiverConstraint] defines the known constraint for the object on which
 /// the property is accessed.
 class DynamicUse {
   final Selector selector;
@@ -64,12 +62,7 @@
     return sb.toString();
   }
 
-  bool appliesUnnamed(MemberEntity element, World world) {
-    return selector.appliesUnnamed(element) &&
-        (mask == null || mask.canHit(element, selector, world));
-  }
-
-  ReceiverConstraint get mask => null;
+  Object get receiverConstraint => null;
 
   DynamicUseKind get kind {
     if (selector.isGetter) {
@@ -83,18 +76,18 @@
 
   List<DartType> get typeArguments => const <DartType>[];
 
-  int get hashCode =>
-      Hashing.listHash(typeArguments, Hashing.objectsHash(selector, mask));
+  int get hashCode => Hashing.listHash(
+      typeArguments, Hashing.objectsHash(selector, receiverConstraint));
 
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! DynamicUse) return false;
     return selector == other.selector &&
-        mask == other.mask &&
+        receiverConstraint == other.receiverConstraint &&
         equalElements(typeArguments, other.typeArguments);
   }
 
-  String toString() => '$selector,$mask';
+  String toString() => '$selector,$receiverConstraint';
 }
 
 class GenericDynamicUse extends DynamicUse {
@@ -118,10 +111,11 @@
 /// This is used in the codegen phase where receivers are constrained to a
 /// type mask or similar.
 class ConstrainedDynamicUse extends DynamicUse {
-  final ReceiverConstraint mask;
+  final Object receiverConstraint;
   final List<DartType> _typeArguments;
 
-  ConstrainedDynamicUse(Selector selector, this.mask, this._typeArguments)
+  ConstrainedDynamicUse(
+      Selector selector, this.receiverConstraint, this._typeArguments)
       : super(selector) {
     assert(
         selector.callStructure.typeArgumentCount ==
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 44d098b..088849b 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -9,7 +9,6 @@
 import '../common.dart';
 import '../common/names.dart' show Identifiers, Names;
 import '../common_elements.dart';
-import '../constants/constant_system.dart';
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
@@ -26,7 +25,7 @@
 import '../universe/class_set.dart';
 import '../util/enumset.dart';
 import '../util/util.dart';
-import '../world.dart' show World, ClosedWorld, OpenWorld;
+import '../world.dart' show World, JClosedWorld, KClosedWorld, OpenWorld;
 import 'class_hierarchy_builder.dart' show ClassHierarchyBuilder, ClassQueries;
 import 'selector.dart' show Selector;
 import 'use.dart'
@@ -42,27 +41,6 @@
 part 'member_usage.dart';
 part 'resolution_world_builder.dart';
 
-/// The known constraint on receiver for a dynamic call site.
-///
-/// This can for instance be used to constrain this dynamic call to `foo` to
-/// 'receivers of the exact instance `Bar`':
-///
-///     class Bar {
-///        void foo() {}
-///     }
-///     main() => new Bar().foo();
-///
-abstract class ReceiverConstraint {
-  /// Returns whether [element] is a potential target when being
-  /// invoked on a receiver with this constraint. [selector] is used to ensure
-  /// library privacy is taken into account.
-  bool canHit(MemberEntity element, Selector selector, covariant World world);
-
-  /// Returns whether this [TypeMask] applied to [selector] can hit a
-  /// [noSuchMethod].
-  bool needsNoSuchMethodHandling(Selector selector, covariant World world);
-}
-
 /// The combined constraints on receivers all the dynamic call sites of the same
 /// selector.
 ///
@@ -118,7 +96,7 @@
 abstract class UniverseSelectorConstraints extends SelectorConstraints {
   /// Adds [constraint] to these selector constraints. Return `true` if the set
   /// of potential receivers expanded due to the new constraint.
-  bool addReceiverConstraint(covariant ReceiverConstraint constraint);
+  bool addReceiverConstraint(covariant Object constraint);
 }
 
 /// Strategy for computing the constraints on potential receivers of dynamic
@@ -127,6 +105,9 @@
   /// Create a [UniverseSelectorConstraints] to represent the global receiver
   /// constraints for dynamic call sites with [selector].
   UniverseSelectorConstraints createSelectorConstraints(Selector selector);
+
+  /// Returns `true`  if [member] is a potential target of [dynamicUse].
+  bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member, World world);
 }
 
 class OpenWorldStrategy implements SelectorConstraintsStrategy {
@@ -135,6 +116,12 @@
   OpenWorldConstraints createSelectorConstraints(Selector selector) {
     return new OpenWorldConstraints();
   }
+
+  @override
+  bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member, World world) {
+    Selector selector = dynamicUse.selector;
+    return selector.appliesUnnamed(member);
+  }
 }
 
 class OpenWorldConstraints extends UniverseSelectorConstraints {
@@ -147,7 +134,7 @@
   bool needsNoSuchMethodHandling(Selector selector, World world) => isAll;
 
   @override
-  bool addReceiverConstraint(ReceiverConstraint constraint) {
+  bool addReceiverConstraint(Object constraint) {
     if (isAll) return false;
     isAll = true;
     return true;
@@ -174,6 +161,15 @@
   StrongModeWorldConstraints createSelectorConstraints(Selector selector) {
     return new StrongModeWorldConstraints();
   }
+
+  @override
+  bool appliedUnnamed(
+      DynamicUse dynamicUse, MemberEntity member, covariant OpenWorld world) {
+    Selector selector = dynamicUse.selector;
+    StrongModeConstraint constraint = dynamicUse.receiverConstraint;
+    return selector.appliesUnnamed(member) &&
+        (constraint == null || constraint.canHit(member, selector, world));
+  }
 }
 
 class StrongModeWorldConstraints extends UniverseSelectorConstraints {
@@ -230,15 +226,13 @@
   }
 }
 
-class StrongModeConstraint implements ReceiverConstraint {
+class StrongModeConstraint {
   final ClassEntity cls;
 
   const StrongModeConstraint(this.cls);
 
-  @override
   bool needsNoSuchMethodHandling(Selector selector, World world) => true;
 
-  @override
   bool canHit(MemberEntity element, Selector selector, OpenWorld world) {
     return world.isInheritedInSubtypeOf(element, cls);
   }
@@ -255,7 +249,7 @@
 }
 
 /// The [WorldBuilder] is an auxiliary class used in the process of computing
-/// the [ClosedWorld].
+/// the [JClosedWorld].
 // TODO(johnniwinther): Move common implementation to a [WorldBuilderBase] when
 // universes and worlds have been unified.
 abstract class WorldBuilder {
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 9bd4e8a..4dde4f2 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -23,17 +23,16 @@
 import 'ordered_typeset.dart';
 import 'options.dart';
 import 'types/abstract_value_domain.dart';
-import 'types/masks.dart' show CommonMasks;
 import 'universe/class_set.dart';
 import 'universe/function_set.dart' show FunctionSet;
 import 'universe/selector.dart' show Selector;
 import 'universe/side_effects.dart' show SideEffects, SideEffectsBuilder;
 import 'universe/world_builder.dart';
 
-/// Common superinterface for [OpenWorld] and [ClosedWorld].
+/// Common superinterface for [OpenWorld] and [JClosedWorld].
 abstract class World {}
 
-/// The [ClosedWorld] represents the information known about a program when
+/// The [JClosedWorld] represents the information known about a program when
 /// compiling with closed-world semantics.
 ///
 /// Given the entrypoint of an application, we can track what's reachable from
@@ -41,7 +40,8 @@
 /// JavaScript types are touched, what language features are used, and so on.
 /// This precise knowledge about what's live in the program is later used in
 /// optimizations and other compiler decisions during code generation.
-abstract class ClosedWorld implements World {
+// TODO(johnniwinther): Maybe this should just be called the JWorld.
+abstract class JClosedWorld implements World {
   BackendUsage get backendUsage;
 
   NativeData get nativeData;
@@ -94,10 +94,6 @@
   /// subclass.
   bool isIndirectlyInstantiated(ClassEntity cls);
 
-  /// Returns `true` if [cls] is abstract and thus can only be instantiated
-  /// through subclasses.
-  bool isAbstract(ClassEntity cls);
-
   /// Returns `true` if [cls] is implemented by an instantiated class.
   bool isImplemented(ClassEntity cls);
 
@@ -271,14 +267,14 @@
   /// of known classes.
   ///
   /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClosedWorld].
+  /// methods defined in [JClosedWorld].
   ClassHierarchyNode getClassHierarchyNode(ClassEntity cls);
 
   /// Returns [ClassSet] for [cls] used to model the extends and implements
   /// relations of known classes.
   ///
   /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClosedWorld].
+  /// methods defined in [JClosedWorld].
   ClassSet getClassSet(ClassEntity cls);
 
   /// Returns `true` if the field [element] is known to be effectively final.
@@ -346,13 +342,6 @@
   ///
   /// If [cls] is provided, the dump will contain only classes related to [cls].
   String dump([ClassEntity cls]);
-}
-
-/// Interface for computing side effects and uses of elements. This is used
-/// during type inference to compute the [ClosedWorld] for code generation.
-abstract class ClosedWorldRefiner {
-  /// The closed world being refined.
-  ClosedWorld get closedWorld;
 
   /// Registers the executing of [element] as without side effects.
   void registerSideEffectsFree(FunctionEntity element);
@@ -389,7 +378,7 @@
 abstract class OpenWorld implements World {
   void registerUsedElement(MemberEntity element);
 
-  ClosedWorld closeWorld();
+  KClosedWorld closeWorld();
 
   /// Returns an iterable over all mixin applications that mixin [cls].
   Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls);
@@ -423,7 +412,7 @@
   SUBTYPE,
 }
 
-abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner {
+abstract class ClosedWorldBase implements JClosedWorld {
   final ConstantSystem constantSystem;
   final NativeData nativeData;
   final InterceptorData interceptorData;
@@ -437,8 +426,6 @@
 
   final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
 
-  // We keep track of subtype and subclass relationships in four
-  // distinct sets to make class hierarchy analysis faster.
   final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes;
   final Map<ClassEntity, ClassSet> _classSets;
 
@@ -461,8 +448,6 @@
   final Set<FunctionEntity> _functionsThatMightBePassedToApply =
       new Set<FunctionEntity>();
 
-  CommonMasks _commonMasks;
-
   final ElementEnvironment elementEnvironment;
   final DartTypes dartTypes;
   final CommonElements commonElements;
@@ -496,24 +481,14 @@
       this.mixinUses,
       this.typesImplementedBySubclasses,
       Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
-      Map<ClassEntity, ClassSet> classSets)
+      Map<ClassEntity, ClassSet> classSets,
+      AbstractValueStrategy abstractValueStrategy)
       : this._implementedClasses = implementedClasses,
         this._classHierarchyNodes = classHierarchyNodes,
-        this._classSets = classSets {
-    _commonMasks = new CommonMasks(this);
-  }
-
-  @override
-  ClosedWorld get closedWorld => this;
-
-  CommonMasks get abstractValueDomain {
-    return _commonMasks;
-  }
+        this._classSets = classSets {}
 
   bool checkEntity(covariant Entity element);
 
-  bool checkClass(covariant ClassEntity cls);
-
   bool checkInvariants(covariant ClassEntity cls,
       {bool mustBeInstantiated: true});
 
@@ -531,42 +506,34 @@
 
   @override
   bool isInstantiated(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode node = _classHierarchyNodes[cls];
     return node != null && node.isInstantiated;
   }
 
   @override
   bool isDirectlyInstantiated(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode node = _classHierarchyNodes[cls];
     return node != null && node.isDirectlyInstantiated;
   }
 
   @override
   bool isAbstractlyInstantiated(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode node = _classHierarchyNodes[cls];
     return node != null && node.isAbstractlyInstantiated;
   }
 
   @override
   bool isExplicitlyInstantiated(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode node = _classHierarchyNodes[cls];
     return node != null && node.isExplicitlyInstantiated;
   }
 
   @override
   bool isIndirectlyInstantiated(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode node = _classHierarchyNodes[cls];
     return node != null && node.isIndirectlyInstantiated;
   }
 
-  @override
-  bool isAbstract(ClassEntity cls) => cls.isAbstract;
-
   /// Returns `true` if [cls] is implemented by an instantiated class.
   bool isImplemented(ClassEntity cls) {
     return _implementedClasses.contains(cls);
@@ -600,7 +567,6 @@
   /// Returns an iterable over the directly instantiated classes that extend
   /// [cls] possibly including [cls] itself, if it is live.
   Iterable<ClassEntity> subclassesOf(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode hierarchy = _classHierarchyNodes[cls];
     if (hierarchy == null) return const <ClassEntity>[];
     return hierarchy
@@ -610,7 +576,6 @@
   /// Returns an iterable over the directly instantiated classes that extend
   /// [cls] _not_ including [cls] itself.
   Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return const <ClassEntity>[];
     return subclasses.subclassesByMask(
@@ -621,7 +586,6 @@
   /// Returns the number of live classes that extend [cls] _not_
   /// including [cls] itself.
   int strictSubclassCount(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return 0;
     return subclasses.instantiatedSubclassCount;
@@ -631,7 +595,6 @@
   /// itself.
   void forEachStrictSubclassOf(
       ClassEntity cls, IterationStep f(ClassEntity cls)) {
-    assert(checkClass(cls));
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return;
     subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
@@ -641,7 +604,6 @@
   /// Returns `true` if [predicate] applies to any live class that extend [cls]
   /// _not_ including [cls] itself.
   bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
-    assert(checkClass(cls));
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return false;
     return subclasses.anySubclass(
@@ -652,7 +614,6 @@
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// possibly including [cls] itself, if it is live.
   Iterable<ClassEntity> subtypesOf(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassSet classSet = _classSets[cls];
     if (classSet == null) {
       return const <ClassEntity>[];
@@ -665,7 +626,6 @@
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// _not_ including [cls].
   Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassSet classSet = _classSets[cls];
     if (classSet == null) {
       return const <ClassEntity>[];
@@ -678,7 +638,6 @@
   /// Returns the number of live classes that implement [cls] _not_
   /// including [cls] itself.
   int strictSubtypeCount(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassSet classSet = _classSets[cls];
     if (classSet == null) return 0;
     return classSet.instantiatedSubtypeCount;
@@ -688,7 +647,6 @@
   /// itself.
   void forEachStrictSubtypeOf(
       ClassEntity cls, IterationStep f(ClassEntity cls)) {
-    assert(checkClass(cls));
     ClassSet classSet = _classSets[cls];
     if (classSet == null) return;
     classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
@@ -698,7 +656,6 @@
   /// Returns `true` if [predicate] applies to any live class that extend [cls]
   /// _not_ including [cls] itself.
   bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
-    assert(checkClass(cls));
     ClassSet classSet = _classSets[cls];
     if (classSet == null) return false;
     return classSet.anySubtype(
@@ -708,8 +665,6 @@
 
   /// Returns `true` if [a] and [b] have any known common subtypes.
   bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) {
-    assert(checkClass(a));
-    assert(checkClass(b));
     ClassSet classSetA = _classSets[a];
     ClassSet classSetB = _classSets[b];
     if (classSetA == null || classSetB == null) return false;
@@ -726,7 +681,6 @@
   /// Returns `true` if any directly instantiated class other than [cls] extends
   /// [cls].
   bool hasAnyStrictSubclass(ClassEntity cls) {
-    assert(checkClass(cls));
     ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
     if (subclasses == null) return false;
     return subclasses.isIndirectlyInstantiated;
@@ -741,7 +695,6 @@
   /// Returns `true` if all directly instantiated classes that implement [cls]
   /// extend it.
   bool hasOnlySubclasses(ClassEntity cls) {
-    assert(checkClass(cls));
     // TODO(johnniwinther): move this to ClassSet?
     if (cls == commonElements.objectClass) return true;
     ClassSet classSet = _classSets[cls];
@@ -754,7 +707,6 @@
 
   @override
   ClassEntity getLubOfInstantiatedSubclasses(ClassEntity cls) {
-    assert(checkClass(cls));
     if (nativeData.isJsInteropClass(cls)) {
       return commonElements.jsJavaScriptObjectClass;
     }
@@ -766,7 +718,6 @@
 
   @override
   ClassEntity getLubOfInstantiatedSubtypes(ClassEntity cls) {
-    assert(checkClass(cls));
     if (nativeData.isJsInteropClass(cls)) {
       return commonElements.jsJavaScriptObjectClass;
     }
@@ -810,8 +761,6 @@
   /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
   /// of a mixin application of [y].
   bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) {
-    assert(checkClass(x));
-    assert(checkClass(y));
     Map<ClassEntity, bool> secondMap =
         _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{};
     return secondMap[y] ??= subtypesOf(x).every((ClassEntity cls) =>
@@ -820,7 +769,6 @@
 
   /// Returns `true` if any subclass of [superclass] implements [type].
   bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) {
-    assert(checkClass(superclass));
     Set<ClassEntity> subclasses = typesImplementedBySubclasses[superclass];
     if (subclasses == null) return false;
     return subclasses.contains(type);
@@ -991,8 +939,6 @@
 
   /// Returns `true` if [cls] or any superclass mixes in [mixin].
   bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
-    assert(checkClass(cls));
-    assert(checkClass(mixin));
     if (isUsedAsMixin(mixin)) {
       ClassEntity current = cls;
       while (current != null) {
@@ -1008,9 +954,8 @@
   /// of known classes.
   ///
   /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClosedWorld].
+  /// methods defined in [JClosedWorld].
   ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
-    assert(checkClass(cls));
     return _classHierarchyNodes[cls];
   }
 
@@ -1018,9 +963,8 @@
   /// relations of known classes.
   ///
   /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClosedWorld].
+  /// methods defined in [JClosedWorld].
   ClassSet getClassSet(ClassEntity cls) {
-    assert(checkClass(cls));
     return _classSets[cls];
   }
 
@@ -1266,7 +1210,7 @@
   }
 }
 
-abstract class ClosedWorldRtiNeedMixin implements ClosedWorld {
+abstract class ClosedWorldRtiNeedMixin implements KClosedWorld {
   RuntimeTypesNeed _rtiNeed;
 
   void computeRtiNeed(ResolutionWorldBuilder resolutionWorldBuilder,
@@ -1277,3 +1221,45 @@
 
   RuntimeTypesNeed get rtiNeed => _rtiNeed;
 }
+
+abstract class KClosedWorld {
+  DartTypes get dartTypes;
+  BackendUsage get backendUsage;
+  NativeData get nativeData;
+  InterceptorData get interceptorData;
+  ElementEnvironment get elementEnvironment;
+  CommonElements get commonElements;
+
+  /// Returns `true` if [cls] is implemented by an instantiated class.
+  bool isImplemented(ClassEntity cls);
+
+  /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
+  /// of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [JClosedWorld].
+  ClassHierarchyNode getClassHierarchyNode(ClassEntity cls);
+
+  /// Returns [ClassSet] for [cls] used to model the extends and implements
+  /// relations of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [JClosedWorld].
+  ClassSet getClassSet(ClassEntity cls);
+  Iterable<MemberEntity> get liveInstanceMembers;
+  Map<ClassEntity, Set<ClassEntity>> get mixinUses;
+  Map<ClassEntity, Set<ClassEntity>> get typesImplementedBySubclasses;
+
+  /// Members that are written either directly or through a setter selector.
+  Iterable<MemberEntity> get assignedInstanceMembers;
+
+  Iterable<ClassEntity> get liveNativeClasses;
+  Iterable<MemberEntity> get processedMembers;
+  RuntimeTypesNeed get rtiNeed;
+  NoSuchMethodData get noSuchMethodData;
+
+  /// Applies [f] to each live class that implements [cls] _not_ including [cls]
+  /// itself.
+  void forEachStrictSubtypeOf(
+      ClassEntity cls, IterationStep f(ClassEntity cls));
+}
diff --git a/pkg/dev_compiler/tool/ddc b/pkg/dev_compiler/tool/ddc
index aa6f9d8..addb332 100755
--- a/pkg/dev_compiler/tool/ddc
+++ b/pkg/dev_compiler/tool/ddc
@@ -70,7 +70,7 @@
   if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
     echo "DDC SDK must be built first, please run:"
     echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_sdk_kernel_summary"
+    echo "    ./tools/build.py -m release dartdevk_sdk"
     exit 1
   fi
 
diff --git a/pkg/dev_compiler/tool/ddw b/pkg/dev_compiler/tool/ddw
index dfae2a2..4941c00 100755
--- a/pkg/dev_compiler/tool/ddw
+++ b/pkg/dev_compiler/tool/ddw
@@ -70,7 +70,7 @@
   if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
     echo "DDC SDK must be built first, please run:"
     echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_sdk_kernel_summary"
+    echo "    ./tools/build.py -m release dartdevk_sdk"
     exit 1
   fi
 
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index e624930..c39a398 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -94,8 +94,8 @@
   /// program.
   ///
   /// The components provided here should be closed and acyclic: any libraries
-  /// that they reference should be defined in a component in [linkedDependencies]
-  /// or any of the [inputSummaries] or [sdkSummary].
+  /// that they reference should be defined in a component in
+  /// [linkedDependencies] or any of the [inputSummaries] or [sdkSummary].
   List<Uri> linkedDependencies = [];
 
   /// URI of the SDK summary file (typically a "file:" URI).
@@ -175,8 +175,8 @@
   // verbose data (Issue #30056)
   bool verbose = false;
 
-  /// Whether to run extra verification steps to validate that compiled components
-  /// are well formed.
+  /// Whether to run extra verification steps to validate that compiled
+  /// components are well formed.
   ///
   /// Errors are reported via the [onError] callback.
   // TODO(sigmund): ensure we don't print errors to stdout (Issue #30056)
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/front_end/lib/src/base/errors.dart
index 7699dd1..1f01f89 100644
--- a/pkg/front_end/lib/src/base/errors.dart
+++ b/pkg/front_end/lib/src/base/errors.dart
@@ -83,8 +83,8 @@
   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.
+   * 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");
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index c3072d9..08b6057 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -104,18 +104,18 @@
 
   /// The SDK summary, or `null` if it has not been read yet.
   ///
-  /// A summary, also referred to as "outline" internally, is a [Component] where
-  /// all method bodies are left out. In essence, it contains just API
-  /// signatures and constants. When strong-mode is enabled, the summary already
-  /// includes inferred types.
+  /// A summary, also referred to as "outline" internally, is a [Component]
+  /// where all method bodies are left out. In essence, it contains just API
+  /// signatures and constants. When strong-mode is enabled, the summary
+  /// already includes inferred types.
   Component _sdkSummaryComponent;
 
   /// The summary for each uri in `options.inputSummaries`.
   ///
-  /// A summary, also referred to as "outline" internally, is a [Component] where
-  /// all method bodies are left out. In essence, it contains just API
-  /// signatures and constants. When strong-mode is enabled, the summary already
-  /// includes inferred types.
+  /// A summary, also referred to as "outline" internally, is a [Component]
+  /// where all method bodies are left out. In essence, it contains just API
+  /// signatures and constants. When strong-mode is enabled, the summary
+  /// already includes inferred types.
   List<Component> _inputSummariesComponents;
 
   /// Other components that are meant to be linked and compiled with the input
diff --git a/pkg/front_end/lib/src/base/source.dart b/pkg/front_end/lib/src/base/source.dart
index a87f933..d3d0884 100644
--- a/pkg/front_end/lib/src/base/source.dart
+++ b/pkg/front_end/lib/src/base/source.dart
@@ -34,24 +34,28 @@
 }
 
 /**
- * The interface `Source` defines the behavior of objects representing source code that can be
- * analyzed by the analysis engine.
+ * 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.
+ * Implementations of this interface need to be aware of some assumptions made
+ * by the analysis engine concerning sources:
  *
- * 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.
+ * * 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 {
   /**
@@ -63,8 +67,8 @@
    * 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.
+   * 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
@@ -72,8 +76,8 @@
   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 that can be used to create
+   * a source that is equal to this source.
    *
    * @return an encoded representation of this source
    * See [SourceFactory.fromEncoding].
@@ -81,9 +85,9 @@
   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 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
    */
@@ -112,9 +116,10 @@
    * 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.
+   * 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
@@ -123,8 +128,9 @@
   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 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
    */
@@ -141,22 +147,23 @@
   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. 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.
+   * 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
+   * @return `true` if the given object is a source that represents the same
+   *         source code as this source
    * See [Object.==].
    */
   @override
@@ -166,8 +173,9 @@
    * 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.
+   * 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
    */
diff --git a/pkg/front_end/lib/src/base/uri_kind.dart b/pkg/front_end/lib/src/base/uri_kind.dart
index 0e6d007..e098992 100644
--- a/pkg/front_end/lib/src/base/uri_kind.dart
+++ b/pkg/front_end/lib/src/base/uri_kind.dart
@@ -3,8 +3,9 @@
 // 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.
+ * 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> {
   /**
diff --git a/pkg/front_end/lib/src/codegen/tools.dart b/pkg/front_end/lib/src/codegen/tools.dart
index cda0e11..02a4050 100644
--- a/pkg/front_end/lib/src/codegen/tools.dart
+++ b/pkg/front_end/lib/src/codegen/tools.dart
@@ -60,8 +60,8 @@
     for (GeneratedContent target in targets) {
       bool ok = await target.check(pkgPath);
       if (!ok) {
-        print(
-            '${target.output(pkgPath).absolute} does not have expected contents.');
+        print("${target.output(pkgPath).absolute}"
+            " doesn't have expected contents.");
         generateNeeded = true;
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index 65fc3cd..914ee9e 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.dart
@@ -4,14 +4,6 @@
 
 library fasta.builder;
 
-import '../../base/instrumentation.dart' show Instrumentation;
-
-import '../problems.dart' show unhandled, unsupported;
-
-import 'library_builder.dart' show LibraryBuilder;
-
-import 'class_builder.dart' show ClassBuilder;
-
 export '../scope.dart' show AccessErrorBuilder, Scope, ScopeBuilder;
 
 export 'builtin_type_builder.dart' show BuiltinTypeBuilder;
@@ -20,6 +12,8 @@
 
 export 'constructor_reference_builder.dart' show ConstructorReferenceBuilder;
 
+export 'declaration.dart' show Declaration;
+
 export 'dynamic_type_builder.dart' show DynamicTypeBuilder;
 
 export 'enum_builder.dart' show EnumBuilder;
@@ -61,93 +55,3 @@
 export 'unresolved_type.dart' show UnresolvedType;
 
 export 'void_type_builder.dart' show VoidTypeBuilder;
-
-abstract class Builder {
-  /// Used when multiple things with the same name are declared within the same
-  /// parent. Only used for declarations, not for scopes.
-  ///
-  // TODO(ahe): Move to member builder or something. Then we can make
-  // this a const class.
-  Builder next;
-
-  /// The values of [parent], [charOffset], and [fileUri] aren't stored. We
-  /// need to evaluate the memory impact of doing so, but want to ensure the
-  /// information is always provided.
-  Builder(Builder parent, int charOffset, Uri fileUri);
-
-  int get charOffset => -1;
-
-  Uri get fileUri => null;
-
-  /// Resolve constructors (lookup names in scope) recorded in this builder and
-  /// return the number of constructors resolved.
-  int resolveConstructors(LibraryBuilder parent) => 0;
-
-  Builder get parent => null;
-
-  bool get isFinal => false;
-
-  bool get isField => false;
-
-  bool get isRegularMethod => false;
-
-  bool get isGetter => false;
-
-  bool get isSetter => false;
-
-  bool get isInstanceMember => false;
-
-  bool get isStatic => false;
-
-  bool get isTopLevel => false;
-
-  bool get isTypeDeclaration => false;
-
-  bool get isTypeVariable => false;
-
-  bool get isConstructor => false;
-
-  bool get isFactory => false;
-
-  bool get isLocal => false;
-
-  bool get isConst => false;
-
-  bool get isSynthetic => false;
-
-  get target => unsupported("${runtimeType}.target", charOffset, fileUri);
-
-  bool get hasProblem => false;
-
-  bool get isPatch => this != origin;
-
-  Builder get origin => this;
-
-  String get fullNameForErrors;
-
-  Uri computeLibraryUri() {
-    Builder builder = this;
-    do {
-      if (builder is LibraryBuilder) return builder.uri;
-      builder = builder.parent;
-    } while (builder != null);
-    return unhandled("no library parent", "${runtimeType}", -1, null);
-  }
-
-  void prepareTopLevelInference(
-      covariant LibraryBuilder library, ClassBuilder currentClass) {}
-
-  void instrumentTopLevelInference(Instrumentation instrumentation) {}
-
-  /// Applies [patch] to this.
-  void applyPatch(Builder patch) {
-    unsupported("${runtimeType}.applyPatch", charOffset, fileUri);
-  }
-
-  /// Returns the number of patches that was finished.
-  int finishPatch() {
-    if (!isPatch) return 0;
-    unsupported("${runtimeType}.finishPatch", charOffset, fileUri);
-    return 0;
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 6121947..1fc5bc5 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -8,8 +8,8 @@
 
 import 'builder.dart'
     show
-        Builder,
         ConstructorReferenceBuilder,
+        Declaration,
         LibraryBuilder,
         MemberBuilder,
         MetadataBuilder,
@@ -90,19 +90,19 @@
   }
 
   /// Used to lookup a static member of this class.
-  Builder findStaticBuilder(
+  Declaration findStaticBuilder(
       String name, int charOffset, Uri fileUri, LibraryBuilder accessingLibrary,
       {bool isSetter: false}) {
     if (accessingLibrary.origin != library.origin && name.startsWith("_")) {
       return null;
     }
-    Builder builder = isSetter
+    Declaration declaration = isSetter
         ? scope.lookupSetter(name, charOffset, fileUri, isInstanceScope: false)
         : scope.lookup(name, charOffset, fileUri, isInstanceScope: false);
-    return builder;
+    return declaration;
   }
 
-  Builder findConstructorOrFactory(
+  Declaration findConstructorOrFactory(
       String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary) {
     if (accessingLibrary.origin != library.origin && name.startsWith("_")) {
       return null;
@@ -137,14 +137,14 @@
     Map<TypeVariableBuilder, TypeBuilder> substitutionMap;
     List arguments;
     List variables;
-    Builder builder;
+    Declaration declaration;
 
     /// If [application] is mixing in [superclass] directly or via other named
     /// mixin applications, return it.
     NamedTypeBuilder findSuperclass(MixinApplicationBuilder application) {
       for (TypeBuilder t in application.mixins) {
         if (t is NamedTypeBuilder) {
-          if (t.builder == superclass) return t;
+          if (t.declaration == superclass) return t;
         } else if (t is MixinApplicationBuilder) {
           NamedTypeBuilder s = findSuperclass(t);
           if (s != null) return s;
@@ -154,16 +154,16 @@
     }
 
     void handleNamedTypeBuilder(NamedTypeBuilder t) {
-      builder = t.builder;
+      declaration = t.declaration;
       arguments = t.arguments ?? const [];
-      if (builder is ClassBuilder) {
-        ClassBuilder cls = builder;
+      if (declaration is ClassBuilder) {
+        ClassBuilder cls = declaration;
         variables = cls.typeVariables;
         supertype = cls.supertype;
       }
     }
 
-    while (builder != superclass) {
+    while (declaration != superclass) {
       variables = null;
       if (supertype is NamedTypeBuilder) {
         handleNamedTypeBuilder(supertype);
@@ -226,4 +226,6 @@
   }
 
   int get typeVariablesCount;
+
+  void prepareTopLevelInference() {}
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart
index d059f88..bc7a3cb 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart
@@ -8,15 +8,19 @@
 
 import 'builder.dart'
     show
-        Builder,
         ClassBuilder,
+        Declaration,
         LibraryBuilder,
         PrefixBuilder,
         QualifiedName,
         Scope,
         TypeBuilder;
 
-class ConstructorReferenceBuilder extends Builder {
+class ConstructorReferenceBuilder {
+  final int charOffset;
+
+  final Uri fileUri;
+
   final Object name;
 
   final List<TypeBuilder> typeArguments;
@@ -24,38 +28,38 @@
   /// This is the name of a named constructor. As `bar` in `new Foo<T>.bar()`.
   final String suffix;
 
-  Builder target;
+  Declaration target;
 
   ConstructorReferenceBuilder(this.name, this.typeArguments, this.suffix,
-      Builder parent, int charOffset)
-      : super(parent, charOffset, parent.fileUri);
+      Declaration parent, this.charOffset)
+      : fileUri = parent.fileUri;
 
   String get fullNameForErrors => "$name${suffix == null ? '' : '.$suffix'}";
 
   void resolveIn(Scope scope, LibraryBuilder accessingLibrary) {
     final name = this.name;
-    Builder builder;
+    Declaration declaration;
     if (name is QualifiedName) {
       String prefix = name.prefix;
       String middle = name.suffix;
-      builder = scope.lookup(prefix, charOffset, fileUri);
-      if (builder is PrefixBuilder) {
-        PrefixBuilder prefix = builder;
-        builder = prefix.lookup(middle, name.charOffset, fileUri);
-      } else if (builder is ClassBuilder) {
-        ClassBuilder cls = builder;
-        builder = cls.findConstructorOrFactory(
+      declaration = scope.lookup(prefix, charOffset, fileUri);
+      if (declaration is PrefixBuilder) {
+        PrefixBuilder prefix = declaration;
+        declaration = prefix.lookup(middle, name.charOffset, fileUri);
+      } else if (declaration is ClassBuilder) {
+        ClassBuilder cls = declaration;
+        declaration = cls.findConstructorOrFactory(
             middle, name.charOffset, fileUri, accessingLibrary);
         if (suffix == null) {
-          target = builder;
+          target = declaration;
           return;
         }
       }
     } else {
-      builder = scope.lookup(name, charOffset, fileUri);
+      declaration = scope.lookup(name, charOffset, fileUri);
     }
-    if (builder is ClassBuilder) {
-      target = builder.findConstructorOrFactory(
+    if (declaration is ClassBuilder) {
+      target = declaration.findConstructorOrFactory(
           suffix ?? "", charOffset, fileUri, accessingLibrary);
     }
     if (target == null) {
diff --git a/pkg/front_end/lib/src/fasta/builder/declaration.dart b/pkg/front_end/lib/src/fasta/builder/declaration.dart
new file mode 100644
index 0000000..d340033
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/declaration.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2018, 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 fasta.declaration;
+
+import '../problems.dart' show unsupported;
+
+abstract class Declaration {
+  /// Used when multiple things with the same name are declared within the same
+  /// parent. Only used for top-level and class-member declarations, not for
+  /// block scopes.
+  Declaration next;
+
+  Declaration();
+
+  Declaration get parent;
+
+  Uri get fileUri;
+
+  int get charOffset;
+
+  get target => unsupported("${runtimeType}.target", charOffset, fileUri);
+
+  Declaration get origin => this;
+
+  String get fullNameForErrors;
+
+  bool get hasProblem => false;
+
+  bool get isConst => false;
+
+  bool get isConstructor => false;
+
+  bool get isFactory => false;
+
+  bool get isField => false;
+
+  bool get isFinal => false;
+
+  bool get isGetter => false;
+
+  bool get isInstanceMember => false;
+
+  bool get isLocal => false;
+
+  bool get isPatch => this != origin;
+
+  bool get isRegularMethod => false;
+
+  bool get isSetter => false;
+
+  bool get isStatic => false;
+
+  bool get isSynthetic => false;
+
+  bool get isTopLevel => false;
+
+  bool get isTypeDeclaration => false;
+
+  bool get isTypeVariable => false;
+
+  /// Applies [patch] to this declaration.
+  void applyPatch(Declaration patch) {
+    unsupported("${runtimeType}.applyPatch", charOffset, fileUri);
+  }
+
+  /// Returns the number of patches that was finished.
+  int finishPatch() {
+    if (!isPatch) return 0;
+    unsupported("${runtimeType}.finishPatch", charOffset, fileUri);
+    return 0;
+  }
+
+  /// Resolve constructors (lookup names in scope) recorded in this builder and
+  /// return the number of constructors resolved.
+  int resolveConstructors(covariant Declaration parent) => 0;
+
+  void instrumentTopLevelInference(covariant instrumentation) {}
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 054a552..8e780a5 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -28,4 +28,6 @@
   bool get isField => true;
 
   bool get hasTypeInferredFromInitializer;
+
+  void prepareTopLevelInference() {}
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 304d87f..7e81d10 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -22,8 +22,8 @@
 
 import 'builder.dart'
     show
-        Builder,
         ClassBuilder,
+        Declaration,
         ModifierBuilder,
         PrefixBuilder,
         Scope,
@@ -51,6 +51,9 @@
         exportScopeBuilder = new ScopeBuilder(exportScope),
         super(null, -1, fileUri);
 
+  @override
+  Declaration get parent => null;
+
   bool get isPart => false;
 
   @override
@@ -64,9 +67,11 @@
   @override
   R get target;
 
+  bool get disableTypeInference => true;
+
   Uri get uri;
 
-  Builder addBuilder(String name, Builder builder, int charOffset);
+  Declaration addBuilder(String name, Declaration declaration, int charOffset);
 
   void addExporter(
       LibraryBuilder exporter, List<Combinator> combinators, int charOffset) {
@@ -93,16 +98,17 @@
   }
 
   /// Returns true if the export scope was modified.
-  bool addToExportScope(String name, Builder member) {
+  bool addToExportScope(String name, Declaration member) {
     if (name.startsWith("_")) return false;
     if (member is PrefixBuilder) return false;
-    Map<String, Builder> map =
+    Map<String, Declaration> map =
         member.isSetter ? exportScope.setters : exportScope.local;
-    Builder existing = map[name];
+    Declaration existing = map[name];
     if (existing == member) return false;
     if (existing != null) {
-      Builder result =
-          buildAmbiguousBuilder(name, existing, member, -1, isExport: true);
+      Declaration result = computeAmbiguousDeclaration(
+          name, existing, member, -1,
+          isExport: true);
       map[name] = result;
       return result != existing;
     } else {
@@ -111,10 +117,11 @@
     return true;
   }
 
-  void addToScope(String name, Builder member, int charOffset, bool isImport);
+  void addToScope(
+      String name, Declaration member, int charOffset, bool isImport);
 
-  Builder buildAmbiguousBuilder(
-      String name, Builder builder, Builder other, int charOffset,
+  Declaration computeAmbiguousDeclaration(
+      String name, Declaration declaration, Declaration other, int charOffset,
       {bool isExport: false, bool isImport: false});
 
   int finishDeferredLoadTearoffs() => 0;
@@ -135,7 +142,7 @@
   /// If [constructorName] is null or the empty string, it's assumed to be an
   /// unnamed constructor. it's an error if [constructorName] starts with
   /// `"_"`, and [bypassLibraryPrivacy] is false.
-  Builder getConstructor(String className,
+  Declaration getConstructor(String className,
       {String constructorName, bool bypassLibraryPrivacy: false}) {
     constructorName ??= "";
     if (constructorName.startsWith("_") && !bypassLibraryPrivacy) {
@@ -145,12 +152,12 @@
           -1,
           null);
     }
-    Builder cls = (bypassLibraryPrivacy ? scope : exportScope)
+    Declaration cls = (bypassLibraryPrivacy ? scope : exportScope)
         .lookup(className, -1, null);
     if (cls is ClassBuilder) {
       // TODO(ahe): This code is similar to code in `endNewExpression` in
       // `body_builder.dart`, try to share it.
-      Builder constructor =
+      Declaration constructor =
           cls.findConstructorOrFactory(constructorName, -1, null, this);
       if (constructor == null) {
         // Fall-through to internal error below.
@@ -182,17 +189,17 @@
 
   void becomeCoreLibrary(dynamicType);
 
-  void forEach(void f(String name, Builder builder)) {
-    scope.forEach((String name, Builder builder) {
-      if (builder.parent == this) {
-        f(name, builder);
+  void forEach(void f(String name, Declaration declaration)) {
+    scope.forEach((String name, Declaration declaration) {
+      if (declaration.parent == this) {
+        f(name, declaration);
       }
     });
   }
 
   /// Don't use for scope lookup. Only use when an element is known to exist
   /// (and not a setter).
-  Builder operator [](String name) {
+  Declaration operator [](String name) {
     return scope.local[name] ??
         internalProblem(
             templateInternalProblemNotFoundIn.withArguments(name, "$fileUri"),
@@ -200,7 +207,7 @@
             fileUri);
   }
 
-  Builder lookup(String name, int charOffset, Uri fileUri) {
+  Declaration lookup(String name, int charOffset, Uri fileUri) {
     return scope.lookup(name, charOffset, fileUri);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 3ff91f6..827fe5f 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -5,13 +5,13 @@
 library fasta.member_builder;
 
 import 'builder.dart'
-    show Builder, ClassBuilder, LibraryBuilder, ModifierBuilder;
+    show ClassBuilder, Declaration, LibraryBuilder, ModifierBuilder;
 
 abstract class MemberBuilder extends ModifierBuilder {
   /// For top-level members, the parent is set correctly during
   /// construction. However, for class members, the parent is initially the
   /// library and updated later.
-  Builder parent;
+  Declaration parent;
 
   String get name;
 
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index f611658..ca27f7f 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -4,25 +4,24 @@
 
 library fasta.metadata_builder;
 
-import 'builder.dart' show Builder, TypeBuilder;
+import 'builder.dart' show Declaration, TypeBuilder;
 
 import 'constructor_reference_builder.dart' show ConstructorReferenceBuilder;
 
-abstract class MetadataBuilder<T extends TypeBuilder> extends Builder {
-  MetadataBuilder(Builder parent, int charOffset)
-      : super(parent, -1, parent.fileUri);
+abstract class MetadataBuilder<T extends TypeBuilder> {
+  MetadataBuilder(Declaration parent, int charOffset);
 
   factory MetadataBuilder.fromConstructor(
       ConstructorReferenceBuilder constructorReference,
       List arguments,
-      Builder parent,
+      Declaration parent,
       int charOffset) {
     return new ConstructorMetadataBuilder(
         constructorReference, arguments, parent, charOffset);
   }
 
   factory MetadataBuilder.fromExpression(
-      Object expression, String postfix, Builder parent, int charOffset) {
+      Object expression, String postfix, Declaration parent, int charOffset) {
     return new ExpressionMetadataBuilder(
         expression, postfix, parent, charOffset);
   }
@@ -34,12 +33,9 @@
 
   final List arguments;
 
-  ConstructorMetadataBuilder(
-      this.constructorReference, this.arguments, Builder parent, int charOffset)
+  ConstructorMetadataBuilder(this.constructorReference, this.arguments,
+      Declaration parent, int charOffset)
       : super(parent, charOffset);
-
-  @override
-  String get fullNameForErrors => constructorReference.fullNameForErrors;
 }
 
 /// Expression metadata (without arguments).
@@ -54,11 +50,6 @@
   final String identifier;
 
   ExpressionMetadataBuilder(
-      this.qualified, this.identifier, Builder parent, int charOffset)
+      this.qualified, this.identifier, Declaration parent, int charOffset)
       : super(parent, charOffset);
-
-  @override
-  String get fullNameForErrors {
-    return identifier == null ? qualified : "$qualified.$identifier";
-  }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart b/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
index 2cb6afa..c229560 100644
--- a/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
@@ -14,16 +14,17 @@
         namedMixinApplicationMask,
         staticMask;
 
-import 'builder.dart' show Builder;
+import 'builder.dart' show Declaration;
 
-abstract class ModifierBuilder extends Builder {
+abstract class ModifierBuilder extends Declaration {
+  final Declaration parent;
+
   final int charOffset;
 
   final Uri fileUri;
 
-  ModifierBuilder(Builder parent, this.charOffset, [Uri fileUri])
-      : fileUri = fileUri ?? parent?.fileUri,
-        super(parent, charOffset, fileUri ?? parent?.fileUri);
+  ModifierBuilder(this.parent, this.charOffset, [Uri fileUri])
+      : fileUri = fileUri ?? parent?.fileUri;
 
   int get modifiers;
 
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index fb021d6..a302a71 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -8,7 +8,7 @@
 
 import 'builder.dart'
     show
-        Builder,
+        Declaration,
         InvalidTypeBuilder,
         PrefixBuilder,
         QualifiedName,
@@ -21,7 +21,7 @@
 
   List<T> arguments;
 
-  TypeDeclarationBuilder<T, R> builder;
+  TypeDeclarationBuilder<T, R> declaration;
 
   NamedTypeBuilder(this.name, this.arguments);
 
@@ -29,17 +29,17 @@
       [Message message]);
 
   @override
-  void bind(TypeDeclarationBuilder builder) {
-    this.builder = builder?.origin;
+  void bind(TypeDeclarationBuilder declaration) {
+    this.declaration = declaration?.origin;
   }
 
   @override
   void resolveIn(Scope scope, int charOffset, Uri fileUri) {
-    if (builder != null) return;
+    if (declaration != null) return;
     final name = this.name;
-    Builder member;
+    Declaration member;
     if (name is QualifiedName) {
-      var prefix = scope.lookup(name.prefix, charOffset, fileUri);
+      Declaration prefix = scope.lookup(name.prefix, charOffset, fileUri);
       if (prefix is PrefixBuilder) {
         member = prefix.lookup(name.suffix, name.charOffset, fileUri);
       }
@@ -47,10 +47,10 @@
       member = scope.lookup(name, charOffset, fileUri);
     }
     if (member is TypeDeclarationBuilder) {
-      builder = member.origin;
+      declaration = member.origin;
       return;
     }
-    builder = buildInvalidType(charOffset, fileUri);
+    declaration = buildInvalidType(charOffset, fileUri);
   }
 
   String get debugName => "NamedTypeBuilder";
diff --git a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart b/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
index c115f35..75e269a1 100644
--- a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
@@ -4,9 +4,9 @@
 
 library fasta.prefix_builder;
 
-import '../builder/builder.dart' show Builder, LibraryBuilder, Scope;
+import 'builder.dart' show Declaration, LibraryBuilder, Scope;
 
-class PrefixBuilder extends Builder {
+class PrefixBuilder extends Declaration {
   final String name;
 
   final Scope exportScope = new Scope.top();
@@ -18,19 +18,20 @@
   @override
   final int charOffset;
 
-  PrefixBuilder(this.name, this.deferred, this.parent, this.charOffset)
-      : super(parent, charOffset, parent.fileUri);
+  PrefixBuilder(this.name, this.deferred, this.parent, this.charOffset);
 
-  Builder lookup(String name, int charOffset, Uri fileUri) {
+  Uri get fileUri => parent.fileUri;
+
+  Declaration lookup(String name, int charOffset, Uri fileUri) {
     return exportScope.lookup(name, charOffset, fileUri);
   }
 
-  void addToExportScope(String name, Builder member, int charOffset) {
-    Map<String, Builder> map =
+  void addToExportScope(String name, Declaration member, int charOffset) {
+    Map<String, Declaration> map =
         member.isSetter ? exportScope.setters : exportScope.local;
-    Builder existing = map[name];
+    Declaration existing = map[name];
     if (existing != null) {
-      map[name] = parent.buildAmbiguousBuilder(
+      map[name] = parent.computeAmbiguousDeclaration(
           name, existing, member, charOffset,
           isExport: true);
     } else {
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 9fea77d..73020a5 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -11,7 +11,7 @@
 
 import 'builder.dart'
     show
-        Builder,
+        Declaration,
         FormalParameterBuilder,
         LibraryBuilder,
         MemberBuilder,
@@ -68,7 +68,7 @@
   /// Language Specifiction, 4th ed, section 9.2.
   Scope computeFormalParameterScope(Scope parent) {
     if (formals == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
+    Map<String, Declaration> local = <String, Declaration>{};
     for (FormalParameterBuilder formal in formals) {
       if (!isConstructor || !formal.hasThis) {
         local[formal.name] = formal;
@@ -95,7 +95,7 @@
     // parameter initializer scope.
 
     if (formals == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
+    Map<String, Declaration> local = <String, Declaration>{};
     for (FormalParameterBuilder formal in formals) {
       local[formal.name] = formal.forFormalParameterInitializerScope();
     }
@@ -108,7 +108,7 @@
   /// to support generic methods.
   Scope computeTypeParameterScope(Scope parent) {
     if (typeVariables == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
+    Map<String, Declaration> local = <String, Declaration>{};
     for (TypeVariableBuilder variable in typeVariables) {
       local[variable.name] = variable;
     }
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index 12346f1..c8ec2d5 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -5,7 +5,12 @@
 library fasta.type_declaration_builder;
 
 import 'builder.dart'
-    show Builder, LibraryBuilder, MetadataBuilder, ModifierBuilder, TypeBuilder;
+    show
+        Declaration,
+        LibraryBuilder,
+        MetadataBuilder,
+        ModifierBuilder,
+        TypeBuilder;
 
 abstract class TypeDeclarationBuilder<T extends TypeBuilder, R>
     extends ModifierBuilder {
@@ -15,7 +20,7 @@
 
   final String name;
 
-  Builder parent;
+  Declaration parent;
 
   TypeDeclarationBuilder(
       this.metadata, this.modifiers, this.name, this.parent, int charOffset,
diff --git a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
index c539213..afe2060 100644
--- a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
+++ b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
@@ -29,11 +29,11 @@
   void checkType() {
     TypeBuilder resolvedType = builder;
     if (resolvedType is NamedTypeBuilder) {
-      TypeDeclarationBuilder declaration = resolvedType.builder;
+      TypeDeclarationBuilder declaration = resolvedType.declaration;
       if (declaration is ClassBuilder) {
         if (resolvedType.arguments != null &&
             resolvedType.arguments.length != declaration.typeVariablesCount) {
-          resolvedType.builder = resolvedType.buildInvalidType(
+          resolvedType.declaration = resolvedType.buildInvalidType(
               charOffset,
               fileUri,
               templateTypeArgumentMismatch.withArguments(
@@ -42,7 +42,7 @@
       } else if (declaration is FunctionTypeAliasBuilder) {
         if (resolvedType.arguments != null &&
             resolvedType.arguments.length != declaration.typeVariablesCount) {
-          resolvedType.builder = resolvedType.buildInvalidType(
+          resolvedType.declaration = resolvedType.buildInvalidType(
               charOffset,
               fileUri,
               templateTypeArgumentMismatch.withArguments(
@@ -56,7 +56,7 @@
   void normalizeType() {
     TypeBuilder resolvedType = builder;
     if (resolvedType is NamedTypeBuilder) {
-      TypeDeclarationBuilder declaration = resolvedType.builder;
+      TypeDeclarationBuilder declaration = resolvedType.declaration;
       if (declaration is ClassBuilder) {
         if (resolvedType.arguments != null &&
             resolvedType.arguments.length != declaration.typeVariablesCount) {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 5a29dbe..78295a0 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -25,7 +25,7 @@
 
 import '../kernel/kernel_builder.dart'
     show
-        Builder,
+        Declaration,
         DynamicTypeBuilder,
         InvalidTypeBuilder,
         KernelInvalidTypeBuilder,
@@ -105,22 +105,23 @@
     }
   }
 
-  Builder addBuilder(String name, Builder builder, int charOffset) {
+  @override
+  Declaration addBuilder(String name, Declaration declaration, int charOffset) {
     if (name == null || name.isEmpty) return null;
-    bool isSetter = builder.isSetter;
+    bool isSetter = declaration.isSetter;
     if (isSetter) {
-      scopeBuilder.addSetter(name, builder);
+      scopeBuilder.addSetter(name, declaration);
     } else {
-      scopeBuilder.addMember(name, builder);
+      scopeBuilder.addMember(name, declaration);
     }
     if (!name.startsWith("_")) {
       if (isSetter) {
-        exportScopeBuilder.addSetter(name, builder);
+        exportScopeBuilder.addSetter(name, declaration);
       } else {
-        exportScopeBuilder.addMember(name, builder);
+        exportScopeBuilder.addMember(name, declaration);
       }
     }
-    return builder;
+    return declaration;
   }
 
   void addTypedef(Typedef typedef) {
@@ -129,13 +130,14 @@
   }
 
   @override
-  void addToScope(String name, Builder member, int charOffset, bool isImport) {
+  void addToScope(
+      String name, Declaration member, int charOffset, bool isImport) {
     unimplemented("addToScope", charOffset, fileUri);
   }
 
   @override
-  Builder buildAmbiguousBuilder(
-      String name, Builder builder, Builder other, int charOffset,
+  Declaration computeAmbiguousDeclaration(
+      String name, Declaration builder, Declaration other, int charOffset,
       {bool isExport: false, bool isImport: false}) {
     if (builder == other) return builder;
     if (builder is InvalidTypeBuilder) return builder;
@@ -154,17 +156,17 @@
 
   void finalizeExports() {
     unserializableExports?.forEach((String name, String message) {
-      Builder builder;
+      Declaration declaration;
       switch (name) {
         case "dynamic":
         case "void":
           // TODO(ahe): It's likely that we shouldn't be exporting these types
           // from dart:core, and this case can be removed.
-          builder = loader.coreLibrary.exportScopeBuilder[name];
+          declaration = loader.coreLibrary.exportScopeBuilder[name];
           break;
 
         default:
-          builder = new KernelInvalidTypeBuilder(
+          declaration = new KernelInvalidTypeBuilder(
               name,
               -1,
               null,
@@ -172,7 +174,7 @@
                   ? null
                   : templateUnspecified.withArguments(message));
       }
-      exportScopeBuilder.addMember(name, builder);
+      exportScopeBuilder.addMember(name, declaration);
     });
 
     for (var reference in library.additionalExports) {
@@ -203,22 +205,22 @@
             -1,
             fileUri);
       }
-      Builder builder;
+      Declaration declaration;
       if (isSetter) {
-        builder = library.exportScope.setters[name];
-        exportScopeBuilder.addSetter(name, builder);
+        declaration = library.exportScope.setters[name];
+        exportScopeBuilder.addSetter(name, declaration);
       } else {
-        builder = library.exportScope.local[name];
-        exportScopeBuilder.addMember(name, builder);
+        declaration = library.exportScope.local[name];
+        exportScopeBuilder.addMember(name, declaration);
       }
-      if (builder == null) {
+      if (declaration == null) {
         internalProblem(
             templateUnspecified.withArguments(
                 "Exported element '$name' not found in '$libraryUri'."),
             -1,
             fileUri);
       }
-      assert(node == builder.target);
+      assert(node == declaration.target);
     }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index 7845ca1..7b54cd3 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -9,7 +9,7 @@
 
 import '../kernel/kernel_builder.dart'
     show
-        Builder,
+        Declaration,
         MemberBuilder,
         isRedirectingGenerativeConstructorImplementation;
 
@@ -23,7 +23,7 @@
 
   final Member member;
 
-  DillMemberBuilder(Member member, Builder parent)
+  DillMemberBuilder(Member member, Declaration parent)
       : modifiers = computeModifiers(member),
         member = member,
         super(parent, member.fileOffset);
diff --git a/pkg/front_end/lib/src/fasta/export.dart b/pkg/front_end/lib/src/fasta/export.dart
index 78723ce..2284a12 100644
--- a/pkg/front_end/lib/src/fasta/export.dart
+++ b/pkg/front_end/lib/src/fasta/export.dart
@@ -4,7 +4,7 @@
 
 library fasta.export;
 
-import 'builder/builder.dart' show Builder, LibraryBuilder;
+import 'builder/builder.dart' show Declaration, LibraryBuilder;
 
 import 'combinator.dart' show Combinator;
 
@@ -23,7 +23,7 @@
 
   Uri get fileUri => exporter.fileUri;
 
-  bool addToExportScope(String name, Builder member) {
+  bool addToExportScope(String name, Declaration member) {
     if (combinators != null) {
       for (Combinator combinator in combinators) {
         if (combinator.isShow && !combinator.names.contains(name)) return false;
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 5f91fd5..1f491c2 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -1046,6 +1046,16 @@
     tip: r"""Try removing the return type.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorWithTypeParameters =
+    messageConstructorWithTypeParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorWithTypeParameters = const MessageCode(
+    "ConstructorWithTypeParameters",
+    severity: Severity.error,
+    message: r"""Constructors can't have type parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeContinueOutsideOfLoop = messageContinueOutsideOfLoop;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2814,6 +2824,59 @@
         r"""Try removing the initializer, or using a different kind of loop.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType _type,
+        DartType
+            _type2)> templateInitializingFormalTypeMismatch = const Template<
+        Message Function(String name, DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2).""",
+    tipTemplate:
+        r"""Try changing the type of parameter '#name' to a subtype of #type2.""",
+    withArguments: _withArgumentsInitializingFormalTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type, DartType _type2)>
+    codeInitializingFormalTypeMismatch =
+    const Code<Message Function(String name, DartType _type, DartType _type2)>(
+        "InitializingFormalTypeMismatch",
+        templateInitializingFormalTypeMismatch,
+        analyzerCode: "INVALID_PARAMETER_DECLARATION",
+        dart2jsCode: "*fatal*",
+        severity: Severity.errorLegacyWarning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializingFormalTypeMismatch(
+    String name, DartType _type, DartType _type2) {
+  NameSystem nameSystem = new NameSystem();
+  StringBuffer buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type);
+  String type = '$buffer';
+
+  buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type2);
+  String type2 = '$buffer';
+
+  return new Message(codeInitializingFormalTypeMismatch,
+      message:
+          """The type of parameter '$name' ($type) is not a subtype of the corresponding field's type ($type2).""",
+      tip: """Try changing the type of parameter '$name' to a subtype of $type2.""",
+      arguments: {'name': name, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInitializingFormalTypeMismatchField =
+    messageInitializingFormalTypeMismatchField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInitializingFormalTypeMismatchField =
+    const MessageCode("InitializingFormalTypeMismatchField",
+        severity: Severity.context,
+        message: r"""The field that corresponds to the parameter.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Uri uri_)> templateInputFileNotFound =
     const Template<Message Function(Uri uri_)>(
         messageTemplate: r"""Input file not found: #uri.""",
diff --git a/pkg/front_end/lib/src/fasta/import.dart b/pkg/front_end/lib/src/fasta/import.dart
index d48f2a2..e27b1e0 100644
--- a/pkg/front_end/lib/src/fasta/import.dart
+++ b/pkg/front_end/lib/src/fasta/import.dart
@@ -6,7 +6,7 @@
 
 import 'package:kernel/ast.dart' show LibraryDependency;
 
-import 'builder/builder.dart' show Builder, LibraryBuilder;
+import 'builder/builder.dart' show Declaration, LibraryBuilder;
 
 import 'kernel/kernel_builder.dart' show toKernelCombinators;
 
@@ -16,8 +16,6 @@
 
 import 'configuration.dart' show Configuration;
 
-typedef void AddToScope(String name, Builder member);
-
 class Import {
   /// The library that is importing [imported];
   final LibraryBuilder importer;
@@ -60,17 +58,17 @@
 
   void finalizeImports(LibraryBuilder importer) {
     if (nativeImportUri != null) return;
-    AddToScope add;
+    void Function(String, Declaration) add;
     if (prefixBuilder == null) {
-      add = (String name, Builder member) {
+      add = (String name, Declaration member) {
         importer.addToScope(name, member, charOffset, true);
       };
     } else {
-      add = (String name, Builder member) {
+      add = (String name, Declaration member) {
         prefixBuilder.addToExportScope(name, member, charOffset);
       };
     }
-    imported.exportScope.forEach((String name, Builder member) {
+    imported.exportScope.forEach((String name, Declaration member) {
       if (combinators != null) {
         for (Combinator combinator in combinators) {
           if (combinator.isShow && !combinator.names.contains(name)) return;
@@ -80,7 +78,8 @@
       add(name, member);
     });
     if (prefixBuilder != null) {
-      Builder existing = importer.addBuilder(prefix, prefixBuilder, charOffset);
+      Declaration existing =
+          importer.addBuilder(prefix, prefixBuilder, charOffset);
       if (existing == prefixBuilder) {
         importer.addToScope(prefix, prefixBuilder, prefixCharOffset, true);
       }
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index b0297d0..0c388d7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -90,6 +90,7 @@
         ThisAccessGenerator,
         ThisPropertyAccessGenerator,
         TypeUseGenerator,
+        UnlinkedGenerator,
         UnresolvedNameGenerator,
         VariableUseGenerator,
         buildIsNull;
@@ -117,6 +118,7 @@
 abstract class BodyBuilder<Expression, Statement, Arguments>
     extends ScopeListener<JumpTarget>
     implements ExpressionGeneratorHelper<Expression, Statement, Arguments> {
+  // TODO(ahe): Rename [library] to 'part'.
   @override
   final KernelLibraryBuilder library;
 
@@ -148,6 +150,7 @@
   // https://github.com/dart-lang/sdk/issues/28989.
   final bool ignoreMainInGetMainClosure;
 
+  // TODO(ahe): Consider renaming [uri] to 'partUri'.
   @override
   final Uri uri;
 
@@ -210,9 +213,9 @@
   Map<String, int> initializedFields;
 
   BodyBuilder(
-      KernelLibraryBuilder library,
+      this.library,
       this.member,
-      Scope scope,
+      this.enclosingScope,
       this.formalParameterScope,
       this.hierarchy,
       this.coreTypes,
@@ -220,9 +223,7 @@
       this.isInstanceMember,
       this.uri,
       this._typeInferrer)
-      : enclosingScope = scope,
-        library = library,
-        enableNative =
+      : enableNative =
             library.loader.target.backendTarget.enableNative(library.uri),
         stringExpectedAfterNative =
             library.loader.target.backendTarget.nativeExtensionExpectsString,
@@ -231,7 +232,38 @@
         needsImplicitSuperInitializer =
             coreTypes?.objectClass != classBuilder?.cls,
         typePromoter = _typeInferrer?.typePromoter,
-        super(scope);
+        super(enclosingScope);
+
+  BodyBuilder.withParents(
+      KernelFieldBuilder field,
+      KernelLibraryBuilder part,
+      KernelClassBuilder classBuilder,
+      ClassHierarchy hierarchy,
+      CoreTypes coreTypes,
+      TypeInferrer typeInferrer)
+      : this(
+            part,
+            field,
+            classBuilder?.scope ?? field.library.scope,
+            null,
+            hierarchy,
+            coreTypes,
+            classBuilder,
+            field.isInstanceMember,
+            field.fileUri,
+            typeInferrer);
+
+  BodyBuilder.forField(KernelFieldBuilder field, ClassHierarchy hierarchy,
+      CoreTypes coreTypes, TypeInferrer typeInferrer)
+      : this.withParents(
+            field,
+            field.parent is KernelClassBuilder
+                ? field.parent.parent
+                : field.parent,
+            field.parent is KernelClassBuilder ? field.parent : null,
+            hierarchy,
+            coreTypes,
+            typeInferrer);
 
   bool get hasParserError => recoverableErrors.isNotEmpty;
 
@@ -260,7 +292,7 @@
   @override
   Expression toValue(Object node) {
     if (node is Generator) {
-      return toExpression(node.buildSimpleRead());
+      return node.buildSimpleRead();
     } else if (node is Expression) {
       return node;
     } else if (node is PrefixBuilder) {
@@ -277,7 +309,7 @@
   }
 
   Expression toEffect(Object node) {
-    if (node is Generator) return toExpression(node.buildForEffect());
+    if (node is Generator) return node.buildForEffect();
     return toValue(node);
   }
 
@@ -321,9 +353,9 @@
     Scope outerSwitchScope = pop();
     if (switchScope.unclaimedForwardDeclarations != null) {
       switchScope.unclaimedForwardDeclarations
-          .forEach((String name, Builder builder) {
+          .forEach((String name, Declaration declaration) {
         if (outerSwitchScope == null) {
-          JumpTarget target = builder;
+          JumpTarget target = declaration;
           for (kernel.Statement statement in target.users) {
             statement.parent.replaceChild(
                 statement,
@@ -331,7 +363,7 @@
                     fasta.templateLabelNotFound.withArguments(name)));
           }
         } else {
-          outerSwitchScope.forwardDeclareLabel(name, builder);
+          outerSwitchScope.forwardDeclareLabel(name, declaration);
         }
       });
     }
@@ -358,9 +390,9 @@
     }
   }
 
-  void declareVariable(VariableDeclaration variable, Scope scope) {
-    String name = variable.name;
-    Builder existing = scope.local[name];
+  void declareVariable(Object variable, Scope scope) {
+    String name = forest.getVariableDeclarationName(variable);
+    Declaration existing = scope.local[name];
     if (existing != null) {
       // This reports an error for duplicated declarations in the same scope:
       // `{ var x; var x; }`
@@ -373,7 +405,7 @@
       return;
     }
     LocatedMessage context = scope.declare(
-        variable.name,
+        forest.getVariableDeclarationName(variable),
         new KernelVariableBuilder(
             variable, member ?? classBuilder ?? library, uri),
         uri);
@@ -554,7 +586,8 @@
                   true,
                   formal.name,
                   formal.charOffset,
-                  toExpression(new VariableGet(formal.declaration)));
+                  toExpression(new VariableGet(formal.declaration)),
+                  formalType: formal.declaration.type);
             }
             member.addInitializer(initializer, _typeInferrer);
           }
@@ -766,6 +799,14 @@
     return toExpression(fakeReturn.expression);
   }
 
+  Expression parseFieldInitializer(Token token) {
+    Parser parser = new Parser(this);
+    token = parser.parseExpression(parser.syntheticPreviousToken(token));
+    Expression expression = popForValue();
+    checkEmpty(token.charOffset);
+    return expression;
+  }
+
   void finishConstructor(
       KernelConstructorBuilder builder, AsyncMarker asyncModifier) {
     /// Quotes below are from [Dart Programming Language Specification, 4th
@@ -1037,13 +1078,10 @@
   void doLogicalExpression(Token token) {
     Expression argument = popForValue();
     Expression receiver = pop();
-    var logicalExpression = new ShadowLogicalExpression(
-        toKernelExpression(receiver),
-        token.stringValue,
-        toKernelExpression(argument))
-      ..fileOffset = offsetForToken(token);
+    Expression logicalExpression =
+        forest.logicalExpression(receiver, token, argument);
     typePromoter.exitLogicalExpression(
-        toKernelExpression(argument), logicalExpression);
+        toKernelExpression(argument), toKernelExpression(logicalExpression));
     push(logicalExpression);
   }
 
@@ -1294,7 +1332,7 @@
         // objects directly.
         var supertype = builder.supertype;
         if (supertype is NamedTypeBuilder) {
-          var builder = supertype.builder;
+          var builder = supertype.declaration;
           if (builder is ClassBuilder) return builder;
         }
         return null;
@@ -1353,20 +1391,26 @@
   scopeLookup(Scope scope, String name, Token token,
       {bool isQualified: false, PrefixBuilder prefix}) {
     int charOffset = offsetForToken(token);
-    Builder builder = scope.lookup(name, charOffset, uri);
-    if (builder == null && prefix == null && (classBuilder?.isPatch ?? false)) {
+    Declaration declaration = scope.lookup(name, charOffset, uri);
+    if (declaration is UnlinkedDeclaration) {
+      return new UnlinkedGenerator(this, token, declaration);
+    }
+    if (declaration == null &&
+        prefix == null &&
+        (classBuilder?.isPatch ?? false)) {
       // The scope of a patched method includes the origin class.
-      builder =
+      declaration =
           classBuilder.origin.findStaticBuilder(name, charOffset, uri, library);
     }
-    if (builder != null && member.isField && builder.isInstanceMember) {
+    if (declaration != null && member.isField && declaration.isInstanceMember) {
       return new IncompleteErrorGenerator(this, token,
           fasta.templateThisAccessInFieldInitializer.withArguments(name));
     }
-    if (builder == null || (!isInstanceContext && builder.isInstanceMember)) {
+    if (declaration == null ||
+        (!isInstanceContext && declaration.isInstanceMember)) {
       Name n = new Name(name, library.library);
       if (!isQualified && isInstanceContext) {
-        assert(builder == null);
+        assert(declaration == null);
         if (constantContext != ConstantContext.none || member.isField) {
           return new UnresolvedNameGenerator(this, token, n);
         }
@@ -1380,23 +1424,23 @@
       } else {
         return new UnresolvedNameGenerator(this, token, n);
       }
-    } else if (builder.isTypeDeclaration) {
+    } else if (declaration.isTypeDeclaration) {
       if (constantContext != ConstantContext.none &&
-          builder.isTypeVariable &&
+          declaration.isTypeVariable &&
           !member.isConstructor) {
         deprecated_addCompileTimeError(
             charOffset, "Not a constant expression.");
       }
       TypeUseGenerator<Expression, Statement, Arguments> generator =
           new TypeUseGenerator<Expression, Statement, Arguments>(
-              this, token, prefix, charOffset, builder, name);
+              this, token, prefix, charOffset, declaration, name);
       return (prefix?.deferred == true)
           ? new DeferredAccessGenerator<Expression, Statement, Arguments>(
               this, token, prefix, generator)
           : generator;
-    } else if (builder.isLocal) {
+    } else if (declaration.isLocal) {
       if (constantContext != ConstantContext.none &&
-          !builder.isConst &&
+          !declaration.isConst &&
           !member.isConstructor) {
         deprecated_addCompileTimeError(
             charOffset, "Not a constant expression.");
@@ -1405,21 +1449,21 @@
       // VariableDeclaration being final. See
       // [ProcedureBuilder.computeFormalParameterInitializerScope]. If that
       // wasn't the case, we could always use [VariableUseGenerator].
-      if (builder.isFinal) {
-        var fact =
-            typePromoter.getFactForAccess(builder.target, functionNestingLevel);
+      if (declaration.isFinal) {
+        var fact = typePromoter.getFactForAccess(
+            declaration.target, functionNestingLevel);
         var scope = typePromoter.currentScope;
         return new ReadOnlyAccessGenerator<Expression, Statement, Arguments>(
             this,
             token,
-            toExpression(new ShadowVariableGet(builder.target, fact, scope)
+            toExpression(new ShadowVariableGet(declaration.target, fact, scope)
               ..fileOffset = charOffset),
             name);
       } else {
         return new VariableUseGenerator<Expression, Statement, Arguments>(
-            this, token, builder.target);
+            this, token, declaration.target);
       }
-    } else if (builder.isInstanceMember) {
+    } else if (declaration.isInstanceMember) {
       if (constantContext != ConstantContext.none &&
           !inInitializer &&
           // TODO(ahe): This is a hack because Fasta sets up the scope
@@ -1433,26 +1477,26 @@
       Name n = new Name(name, library.library);
       Member getter;
       Member setter;
-      if (builder is AccessErrorBuilder) {
-        setter = builder.parent.target;
+      if (declaration is AccessErrorBuilder) {
+        setter = declaration.parent.target;
         getter = lookupInstanceMember(n);
       } else {
-        getter = builder.target;
+        getter = declaration.target;
         setter = lookupInstanceMember(n, isSetter: true);
       }
       return new ThisPropertyAccessGenerator<Expression, Statement, Arguments>(
           this, token, n, getter, setter);
-    } else if (builder.isRegularMethod) {
-      assert(builder.isStatic || builder.isTopLevel);
+    } else if (declaration.isRegularMethod) {
+      assert(declaration.isStatic || declaration.isTopLevel);
       StaticAccessGenerator<Expression, Statement, Arguments> generator =
           new StaticAccessGenerator<Expression, Statement, Arguments>(
-              this, token, builder.target, null);
+              this, token, declaration.target, null);
       return (prefix?.deferred == true)
           ? new DeferredAccessGenerator<Expression, Statement, Arguments>(
               this, token, prefix, generator)
           : generator;
-    } else if (builder is PrefixBuilder) {
-      if (constantContext != ConstantContext.none && builder.deferred) {
+    } else if (declaration is PrefixBuilder) {
+      if (constantContext != ConstantContext.none && declaration.deferred) {
         deprecated_addCompileTimeError(
             charOffset,
             "'$name' can't be used in a constant expression because it's "
@@ -1461,23 +1505,24 @@
             "You might try moving the constant to the deferred library, "
             "or removing 'deferred' from the import.");
       }
-      return builder;
-    } else if (builder is LoadLibraryBuilder) {
+      return declaration;
+    } else if (declaration is LoadLibraryBuilder) {
       return new LoadLibraryGenerator<Expression, Statement, Arguments>(
-          this, token, builder);
+          this, token, declaration);
     } else {
-      if (builder.hasProblem && builder is! AccessErrorBuilder) return builder;
-      Builder setter;
-      if (builder.isSetter) {
-        setter = builder;
-      } else if (builder.isGetter) {
+      if (declaration.hasProblem && declaration is! AccessErrorBuilder)
+        return declaration;
+      Declaration setter;
+      if (declaration.isSetter) {
+        setter = declaration;
+      } else if (declaration.isGetter) {
         setter = scope.lookupSetter(name, charOffset, uri);
-      } else if (builder.isField && !builder.isFinal) {
-        setter = builder;
+      } else if (declaration.isField && !declaration.isFinal) {
+        setter = declaration;
       }
       StaticAccessGenerator<Expression, Statement, Arguments> generator =
           new StaticAccessGenerator<Expression, Statement,
-              Arguments>.fromBuilder(this, builder, token, setter);
+              Arguments>.fromBuilder(this, declaration, token, setter);
       if (constantContext != ConstantContext.none) {
         Member readTarget = generator.readTarget;
         if (!(readTarget is Field && readTarget.isConst ||
@@ -2205,8 +2250,8 @@
     debugEvent("FormalParameter");
     if (thisKeyword != null) {
       if (!inConstructor) {
-        deprecated_addCompileTimeError(thisKeyword.charOffset,
-            "'this' parameters can only be used on constructors.");
+        handleRecoverableError(fasta.messageFieldInitializerOutsideConstructor,
+            thisKeyword, thisKeyword);
         thisKeyword = null;
       }
     }
@@ -2849,7 +2894,8 @@
         return deprecated_buildCompileTimeError(
             "An enum class can't be instantiated.", nameToken.charOffset);
       }
-      Builder b = type.findConstructorOrFactory(name, charOffset, uri, library);
+      Declaration b =
+          type.findConstructorOrFactory(name, charOffset, uri, library);
       Member target;
       Member initialTarget;
       List<DartType> targetTypeArguments;
@@ -3823,7 +3869,8 @@
       [int charOffset = -1]) {
     addProblemErrorIfConst(message, charOffset, className.length);
     // TODO(ahe): The following doesn't make sense to Analyzer AST.
-    Builder constructor = library.loader.getAbstractClassInstantiationError();
+    Declaration constructor =
+        library.loader.getAbstractClassInstantiationError();
     return toExpression(new Throw(toKernelExpression(buildStaticInvocation(
         constructor.target,
         forest.arguments(<Expression>[
@@ -3872,10 +3919,20 @@
     return initializer;
   }
 
+  /// Parameter [formalType] should only be passed in the special case of
+  /// building a field initializer as a desugaring of an initializing formal
+  /// parameter.  The spec says the following:
+  ///
+  /// "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
+  /// _Tid_, where _Tid_ is the type of the instance variable named _id_ in the
+  /// immediately enclosing class.  It is a static warning if the static type of
+  /// _id_ is not a subtype of _Tid_."
   @override
   Initializer buildFieldInitializer(
-      bool isSynthetic, String name, int offset, Expression expression) {
-    Builder builder =
+      bool isSynthetic, String name, int offset, Expression expression,
+      {DartType formalType}) {
+    Declaration builder =
         classBuilder.scope.local[name] ?? classBuilder.origin.scope.local[name];
     if (builder is KernelFieldBuilder && builder.isInstanceMember) {
       initializedFields ??= <String, int>{};
@@ -3897,7 +3954,7 @@
                   .withArguments(name)
                   .withLocation(uri, builder.charOffset, noLength)
             ]);
-        Builder constructor =
+        Declaration constructor =
             library.loader.getDuplicatedFieldInitializerError();
         return buildInvalidInitializer(
             toExpression(new Throw(toKernelExpression(buildStaticInvocation(
@@ -3908,6 +3965,21 @@
                 charOffset: offset)))),
             offset);
       } else {
+        if (library.loader.target.strongMode &&
+            formalType != null &&
+            !_typeInferrer.typeSchemaEnvironment
+                .isSubtypeOf(formalType, builder.field.type)) {
+          library.addProblem(
+              fasta.templateInitializingFormalTypeMismatch
+                  .withArguments(name, formalType, builder.field.type),
+              offset,
+              noLength,
+              uri,
+              context: [
+                fasta.messageInitializingFormalTypeMismatchField
+                    .withLocation(builder.fileUri, builder.charOffset, noLength)
+              ]);
+        }
         return new ShadowFieldInitializer(
             builder.field, toKernelExpression(expression))
           ..fileOffset = offset
@@ -4221,16 +4293,24 @@
   String toString() => "initialized-identifier($name, $initializer)";
 }
 
-class JumpTarget<Statement> extends Builder {
+class JumpTarget<Statement> extends Declaration {
   final List<Statement> users = <Statement>[];
 
   final JumpTargetKind kind;
 
   final int functionNestingLevel;
 
-  JumpTarget(this.kind, this.functionNestingLevel, MemberBuilder member,
-      int charOffset)
-      : super(member, charOffset, member.fileUri);
+  @override
+  final MemberBuilder parent;
+
+  @override
+  final int charOffset;
+
+  JumpTarget(
+      this.kind, this.functionNestingLevel, this.parent, this.charOffset);
+
+  @override
+  Uri get fileUri => parent.fileUri;
 
   bool get isBreakTarget => kind == JumpTargetKind.Break;
 
@@ -4286,22 +4366,31 @@
   String get fullNameForErrors => "<jump-target>";
 }
 
-class LabelTarget<Statement> extends Builder implements JumpTarget<Statement> {
+class LabelTarget<Statement> extends Declaration
+    implements JumpTarget<Statement> {
   final List<Object> labels;
 
+  @override
+  final MemberBuilder parent;
+
   final JumpTarget breakTarget;
 
   final JumpTarget continueTarget;
 
   final int functionNestingLevel;
 
-  LabelTarget(this.labels, MemberBuilder member, this.functionNestingLevel,
-      int charOffset)
+  @override
+  final int charOffset;
+
+  LabelTarget(
+      this.labels, this.parent, this.functionNestingLevel, this.charOffset)
       : breakTarget = new JumpTarget<Statement>(
-            JumpTargetKind.Break, functionNestingLevel, member, charOffset),
+            JumpTargetKind.Break, functionNestingLevel, parent, charOffset),
         continueTarget = new JumpTarget<Statement>(
-            JumpTargetKind.Continue, functionNestingLevel, member, charOffset),
-        super(member, charOffset, member.fileUri);
+            JumpTargetKind.Continue, functionNestingLevel, parent, charOffset);
+
+  @override
+  Uri get fileUri => parent.fileUri;
 
   bool get hasUsers => breakTarget.hasUsers || continueTarget.hasUsers;
 
@@ -4405,18 +4494,18 @@
         typeParameters: typeParameters);
   }
 
-  Scope computeFormalParameterScope(Scope parent, Builder builder,
+  Scope computeFormalParameterScope(Scope parent, Declaration declaration,
       ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper) {
     if (required.length == 0 && optional == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
+    Map<String, Declaration> local = <String, Declaration>{};
 
     for (VariableDeclaration parameter in required) {
       if (local[parameter.name] != null) {
         helper.deprecated_addCompileTimeError(
             parameter.fileOffset, "Duplicated name.");
       }
-      local[parameter.name] =
-          new KernelVariableBuilder(parameter, builder, builder.fileUri);
+      local[parameter.name] = new KernelVariableBuilder(
+          parameter, declaration, declaration.fileUri);
     }
     if (optional != null) {
       for (VariableDeclaration parameter in optional.formals) {
@@ -4424,8 +4513,8 @@
           helper.deprecated_addCompileTimeError(
               parameter.fileOffset, "Duplicated name.");
         }
-        local[parameter.name] =
-            new KernelVariableBuilder(parameter, builder, builder.fileUri);
+        local[parameter.name] = new KernelVariableBuilder(
+            parameter, declaration, declaration.fileUri);
       }
     }
     return new Scope(local, null, parent, "formals", isModifiable: false);
@@ -4458,7 +4547,7 @@
 String getNodeName(Object node) {
   if (node is Identifier) {
     return node.name;
-  } else if (node is Builder) {
+  } else if (node is Declaration) {
     return node.fullNameForErrors;
   } else if (node is ThisAccessGenerator) {
     return node.isSuper ? "super" : "this";
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index ad42775..c69b304 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -15,11 +15,12 @@
         messageInvalidInitializer,
         templateDeferredTypeAnnotation,
         templateIntegerLiteralIsOutOfRange,
-        templateNotAType;
+        templateNotAType,
+        templateUnresolvedPrefixInTypeAnnotation;
 
 import '../names.dart' show lengthName;
 
-import '../parser.dart' show lengthForToken, offsetForToken;
+import '../parser.dart' show lengthForToken, lengthOfSpan, offsetForToken;
 
 import '../problems.dart' show unhandled, unsupported;
 
@@ -31,7 +32,8 @@
         Identifier,
         LoadLibraryBuilder,
         PrefixBuilder,
-        TypeDeclarationBuilder;
+        TypeDeclarationBuilder,
+        UnlinkedDeclaration;
 
 import 'kernel_ast_api.dart'
     show
@@ -47,8 +49,8 @@
 import 'kernel_builder.dart'
     show
         AccessErrorBuilder,
-        Builder,
         BuiltinTypeBuilder,
+        Declaration,
         FunctionTypeAliasBuilder,
         KernelClassBuilder,
         KernelFunctionTypeAliasBuilder,
@@ -67,7 +69,6 @@
         ParenthesizedExpressionGenerator,
         SendAccessGenerator,
         ThisAccessGenerator,
-        UnresolvedNameGenerator,
         buildIsNull;
 
 abstract class ExpressionGenerator<Expression, Statement, Arguments> {
@@ -455,24 +456,24 @@
 
   factory StaticAccessGenerator.fromBuilder(
       ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
-      Builder builder,
+      Declaration declaration,
       Token token,
-      Builder builderSetter) {
-    if (builder is AccessErrorBuilder) {
-      AccessErrorBuilder error = builder;
-      builder = error.builder;
+      Declaration builderSetter) {
+    if (declaration is AccessErrorBuilder) {
+      AccessErrorBuilder error = declaration;
+      declaration = error.builder;
       // We should only see an access error here if we've looked up a setter
       // when not explicitly looking for a setter.
-      assert(builder.isSetter);
-    } else if (builder.target == null) {
+      assert(declaration.isSetter);
+    } else if (declaration.target == null) {
       return unhandled(
-          "${builder.runtimeType}",
+          "${declaration.runtimeType}",
           "StaticAccessGenerator.fromBuilder",
           offsetForToken(token),
           helper.uri);
     }
-    Member getter = builder.target.hasGetter ? builder.target : null;
-    Member setter = builder.target.hasSetter ? builder.target : null;
+    Member getter = declaration.target.hasGetter ? declaration.target : null;
+    Member setter = declaration.target.hasSetter ? declaration.target : null;
     if (setter == null) {
       if (builderSetter?.target?.hasSetter ?? false) {
         setter = builderSetter.target;
@@ -720,7 +721,8 @@
   @override
   buildPropertyAccess(
       IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
-    return this;
+    return send.withReceiver(buildSimpleRead(), operatorOffset,
+        isNullAware: isNullAware);
   }
 
   @override
@@ -797,3 +799,66 @@
         isSetter: true);
   }
 }
+
+abstract class UnresolvedNameGenerator<Expression, Statement, Arguments>
+    implements ErroneousExpressionGenerator<Expression, Statement, Arguments> {
+  factory UnresolvedNameGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Name name) {
+    return helper.forest.unresolvedNameGenerator(helper, token, name);
+  }
+
+  String get debugName => "UnresolvedNameGenerator";
+
+  Expression doInvocation(int charOffset, Arguments arguments) {
+    return buildError(arguments, offset: charOffset);
+  }
+
+  @override
+  DartType buildErroneousTypeNotAPrefix(Identifier suffix) {
+    helper.addProblem(
+        templateUnresolvedPrefixInTypeAnnotation.withArguments(
+            name.name, suffix.name),
+        offsetForToken(token),
+        lengthOfSpan(token, suffix.token));
+    return const InvalidType();
+  }
+
+  @override
+  Expression buildError(Arguments arguments,
+      {bool isGetter: false, bool isSetter: false, int offset}) {
+    offset ??= offsetForToken(this.token);
+    return helper.throwNoSuchMethodError(
+        storeOffset(forest.literalNull(null), offset),
+        plainNameForRead,
+        arguments,
+        offset,
+        isGetter: isGetter,
+        isSetter: isSetter);
+  }
+}
+
+abstract class UnlinkedGenerator<Expression, Statement, Arguments>
+    implements Generator<Expression, Statement, Arguments> {
+  factory UnlinkedGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      UnlinkedDeclaration declaration) {
+    return helper.forest.unlinkedGenerator(helper, token, declaration);
+  }
+
+  UnlinkedDeclaration get declaration;
+
+  @override
+  String get plainNameForRead => declaration.name;
+
+  @override
+  String get debugName => "UnlinkedGenerator";
+
+  @override
+  void printOn(StringSink sink) {
+    sink.write(", name: ");
+    sink.write(declaration.name);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 4d3404a..5351b10 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -80,7 +80,8 @@
   Initializer buildInvalidInitializer(Expression expression, [int offset]);
 
   Initializer buildFieldInitializer(
-      bool isSynthetic, String name, int offset, Expression expression);
+      bool isSynthetic, String name, int offset, Expression expression,
+      {DartType formalType});
 
   Initializer buildSuperInitializer(
       bool isSynthetic, Constructor constructor, Arguments arguments,
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 3acd9df..a976f3b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -58,6 +58,8 @@
         KernelThisIndexedAccessGenerator,
         KernelThisPropertyAccessGenerator,
         KernelTypeUseGenerator,
+        KernelUnlinkedGenerator,
+        KernelUnresolvedNameGenerator,
         KernelVariableUseGenerator;
 
 import 'kernel_shadow_ast.dart'
@@ -83,6 +85,7 @@
         ShadowLabeledStatement,
         ShadowListLiteral,
         ShadowLoadLibrary,
+        ShadowLogicalExpression,
         ShadowMapLiteral,
         ShadowNot,
         ShadowNullLiteral,
@@ -107,7 +110,8 @@
         Generator,
         LoadLibraryBuilder,
         PrefixBuilder,
-        TypeDeclarationBuilder;
+        TypeDeclarationBuilder,
+        UnlinkedDeclaration;
 
 /// A shadow tree factory.
 class Fangorn extends Forest<Expression, Statement, Token, Arguments> {
@@ -427,6 +431,14 @@
       statement;
 
   @override
+  Expression logicalExpression(
+      Expression leftOperand, Token operator, Expression rightOperand) {
+    return new ShadowLogicalExpression(
+        leftOperand, operator.stringValue, rightOperand)
+      ..fileOffset = offsetForToken(operator);
+  }
+
+  @override
   Expression notExpression(Expression operand, Token token) {
     return new ShadowNot(operand)..fileOffset = offsetForToken(token);
   }
@@ -537,6 +549,11 @@
   int getLabelOffset(Label label) => label.charOffset;
 
   @override
+  String getVariableDeclarationName(VariableDeclaration declaration) {
+    return declaration.name;
+  }
+
+  @override
   bool isBlock(Object node) => node is Block;
 
   @override
@@ -742,6 +759,22 @@
       Token token) {
     return new KernelLargeIntAccessGenerator(helper, token);
   }
+
+  @override
+  KernelUnresolvedNameGenerator unresolvedNameGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Name name) {
+    return new KernelUnresolvedNameGenerator(helper, token, name);
+  }
+
+  @override
+  KernelUnlinkedGenerator unlinkedGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      UnlinkedDeclaration declaration) {
+    return new KernelUnlinkedGenerator(helper, token, declaration);
+  }
 }
 
 class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 8509c30..ac39797 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -19,7 +19,11 @@
 import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
 
 import 'kernel_builder.dart'
-    show LoadLibraryBuilder, PrefixBuilder, TypeDeclarationBuilder;
+    show
+        LoadLibraryBuilder,
+        PrefixBuilder,
+        TypeDeclarationBuilder,
+        UnlinkedDeclaration;
 
 export 'body_builder.dart' show Identifier, Operator;
 
@@ -28,7 +32,11 @@
 export 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
 
 export 'kernel_builder.dart'
-    show LoadLibraryBuilder, PrefixBuilder, TypeDeclarationBuilder;
+    show
+        LoadLibraryBuilder,
+        PrefixBuilder,
+        TypeDeclarationBuilder,
+        UnlinkedDeclaration;
 
 /// A tree factory.
 ///
@@ -250,6 +258,11 @@
   Statement labeledStatement(
       LabelTarget<Statement> target, Statement statement);
 
+  /// Return a representation of a logical expression having the [leftOperand],
+  /// [rightOperand] and the [operator] (either `&&` or `||`).
+  Expression logicalExpression(
+      Expression leftOperand, Location operator, Expression rightOperand);
+
   Expression notExpression(Expression operand, Location location);
 
   /// Return a representation of a parenthesized condition consisting of the
@@ -317,6 +330,9 @@
   /// Return the offset of the given [label].
   int getLabelOffset(covariant label);
 
+  /// Return the name of the given variable [declaration].
+  String getVariableDeclarationName(covariant declaration);
+
   bool isBlock(Object node);
 
   /// Return `true` if the given [statement] is the representation of an empty
@@ -446,6 +462,16 @@
       ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
       Location location);
 
+  Generator<Expression, Statement, Arguments> unresolvedNameGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Location location,
+      kernel.Name name);
+
+  Generator<Expression, Statement, Arguments> unlinkedGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Location location,
+      UnlinkedDeclaration declaration);
+
   // TODO(ahe): Remove this method when all users are moved here.
   kernel.Arguments castArguments(Arguments arguments) {
     dynamic a = arguments;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
index f2ff3b6..9b1651a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
@@ -40,6 +40,10 @@
       : super(library, member, scope, formalParameterScope, hierarchy,
             coreTypes, classBuilder, isInstanceMember, uri, typeInferrer);
 
+  KernelBodyBuilder.forField(ModifierBuilder member, ClassHierarchy hierarchy,
+      CoreTypes coreTypes, TypeInferrer typeInferrer)
+      : super.forField(member, hierarchy, coreTypes, typeInferrer);
+
   @override
   void enterThenForTypePromotion(Expression condition) {
     typePromoter.enterThen(condition);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index aa4860e..a2fbeca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -4,6 +4,18 @@
 
 library fasta.kernel_builder;
 
+import 'package:kernel/ast.dart'
+    show
+        Combinator,
+        Constructor,
+        Initializer,
+        Procedure,
+        RedirectingInitializer;
+
+import '../combinator.dart' as fasta;
+
+export '../builder/builder.dart';
+
 export 'kernel_class_builder.dart' show KernelClassBuilder;
 
 export 'kernel_enum_builder.dart' show KernelEnumBuilder;
@@ -12,20 +24,22 @@
 
 export 'kernel_formal_parameter_builder.dart' show KernelFormalParameterBuilder;
 
-export 'kernel_function_type_builder.dart' show KernelFunctionTypeBuilder;
-
 export 'kernel_function_type_alias_builder.dart'
     show KernelFunctionTypeAliasBuilder;
 
-export 'kernel_prefix_builder.dart' show KernelPrefixBuilder;
+export 'kernel_function_type_builder.dart' show KernelFunctionTypeBuilder;
 
-export 'kernel_named_type_builder.dart' show KernelNamedTypeBuilder;
+export 'kernel_invalid_type_builder.dart' show KernelInvalidTypeBuilder;
 
 export 'kernel_library_builder.dart' show KernelLibraryBuilder;
 
 export 'kernel_mixin_application_builder.dart'
     show KernelMixinApplicationBuilder;
 
+export 'kernel_named_type_builder.dart' show KernelNamedTypeBuilder;
+
+export 'kernel_prefix_builder.dart' show KernelPrefixBuilder;
+
 export 'kernel_procedure_builder.dart'
     show
         KernelConstructorBuilder,
@@ -37,23 +51,11 @@
 
 export 'kernel_type_variable_builder.dart' show KernelTypeVariableBuilder;
 
-export '../builder/builder.dart';
-
 export 'kernel_variable_builder.dart' show KernelVariableBuilder;
 
-export 'kernel_invalid_type_builder.dart' show KernelInvalidTypeBuilder;
-
 export 'load_library_builder.dart' show LoadLibraryBuilder;
 
-import 'package:kernel/ast.dart'
-    show
-        Combinator,
-        Constructor,
-        Initializer,
-        Procedure,
-        RedirectingInitializer;
-
-import '../combinator.dart' as fasta;
+export 'unlinked_scope.dart' show UnlinkedDeclaration;
 
 int compareProcedures(Procedure a, Procedure b) {
   int i = "${a.fileUri}".compareTo("${b.fileUri}");
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 2e2c334..efd77e8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -73,9 +73,9 @@
 
 import 'kernel_builder.dart'
     show
-        Builder,
         ClassBuilder,
         ConstructorReferenceBuilder,
+        Declaration,
         KernelLibraryBuilder,
         KernelProcedureBuilder,
         KernelRedirectingFactoryBuilder,
@@ -199,20 +199,20 @@
       // Copy keys to avoid concurrent modification error.
       List<String> names = constructors.keys.toList();
       for (String name in names) {
-        Builder builder = constructors[name];
-        if (builder.parent != this) {
+        Declaration declaration = constructors[name];
+        if (declaration.parent != this) {
           unexpected(
-              "$fileUri", "${builder.parent.fileUri}", charOffset, fileUri);
+              "$fileUri", "${declaration.parent.fileUri}", charOffset, fileUri);
         }
-        if (builder is KernelRedirectingFactoryBuilder) {
+        if (declaration is KernelRedirectingFactoryBuilder) {
           // Compute the immediate redirection target, not the effective.
           ConstructorReferenceBuilder redirectionTarget =
-              builder.redirectionTarget;
+              declaration.redirectionTarget;
           if (redirectionTarget != null) {
-            Builder targetBuilder = redirectionTarget.target;
-            addRedirectingConstructor(builder, library);
+            Declaration targetBuilder = redirectionTarget.target;
+            addRedirectingConstructor(declaration, library);
             if (targetBuilder is ProcedureBuilder) {
-              List<DartType> typeArguments = builder.typeArguments;
+              List<DartType> typeArguments = declaration.typeArguments;
               if (typeArguments == null) {
                 // TODO(32049) If type arguments aren't specified, they should
                 // be inferred.  Currently, the inference is not performed.
@@ -222,10 +222,10 @@
                     const DynamicType(),
                     growable: true);
               }
-              builder.setRedirectingFactoryBody(
+              declaration.setRedirectingFactoryBody(
                   targetBuilder.target, typeArguments);
             } else if (targetBuilder is DillMemberBuilder) {
-              List<DartType> typeArguments = builder.typeArguments;
+              List<DartType> typeArguments = declaration.typeArguments;
               if (typeArguments == null) {
                 // TODO(32049) If type arguments aren't specified, they should
                 // be inferred.  Currently, the inference is not performed.
@@ -235,19 +235,19 @@
                     const DynamicType(),
                     growable: true);
               }
-              builder.setRedirectingFactoryBody(
+              declaration.setRedirectingFactoryBody(
                   targetBuilder.member, typeArguments);
             } else {
               var message = templateRedirectionTargetNotFound
                   .withArguments(redirectionTarget.fullNameForErrors);
-              if (builder.isConst) {
-                addCompileTimeError(message, builder.charOffset, noLength);
+              if (declaration.isConst) {
+                addCompileTimeError(message, declaration.charOffset, noLength);
               } else {
-                addProblem(message, builder.charOffset, noLength);
+                addProblem(message, declaration.charOffset, noLength);
               }
               // CoreTypes aren't computed yet, and this is the outline
               // phase. So we can't and shouldn't create a method body.
-              builder.body = new RedirectingFactoryBody.unresolved(
+              declaration.body = new RedirectingFactoryBody.unresolved(
                   redirectionTarget.fullNameForErrors);
             }
           }
@@ -427,8 +427,9 @@
       KernelTarget target, Procedure procedure, ClassHierarchy hierarchy) {
     CloneWithoutBody cloner = new CloneWithoutBody(
         typeSubstitution: getSubstitutionMap(
-            hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)));
-    Procedure cloned = cloner.clone(procedure);
+            hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)),
+        cloneAnnotations: false);
+    Procedure cloned = cloner.clone(procedure)..isExternal = false;
     transformProcedureToNoSuchMethodForwarder(noSuchMethod, target, cloned);
     cls.procedures.add(cloned);
     cloned.parent = cls;
@@ -830,24 +831,24 @@
   }
 
   @override
-  void applyPatch(Builder patch) {
+  void applyPatch(Declaration patch) {
     if (patch is KernelClassBuilder) {
       patch.actualOrigin = this;
       // TODO(ahe): Complain if `patch.supertype` isn't null.
-      scope.local.forEach((String name, Builder member) {
-        Builder memberPatch = patch.scope.local[name];
+      scope.local.forEach((String name, Declaration member) {
+        Declaration memberPatch = patch.scope.local[name];
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
       });
-      scope.setters.forEach((String name, Builder member) {
-        Builder memberPatch = patch.scope.setters[name];
+      scope.setters.forEach((String name, Declaration member) {
+        Declaration memberPatch = patch.scope.setters[name];
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
       });
-      constructors.local.forEach((String name, Builder member) {
-        Builder memberPatch = patch.constructors.local[name];
+      constructors.local.forEach((String name, Declaration member) {
+        Declaration memberPatch = patch.constructors.local[name];
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
@@ -876,29 +877,29 @@
   }
 
   @override
-  Builder findStaticBuilder(
+  Declaration findStaticBuilder(
       String name, int charOffset, Uri fileUri, LibraryBuilder accessingLibrary,
       {bool isSetter: false}) {
-    Builder builder = super.findStaticBuilder(
+    Declaration declaration = super.findStaticBuilder(
         name, charOffset, fileUri, accessingLibrary,
         isSetter: isSetter);
-    if (builder == null && isPatch) {
+    if (declaration == null && isPatch) {
       return origin.findStaticBuilder(
           name, charOffset, fileUri, accessingLibrary,
           isSetter: isSetter);
     }
-    return builder;
+    return declaration;
   }
 
   @override
-  Builder findConstructorOrFactory(
+  Declaration findConstructorOrFactory(
       String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary) {
-    Builder builder =
+    Declaration declaration =
         super.findConstructorOrFactory(name, charOffset, uri, accessingLibrary);
-    if (builder == null && isPatch) {
+    if (declaration == null && isPatch) {
       return origin.findConstructorOrFactory(
           name, charOffset, uri, accessingLibrary);
     }
-    return builder;
+    return declaration;
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
index ef2a750..5c4c3d9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
@@ -42,7 +42,7 @@
 
 import 'kernel_builder.dart'
     show
-        Builder,
+        Declaration,
         EnumBuilder,
         FormalParameterBuilder,
         KernelClassBuilder,
@@ -266,7 +266,7 @@
         new FieldInitializer(nameField,
             new VariableGet(constructor.function.positionalParameters[1]))
           ..parent = constructor);
-    KernelClassBuilder objectClass = objectType.builder;
+    KernelClassBuilder objectClass = objectType.declaration;
     MemberBuilder superConstructor = objectClass.findConstructorOrFactory(
         "", charOffset, fileUri, libraryBuilder);
     if (superConstructor == null || !superConstructor.isConstructor) {
@@ -298,7 +298,7 @@
   }
 
   @override
-  Builder findConstructorOrFactory(
+  Declaration findConstructorOrFactory(
       String name, int charOffset, Uri uri, LibraryBuilder library) {
     return null;
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index e09b708..bc2d940 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:kernel/ast.dart' show Arguments, Expression, Node, Statement;
+import 'package:kernel/ast.dart'
+    show Arguments, Expression, InvalidExpression, Node, Statement;
 
 import '../../scanner/token.dart' show Token;
 
@@ -13,8 +14,7 @@
         LocatedMessage,
         messageLoadLibraryTakesNoArguments,
         messageSuperAsExpression,
-        templateNotAPrefixInTypeAnnotation,
-        templateUnresolvedPrefixInTypeAnnotation;
+        templateNotAPrefixInTypeAnnotation;
 
 import '../messages.dart' show Message, noLength;
 
@@ -62,13 +62,16 @@
         ThisIndexedAccessGenerator,
         ThisPropertyAccessGenerator,
         TypeUseGenerator,
+        UnlinkedGenerator,
+        UnresolvedNameGenerator,
         VariableUseGenerator;
 
 import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
 
 import 'forest.dart' show Forest;
 
-import 'kernel_builder.dart' show LoadLibraryBuilder, PrefixBuilder;
+import 'kernel_builder.dart'
+    show LoadLibraryBuilder, PrefixBuilder, UnlinkedDeclaration;
 
 import 'kernel_api.dart' show NameSystem, printNodeOn, printQualifiedNameOn;
 
@@ -110,7 +113,7 @@
 
 import 'kernel_builder.dart'
     show
-        Builder,
+        Declaration,
         KernelClassBuilder,
         KernelInvalidTypeBuilder,
         LoadLibraryBuilder,
@@ -1304,12 +1307,12 @@
 
     if (declaration is KernelClassBuilder) {
       KernelClassBuilder declaration = this.declaration;
-      Builder builder = declaration.findStaticBuilder(
+      Declaration member = declaration.findStaticBuilder(
           name.name, offsetForToken(token), uri, helper.library);
 
       Generator generator;
-      if (builder == null) {
-        // If we find a setter, [builder] is an [AccessErrorBuilder], not null.
+      if (member == null) {
+        // If we find a setter, [member] is an [AccessErrorBuilder], not null.
         if (send is IncompletePropertyAccessGenerator) {
           generator = new UnresolvedNameGenerator(helper, send.token, name);
         } else {
@@ -1317,18 +1320,18 @@
               arguments, name.name, null, token.charOffset, Constness.implicit);
         }
       } else {
-        Builder setter;
-        if (builder.isSetter) {
-          setter = builder;
-        } else if (builder.isGetter) {
+        Declaration setter;
+        if (member.isSetter) {
+          setter = member;
+        } else if (member.isGetter) {
           setter = declaration.findStaticBuilder(
               name.name, offsetForToken(token), uri, helper.library,
               isSetter: true);
-        } else if (builder.isField && !builder.isFinal) {
-          setter = builder;
+        } else if (member.isField && !member.isFinal) {
+          setter = member;
         }
         generator = new StaticAccessGenerator<Expression, Statement,
-            Arguments>.fromBuilder(helper, builder, send.token, setter);
+            Arguments>.fromBuilder(helper, member, send.token, setter);
       }
 
       return arguments == null
@@ -1431,6 +1434,84 @@
   }
 }
 
+class KernelUnresolvedNameGenerator extends KernelGenerator
+    with
+        ErroneousExpressionGenerator<Expression, Statement, Arguments>,
+        UnresolvedNameGenerator<Expression, Statement, Arguments> {
+  @override
+  final Name name;
+
+  KernelUnresolvedNameGenerator(
+      ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
+      Token token,
+      this.name)
+      : super(helper, token);
+
+  @override
+  Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+    return unsupported("_makeRead", offsetForToken(token), uri);
+  }
+
+  @override
+  Expression _makeWrite(Expression value, bool voidContext,
+      ShadowComplexAssignment complexAssignment) {
+    return unsupported("_makeWrite", offsetForToken(token), uri);
+  }
+
+  @override
+  void printOn(StringSink sink) {
+    sink.write(", name: ");
+    sink.write(name.name);
+  }
+}
+
+class KernelUnlinkedGenerator extends KernelGenerator
+    with UnlinkedGenerator<Expression, Statement, Arguments> {
+  @override
+  final UnlinkedDeclaration declaration;
+
+  final Expression receiver;
+
+  final Name name;
+
+  KernelUnlinkedGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      this.declaration)
+      : name = new Name(declaration.name, helper.library.target),
+        receiver = new InvalidExpression(declaration.name)
+          ..fileOffset = offsetForToken(token),
+        super(helper, token);
+
+  @override
+  Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+    return unsupported("_makeRead", offsetForToken(token), uri);
+  }
+
+  @override
+  Expression _makeWrite(Expression value, bool voidContext,
+      ShadowComplexAssignment complexAssignment) {
+    return unsupported("_makeWrite", offsetForToken(token), uri);
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext}) {
+    return new PropertySet(receiver, name, value)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
+  Expression buildSimpleRead() {
+    return new ShadowPropertyGet(receiver, name)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
+  Expression doInvocation(int offset, Arguments arguments) {
+    return unsupported("doInvocation", offset, uri);
+  }
+}
+
 Expression makeLet(VariableDeclaration variable, Expression body) {
   if (variable == null) return body;
   return new Let(variable, body);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
index e384183..1f93a18 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
@@ -217,64 +217,6 @@
   }
 }
 
-class UnresolvedNameGenerator extends KernelGenerator
-    with ErroneousExpressionGenerator<Expression, Statement, Arguments> {
-  @override
-  final Name name;
-
-  UnresolvedNameGenerator(
-      ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
-      Token token,
-      this.name)
-      : super(helper, token);
-
-  String get debugName => "UnresolvedNameGenerator";
-
-  Expression doInvocation(int charOffset, Arguments arguments) {
-    return buildError(arguments, offset: charOffset);
-  }
-
-  @override
-  DartType buildErroneousTypeNotAPrefix(Identifier suffix) {
-    helper.addProblem(
-        templateUnresolvedPrefixInTypeAnnotation.withArguments(
-            name.name, suffix.name),
-        offsetForToken(token),
-        lengthOfSpan(token, suffix.token));
-    return const InvalidType();
-  }
-
-  @override
-  Expression buildError(Arguments arguments,
-      {bool isGetter: false, bool isSetter: false, int offset}) {
-    offset ??= offsetForToken(this.token);
-    return helper.throwNoSuchMethodError(
-        storeOffset(forest.literalNull(null), offset),
-        plainNameForRead,
-        arguments,
-        offset,
-        isGetter: isGetter,
-        isSetter: isSetter);
-  }
-
-  @override
-  Expression _makeRead(ShadowComplexAssignment complexAssignment) {
-    return unsupported("_makeRead", offsetForToken(token), uri);
-  }
-
-  @override
-  Expression _makeWrite(Expression value, bool voidContext,
-      ShadowComplexAssignment complexAssignment) {
-    return unsupported("_makeWrite", offsetForToken(token), uri);
-  }
-
-  @override
-  void printOn(StringSink sink) {
-    sink.write(", name: ");
-    sink.write(name.name);
-  }
-}
-
 class IncompleteErrorGenerator extends IncompleteSendGenerator
     with ErroneousExpressionGenerator<Expression, Statement, Arguments> {
   final Message message;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 4c7ec10..873d0f0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -4,28 +4,27 @@
 
 library fasta.kernel_field_builder;
 
-import 'package:front_end/src/base/instrumentation.dart'
-    show Instrumentation, InstrumentationValueForType;
-
 import 'package:kernel/ast.dart'
     show DartType, Expression, Field, Name, NullLiteral;
 
-import '../../scanner/token.dart' show Token;
+import '../../base/instrumentation.dart'
+    show Instrumentation, InstrumentationValueForType;
 
-import '../builder/class_builder.dart' show ClassBuilder;
+import '../../scanner/token.dart' show Token;
 
 import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
 
-import '../parser/parser.dart' show Parser;
-
 import '../problems.dart' show internalProblem;
 
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
 import 'kernel_body_builder.dart' show KernelBodyBuilder;
 
 import 'kernel_builder.dart'
-    show Builder, FieldBuilder, KernelTypeBuilder, MetadataBuilder;
+    show
+        Declaration,
+        FieldBuilder,
+        KernelTypeBuilder,
+        LibraryBuilder,
+        MetadataBuilder;
 
 import 'kernel_shadow_ast.dart' show ShadowField;
 
@@ -41,7 +40,7 @@
       this.type,
       String name,
       int modifiers,
-      Builder compilationUnit,
+      Declaration compilationUnit,
       int charOffset,
       this.initializerTokenForInference,
       this.hasInitializer)
@@ -61,7 +60,7 @@
   bool get isEligibleForInference =>
       type == null && (hasInitializer || isInstanceMember);
 
-  Field build(SourceLibraryBuilder library) {
+  Field build(LibraryBuilder library) {
     field.name ??= new Name(name, library.target);
     if (type != null) {
       field.type = type.build(library);
@@ -86,35 +85,20 @@
   Field get target => field;
 
   @override
-  void prepareTopLevelInference(
-      SourceLibraryBuilder library, ClassBuilder currentClass) {
-    if (isEligibleForInference) {
-      var memberScope =
-          currentClass == null ? library.scope : currentClass.scope;
-      var typeInferenceEngine = library.loader.typeInferenceEngine;
-      var typeInferrer = typeInferenceEngine.createTopLevelTypeInferrer(
-          field.enclosingClass?.thisType, field);
-      if (hasInitializer) {
-        KernelBodyBuilder bodyBuilder = new KernelBodyBuilder(
-            library,
-            this,
-            memberScope,
-            null,
-            typeInferenceEngine.classHierarchy,
-            typeInferenceEngine.coreTypes,
-            currentClass,
-            isInstanceMember,
-            library.fileUri,
-            typeInferrer);
-        Parser parser = new Parser(bodyBuilder);
-        Token token = parser
-            .parseExpression(
-                parser.syntheticPreviousToken(initializerTokenForInference))
-            .next;
-        Expression expression = bodyBuilder.popForValue();
-        bodyBuilder.checkEmpty(token.charOffset);
-        initializer = expression;
-      }
+  void prepareTopLevelInference() {
+    if (!isEligibleForInference) return;
+    var typeInferenceEngine = library.loader.typeInferenceEngine;
+    var typeInferrer = typeInferenceEngine.createTopLevelTypeInferrer(
+        field.enclosingClass?.thisType, field);
+    if (hasInitializer) {
+      initializer = new KernelBodyBuilder.forField(
+              this,
+              // TODO(ahe): Why can't we use the loader's classHierarchy and
+              // coreTypes?
+              typeInferenceEngine.classHierarchy,
+              typeInferenceEngine.coreTypes,
+              typeInferrer)
+          .parseFieldInitializer(initializerTokenForInference);
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index c25088e..c5291df 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -49,10 +49,10 @@
 import 'kernel_builder.dart'
     show
         AccessErrorBuilder,
-        Builder,
         BuiltinTypeBuilder,
         ClassBuilder,
         ConstructorReferenceBuilder,
+        Declaration,
         DynamicTypeBuilder,
         FormalParameterBuilder,
         InvalidTypeBuilder,
@@ -233,7 +233,7 @@
   }
 
   Map<String, TypeVariableBuilder> checkTypeVariables(
-      List<TypeVariableBuilder> typeVariables, Builder owner) {
+      List<TypeVariableBuilder> typeVariables, Declaration owner) {
     if (typeVariables?.isEmpty ?? true) return null;
     Map<String, TypeVariableBuilder> typeVariablesByName =
         <String, TypeVariableBuilder>{};
@@ -479,7 +479,7 @@
         typeVariables: typeVariables,
         modifiers: modifiers,
         interfaces: interfaces);
-    checkTypeVariables(typeVariables, supertype.builder);
+    checkTypeVariables(typeVariables, supertype.declaration);
   }
 
   @override
@@ -727,34 +727,34 @@
   }
 
   @override
-  void buildBuilder(Builder builder, LibraryBuilder coreLibrary) {
+  void buildBuilder(Declaration declaration, LibraryBuilder coreLibrary) {
     Class cls;
     Member member;
     Typedef typedef;
-    if (builder is SourceClassBuilder) {
-      cls = builder.build(this, coreLibrary);
-    } else if (builder is KernelFieldBuilder) {
-      member = builder.build(this)..isStatic = true;
-    } else if (builder is KernelProcedureBuilder) {
-      member = builder.build(this)..isStatic = true;
-    } else if (builder is KernelFunctionTypeAliasBuilder) {
-      typedef = builder.build(this);
-    } else if (builder is KernelEnumBuilder) {
-      cls = builder.build(this, coreLibrary);
-    } else if (builder is PrefixBuilder) {
+    if (declaration is SourceClassBuilder) {
+      cls = declaration.build(this, coreLibrary);
+    } else if (declaration is KernelFieldBuilder) {
+      member = declaration.build(this)..isStatic = true;
+    } else if (declaration is KernelProcedureBuilder) {
+      member = declaration.build(this)..isStatic = true;
+    } else if (declaration is KernelFunctionTypeAliasBuilder) {
+      typedef = declaration.build(this);
+    } else if (declaration is KernelEnumBuilder) {
+      cls = declaration.build(this, coreLibrary);
+    } else if (declaration is PrefixBuilder) {
       // Ignored. Kernel doesn't represent prefixes.
       return;
-    } else if (builder is BuiltinTypeBuilder) {
+    } else if (declaration is BuiltinTypeBuilder) {
       // Nothing needed.
       return;
     } else {
-      unhandled("${builder.runtimeType}", "buildBuilder", builder.charOffset,
-          builder.fileUri);
+      unhandled("${declaration.runtimeType}", "buildBuilder",
+          declaration.charOffset, declaration.fileUri);
       return;
     }
-    if (builder.isPatch) {
-      // The kernel node of a patch is shared with the origin builder. We have
-      // two builders: the origin, and the patch, but only one kernel node
+    if (declaration.isPatch) {
+      // The kernel node of a patch is shared with the origin declaration. We
+      // have two builders: the origin, and the patch, but only one kernel node
       // (which corresponds to the final output). Consequently, the node
       // shouldn't be added to its apparent kernel parent as this would create
       // a duplicate entry in the parent's list of children/members.
@@ -770,7 +770,7 @@
   }
 
   void addNativeDependency(Uri nativeImportUri) {
-    Builder constructor = loader.getNativeAnnotation();
+    Declaration constructor = loader.getNativeAnnotation();
     Arguments arguments =
         new Arguments(<Expression>[new StringLiteral("$nativeImportUri")]);
     Expression annotation;
@@ -865,16 +865,16 @@
   }
 
   @override
-  Builder buildAmbiguousBuilder(
-      String name, Builder builder, Builder other, int charOffset,
+  Declaration computeAmbiguousDeclaration(
+      String name, Declaration declaration, Declaration other, int charOffset,
       {bool isExport: false, bool isImport: false}) {
     // TODO(ahe): Can I move this to Scope or Prefix?
-    if (builder == other) return builder;
-    if (builder is InvalidTypeBuilder) return builder;
+    if (declaration == other) return declaration;
+    if (declaration is InvalidTypeBuilder) return declaration;
     if (other is InvalidTypeBuilder) return other;
-    if (builder is AccessErrorBuilder) {
-      AccessErrorBuilder error = builder;
-      builder = error.builder;
+    if (declaration is AccessErrorBuilder) {
+      AccessErrorBuilder error = declaration;
+      declaration = error.builder;
     }
     if (other is AccessErrorBuilder) {
       AccessErrorBuilder error = other;
@@ -882,28 +882,28 @@
     }
     bool isLocal = false;
     bool isLoadLibrary = false;
-    Builder preferred;
+    Declaration preferred;
     Uri uri;
     Uri otherUri;
     Uri preferredUri;
     Uri hiddenUri;
-    if (scope.local[name] == builder) {
+    if (scope.local[name] == declaration) {
       isLocal = true;
-      preferred = builder;
-      hiddenUri = other.computeLibraryUri();
+      preferred = declaration;
+      hiddenUri = computeLibraryUri(other);
     } else {
-      uri = builder.computeLibraryUri();
-      otherUri = other.computeLibraryUri();
-      if (builder is LoadLibraryBuilder) {
+      uri = computeLibraryUri(declaration);
+      otherUri = computeLibraryUri(other);
+      if (declaration is LoadLibraryBuilder) {
         isLoadLibrary = true;
-        preferred = builder;
+        preferred = declaration;
         preferredUri = otherUri;
       } else if (other is LoadLibraryBuilder) {
         isLoadLibrary = true;
         preferred = other;
         preferredUri = uri;
       } else if (otherUri?.scheme == "dart" && uri?.scheme != "dart") {
-        preferred = builder;
+        preferred = declaration;
         preferredUri = uri;
         hiddenUri = otherUri;
       } else if (uri?.scheme == "dart" && otherUri?.scheme != "dart") {
@@ -930,14 +930,15 @@
       }
       return preferred;
     }
-    if (builder.next == null && other.next == null) {
-      if (isImport && builder is PrefixBuilder && other is PrefixBuilder) {
+    if (declaration.next == null && other.next == null) {
+      if (isImport && declaration is PrefixBuilder && other is PrefixBuilder) {
         // Handles the case where the same prefix is used for different
         // imports.
-        return builder
+        return declaration
           ..exportScope.merge(other.exportScope,
-              (String name, Builder existing, Builder member) {
-            return buildAmbiguousBuilder(name, existing, member, charOffset,
+              (String name, Declaration existing, Declaration member) {
+            return computeAmbiguousDeclaration(
+                name, existing, member, charOffset,
                 isExport: isExport, isImport: isImport);
           });
       }
@@ -1022,7 +1023,7 @@
     for (var declaration in libraryDeclaration.members.values) {
       if (declaration is KernelClassBuilder) {
         count += computeDefaultTypesForVariables(declaration.typeVariables);
-        declaration.forEach((String name, Builder member) {
+        declaration.forEach((String name, Declaration member) {
           if (member is KernelProcedureBuilder) {
             count += computeDefaultTypesForVariables(member.typeVariables);
           }
@@ -1047,7 +1048,7 @@
   @override
   void addImportsToScope() {
     super.addImportsToScope();
-    exportScope.forEach((String name, Builder member) {
+    exportScope.forEach((String name, Declaration member) {
       if (member.parent != this) {
         switch (name) {
           case "dynamic":
@@ -1071,9 +1072,9 @@
   @override
   void applyPatches() {
     if (!isPatch) return;
-    origin.forEach((String name, Builder member) {
+    origin.forEach((String name, Declaration member) {
       bool isSetter = member.isSetter;
-      Builder patch = isSetter ? scope.setters[name] : scope.local[name];
+      Declaration patch = isSetter ? scope.setters[name] : scope.local[name];
       if (patch != null) {
         // [patch] has the same name as a [member] in [origin] library, so it
         // must be a patch to [member].
@@ -1090,7 +1091,7 @@
         }
       }
     });
-    forEach((String name, Builder member) {
+    forEach((String name, Declaration member) {
       // We need to inject all non-patch members into the origin library. This
       // should only apply to private members.
       if (member.isPatch) {
@@ -1106,13 +1107,13 @@
   int finishPatchMethods() {
     if (!isPatch) return 0;
     int count = 0;
-    forEach((String name, Builder member) {
+    forEach((String name, Declaration member) {
       count += member.finishPatch();
     });
     return count;
   }
 
-  void injectMemberFromPatch(String name, Builder member) {
+  void injectMemberFromPatch(String name, Declaration member) {
     if (member.isSetter) {
       assert(scope.setters[name] == null);
       scopeBuilder.addSetter(name, member);
@@ -1122,7 +1123,7 @@
     }
   }
 
-  void exportMemberFromPatch(String name, Builder member) {
+  void exportMemberFromPatch(String name, Declaration member) {
     if (uri.scheme != "dart" || !uri.path.startsWith("_")) {
       addCompileTimeError(templatePatchInjectionFailed.withArguments(name, uri),
           member.charOffset, noLength, member.fileUri);
@@ -1138,3 +1139,13 @@
     addToExportScope(name, member);
   }
 }
+
+Uri computeLibraryUri(Declaration declaration) {
+  Declaration current = declaration;
+  do {
+    if (current is LibraryBuilder) return current.uri;
+    current = current.parent;
+  } while (current != null);
+  return unhandled("no library parent", "${declaration.runtimeType}",
+      declaration.charOffset, declaration.fileUri);
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart
index c70f250f..4c3e69c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart
@@ -37,7 +37,7 @@
 
   Supertype handleInvalidSupertype(
       LibraryBuilder library, int charOffset, Uri fileUri) {
-    var template = builder.isTypeVariable
+    var template = declaration.isTypeVariable
         ? templateSupertypeIsTypeVariable
         : templateSupertypeIsIllegal;
     library.addCompileTimeError(
@@ -46,12 +46,12 @@
   }
 
   DartType build(LibraryBuilder library) {
-    return builder.buildType(library, arguments);
+    return declaration.buildType(library, arguments);
   }
 
   Supertype buildSupertype(
       LibraryBuilder library, int charOffset, Uri fileUri) {
-    TypeDeclarationBuilder declaration = builder;
+    TypeDeclarationBuilder declaration = this.declaration;
     if (declaration is KernelClassBuilder) {
       return declaration.buildSupertype(library, arguments);
     } else if (declaration is KernelInvalidTypeBuilder) {
@@ -68,7 +68,7 @@
 
   Supertype buildMixedInType(
       LibraryBuilder library, int charOffset, Uri fileUri) {
-    TypeDeclarationBuilder declaration = builder;
+    TypeDeclarationBuilder declaration = this.declaration;
     if (declaration is KernelClassBuilder) {
       return declaration.buildMixedInType(library, arguments);
     } else if (declaration is KernelInvalidTypeBuilder) {
@@ -84,9 +84,9 @@
   }
 
   TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution) {
-    TypeBuilder result = substitution[builder];
+    TypeBuilder result = substitution[declaration];
     if (result != null) {
-      assert(builder is TypeVariableBuilder);
+      assert(declaration is TypeVariableBuilder);
       return result;
     } else if (arguments != null) {
       List<KernelTypeBuilder> arguments;
@@ -100,7 +100,7 @@
         i++;
       }
       if (arguments != null) {
-        return new KernelNamedTypeBuilder(name, arguments)..bind(builder);
+        return new KernelNamedTypeBuilder(name, arguments)..bind(declaration);
       }
     }
     return this;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart
deleted file mode 100644
index 687e5ff..0000000
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart
+++ /dev/null
@@ -1,744 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// A transformation to create a self-contained modular kernel without
-/// unnecessary references to other libraries.
-library fasta.kernel.kernel_outline_shaker;
-
-import 'package:kernel/ast.dart';
-import 'package:kernel/binary/ast_to_binary.dart';
-import 'package:kernel/core_types.dart';
-
-import '../problems.dart' show unimplemented, unsupported;
-
-/// Serialize outlines of the nodes in libraries whose URI match [isIncluded],
-/// and outlines of members and classes which are transitively referenced from
-/// the included libraries. Only outlines are serialized, even for included
-/// libraries, all function bodies are ignored.
-void serializeTrimmedOutline(
-    Sink<List<int>> sink, Component component, bool isIncluded(Uri uri)) {
-  var data = new _RetainedDataBuilder();
-  data._markRequired(component);
-
-  for (var library in component.libraries) {
-    if (!isIncluded(library.importUri)) continue;
-    data.markAdditionalExports(library);
-    for (var clazz in library.classes) {
-      if (clazz.name.startsWith('_')) continue;
-      data.markClassForExport(clazz);
-    }
-    for (var field in library.fields) {
-      if (field.name.isPrivate) continue;
-      data.markMember(field);
-    }
-    for (var procedure in library.procedures) {
-      if (procedure.name.isPrivate) continue;
-      data.markMember(procedure);
-    }
-    for (var typedef in library.typedefs) {
-      if (typedef.name.startsWith('_')) continue;
-      data.markTypedef(typedef);
-    }
-  }
-
-  new _TrimmedBinaryPrinter(sink, isIncluded, data)
-      .writeComponentFile(component);
-}
-
-/// Removes unnecessary libraries, classes, and members from [component].
-///
-/// This applies a simple "tree-shaking" technique: the full body of libraries
-/// whose URI match [isIncluded] is preserved, and so is the outline of the
-/// members and classes which are transitively visible from the
-/// included libraries.
-///
-/// The intent is that the resulting component has the entire code that is meant
-/// to be included and the minimum required to prevent dangling references and
-/// allow modular program transformations.
-///
-/// Note that the resulting component may include libraries not in [isIncluded],
-/// but those will be marked as external. There should be no method bodies for
-/// any members of those libraries.
-void trimProgram(Component component, bool isIncluded(Uri uri)) {
-  var data = new _RetainedDataBuilder();
-  data._markRequired(component);
-
-  data.markMember(component.mainMethod);
-  for (var library in component.libraries) {
-    if (isIncluded(library.importUri)) {
-      library.accept(data);
-    }
-  }
-
-  new _KernelOutlineShaker(isIncluded, data).transform(component);
-}
-
-/// Transformer that trims everything in the excluded libraries that is not
-/// marked as preserved by the given [_RetainedData]. For every member in these
-/// excluded libraries, this transformer also removes function bodies and
-/// initializers.
-class _KernelOutlineShaker extends Transformer {
-  final bool Function(Uri uri) isIncluded;
-  final _RetainedData data;
-
-  _KernelOutlineShaker(this.isIncluded, this.data);
-
-  @override
-  Member defaultMember(Member node) {
-    if (!data.isMemberUsed(node)) {
-      node.canonicalName?.unbind();
-      return null;
-    } else {
-      if (node is Procedure) {
-        _clearParameterInitializers(node.function);
-        node.function.body = null;
-      } else if (node is Field) {
-        if (node.name.name == '_exports#') return null;
-        node.initializer = null;
-      } else if (node is Constructor) {
-        if (!node.isConst) {
-          _clearParameterInitializers(node.function);
-        }
-        node.initializers.clear();
-        node.function.body = null;
-      }
-      return node;
-    }
-  }
-
-  @override
-  TreeNode defaultTreeNode(TreeNode node) => node;
-
-  void transform(Component component) {
-    var toRemove = new Set<Library>();
-    for (var library in component.libraries) {
-      if (!isIncluded(library.importUri)) {
-        if (!data.isLibraryUsed(library)) {
-          toRemove.add(library);
-        } else {
-          library.isExternal = true;
-          library.transformChildren(this);
-        }
-      }
-    }
-    component.libraries.removeWhere(toRemove.contains);
-  }
-
-  @override
-  Class visitClass(Class node) {
-    if (!data.isClassUsed(node)) {
-      node.canonicalName?.unbind();
-      return null; // Remove the class.
-    } else {
-      node.transformChildren(this);
-      return node;
-    }
-  }
-
-  @override
-  Typedef visitTypedef(Typedef node) {
-    if (!data.isTypedefUsed(node)) {
-      node.canonicalName?.unbind();
-      return null; // Remove the typedef.
-    } else {
-      node.transformChildren(this);
-      return node;
-    }
-  }
-
-  static void _clearParameterInitializers(FunctionNode function) {
-    for (var parameter in function.positionalParameters) {
-      parameter.initializer = null;
-    }
-    for (var parameter in function.namedParameters) {
-      parameter.initializer = null;
-    }
-  }
-}
-
-/// Informs about which libraries, classes, and members should be retained by
-/// the [_KernelOutlineShaker] when tree-shaking.
-abstract class _RetainedData {
-  /// Whether a class should be preserved. If a class is preserved, its
-  /// supertypes will be preserved too, but some of it members may not be
-  /// included.
-  bool isClassUsed(Class cls);
-
-  /// Whether the field initializer should be preserved.
-  bool isFieldInitializerUsed(Field node);
-
-  /// Whether a library should be preserved and mark as external.
-  bool isLibraryUsed(Library library);
-
-  /// Whether a member should be preserved. If so, its enclosing class/library
-  /// will be preserved too.
-  bool isMemberUsed(Member member);
-
-  /// Whether the parameter initializer should be preserved.
-  bool isParameterInitializerUsed(VariableDeclaration node);
-
-  /// Whether a typedef should be preserved. If a typedef is preserved, its
-  /// return type and types of parameters will be preserved too.
-  bool isTypedefUsed(Typedef node);
-}
-
-/// A builder of [_RetainedData] that recursively marks transitive dependencies.
-///
-/// When it is used as a [RecursiveVisitor], it recursively marks nodes that
-/// are references by visited nodes.
-class _RetainedDataBuilder extends RecursiveVisitor implements _RetainedData {
-  /// Libraries that contained code that is transitively reachable from the
-  /// included libraries.
-  final Set<Library> libraries = new Set<Library>();
-
-  /// Classes that are transitively reachable from the included libraries.
-  final Set<Class> classes = new Set<Class>();
-
-  /// Typedefs that are transitively reachable from the included libraries.
-  final Set<Typedef> typedefs = new Set<Typedef>();
-
-  /// Members that are transitively reachable from the included libraries.
-  final Set<Member> members = new Set<Member>();
-
-  /// Fields for which initializers should be kept because they are constants,
-  /// or are final fields of classes with constant constructors.
-  final Set<Field> fieldsWithInitializers = new Set<Field>();
-
-  /// Parameters for which initializers should be kept because they are
-  /// parameters of a constant constructors.
-  final Set<VariableDeclaration> parametersWithInitializers =
-      new Set<VariableDeclaration>();
-
-  _TypeMarker typeMarker;
-
-  _RetainedDataBuilder() {
-    typeMarker = new _TypeMarker(this);
-  }
-
-  @override
-  bool isClassUsed(Class cls) => classes.contains(cls);
-
-  @override
-  bool isFieldInitializerUsed(Field node) {
-    return fieldsWithInitializers.contains(node);
-  }
-
-  @override
-  bool isLibraryUsed(Library library) => libraries.contains(library);
-
-  @override
-  bool isMemberUsed(Member m) => members.contains(m);
-
-  @override
-  bool isParameterInitializerUsed(VariableDeclaration node) {
-    return parametersWithInitializers.contains(node);
-  }
-
-  @override
-  bool isTypedefUsed(Typedef node) => typedefs.contains(node);
-
-  void markAdditionalExports(Library node) {
-    for (var reference in node.additionalExports) {
-      var node = reference.node;
-      if (node is Class) {
-        markClassForExport(node);
-      } else if (node is Member) {
-        markMember(node);
-      } else if (node is Typedef) {
-        markTypedef(node);
-      } else {
-        unimplemented('export ${node.runtimeType}', -1, null);
-      }
-    }
-  }
-
-  void markAnnotations(List<Expression> annotations) {
-    for (var annotation in annotations) {
-      annotation.accept(this);
-    }
-  }
-
-  /// Mark a class and it's supertypes as used.
-  void markClass(Class cls) {
-    if (cls == null || !classes.add(cls)) return;
-    markLibrary(cls.parent);
-    markAnnotations(cls.annotations);
-    cls.typeParameters.forEach((t) => t.bound.accept(typeMarker));
-    markSupertype(cls.supertype);
-    markSupertype(cls.mixedInType);
-    cls.implementedTypes.forEach(markSupertype);
-
-    for (var field in cls.fields) {
-      if (!field.isStatic && !field.name.isPrivate) {
-        markMember(field);
-      }
-    }
-    for (var method in cls.procedures) {
-      if (!method.isStatic && !method.name.isPrivate) {
-        markMember(method);
-      }
-    }
-  }
-
-  /// Mark the given class as exported, so mark all its public members.
-  void markClassForExport(Class node) {
-    markClass(node);
-    for (var field in node.fields) {
-      if (!field.name.isPrivate) {
-        markMember(field);
-      }
-    }
-    for (var constructor in node.constructors) {
-      if (!constructor.name.isPrivate) {
-        markMember(constructor);
-      }
-    }
-    for (var method in node.procedures) {
-      if (!method.name.isPrivate) {
-        markMember(method);
-      }
-    }
-  }
-
-  /// Mark a library as used.
-  void markLibrary(Library lib) {
-    libraries.add(lib);
-  }
-
-  /// Mark a member and types mentioned on its interface.
-  void markMember(Member node) {
-    if (node == null || !members.add(node)) return;
-
-    var parent = node.parent;
-    if (parent is Library) {
-      markLibrary(parent);
-    } else if (parent is Class) {
-      markClass(parent);
-    }
-
-    markAnnotations(node.annotations);
-    markMemberInterface(node);
-
-    if (node is Field) {
-      if (_shouldKeepFieldInitializer(node)) {
-        fieldsWithInitializers.add(node);
-        node.initializer?.accept(this);
-      }
-    }
-  }
-
-  void markMemberInterface(Member node) {
-    if (node is Field) {
-      node.type.accept(typeMarker);
-    } else if (node is Constructor) {
-      var function = node.function;
-      for (var parameter in function.positionalParameters) {
-        markParameterType(parameter);
-        if (node.isConst) {
-          markParameterInitializer(parameter);
-        }
-      }
-      for (var parameter in function.namedParameters) {
-        markParameterType(parameter);
-        if (node.isConst) {
-          markParameterInitializer(parameter);
-        }
-      }
-      // We don't mark automatically all constructors of classes.
-      // So, we need transitively mark super/redirect initializers.
-      for (var initializer in node.initializers) {
-        if (initializer is SuperInitializer) {
-          markMember(initializer.target);
-        } else if (initializer is RedirectingInitializer) {
-          markMember(initializer.target);
-        }
-      }
-    } else if (node is Procedure) {
-      var function = node.function;
-      function.typeParameters.forEach((p) => p.bound.accept(typeMarker));
-      function.positionalParameters.forEach(markParameterType);
-      function.namedParameters.forEach(markParameterType);
-      function.returnType.accept(typeMarker);
-    }
-  }
-
-  void markParameterInitializer(VariableDeclaration parameter) {
-    parametersWithInitializers.add(parameter);
-    parameter.initializer?.accept(this);
-  }
-
-  void markParameterType(VariableDeclaration parameter) {
-    return parameter.type.accept(typeMarker);
-  }
-
-  /// Mark the class and type arguments of [node].
-  void markSupertype(Supertype node) {
-    if (node == null) return;
-    markClass(node.classNode);
-    node.typeArguments.forEach((t) => t.accept(typeMarker));
-  }
-
-  /// Mark the typedef.
-  void markTypedef(Typedef node) {
-    if (node == null || !typedefs.add(node)) return;
-    markLibrary(node.parent);
-    markAnnotations(node.annotations);
-
-    DartType type = node.type;
-    if (type is FunctionType) {
-      type.returnType?.accept(typeMarker);
-      for (var positionalType in type.positionalParameters) {
-        positionalType.accept(typeMarker);
-      }
-      for (var namedType in type.namedParameters) {
-        namedType.type.accept(typeMarker);
-      }
-    }
-  }
-
-  @override
-  visitConstructor(Constructor node) {
-    if (!node.initializers.any((i) => i is SuperInitializer)) {
-      // super() is currently implicit.
-      var supertype = node.enclosingClass.supertype;
-      if (supertype != null) {
-        for (var constructor in supertype.classNode.constructors) {
-          if (constructor.name.name == '') markMember(constructor);
-        }
-      }
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  visitConstructorInvocation(ConstructorInvocation node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    if (node.receiver is! ThisExpression) {
-      return unsupported("direct call not on this", node.fileOffset, null);
-    }
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitDirectPropertySet(DirectPropertySet node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitFunctionType(FunctionType node) {
-    markTypedef(node.typedefReference?.asTypedef);
-    super.visitFunctionType(node);
-  }
-
-  @override
-  visitInterfaceType(InterfaceType node) {
-    markClass(node.classNode);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitLibrary(Library node) {
-    markAdditionalExports(node);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitMethodInvocation(MethodInvocation node) {
-    markMember(node.interfaceTarget);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitPropertyGet(PropertyGet node) {
-    markMember(node.interfaceTarget);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitPropertySet(PropertySet node) {
-    markMember(node.interfaceTarget);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitRedirectingInitializer(RedirectingInitializer node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitStaticGet(StaticGet node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitStaticInvocation(StaticInvocation node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitStaticSet(StaticSet node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitSuperInitializer(SuperInitializer node) {
-    markMember(node.target);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitSuperPropertyGet(SuperPropertyGet node) {
-    markMember(node.interfaceTarget);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitSuperPropertySet(SuperPropertySet node) {
-    markMember(node.interfaceTarget);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitSupertype(Supertype node) {
-    markClass(node.classNode);
-    node.visitChildren(this);
-  }
-
-  @override
-  visitTypedefReference(Typedef node) {
-    return unimplemented("visitTypedefReference", -1, null);
-  }
-
-  /// Marks classes and members that are assumed to exist by fasta or by
-  /// transformers.
-  // TODO(sigmund): consider being more fine-grained and only marking what is
-  // seen and used.
-  void _markRequired(Component component) {
-    var coreTypes = new CoreTypes(component);
-    coreTypes.objectClass.members.forEach(markMember);
-
-    // These are assumed to be available by fasta:
-    markClass(coreTypes.objectClass);
-    markClass(coreTypes.nullClass);
-    markClass(coreTypes.boolClass);
-    markClass(coreTypes.intClass);
-    markClass(coreTypes.numClass);
-    markClass(coreTypes.doubleClass);
-    markClass(coreTypes.stringClass);
-    markClass(coreTypes.listClass);
-    markClass(coreTypes.mapClass);
-    markClass(coreTypes.iterableClass);
-    markClass(coreTypes.iteratorClass);
-    markClass(coreTypes.futureClass);
-    markClass(coreTypes.streamClass);
-    markClass(coreTypes.symbolClass);
-    markClass(coreTypes.internalSymbolClass);
-    markClass(coreTypes.typeClass);
-    markClass(coreTypes.functionClass);
-    markClass(coreTypes.invocationClass);
-    markMember(coreTypes.compileTimeErrorDefaultConstructor);
-    markMember(coreTypes.constantExpressionErrorDefaultConstructor);
-    markMember(coreTypes.duplicatedFieldInitializerErrorDefaultConstructor);
-    markMember(coreTypes.externalNameDefaultConstructor);
-    markMember(coreTypes.fallThroughErrorUrlAndLineConstructor);
-
-    // These are needed by the continuation (async/await) transformer:
-    markClass(coreTypes.iteratorClass);
-    markClass(coreTypes.futureClass);
-    markClass(coreTypes.futureOrClass);
-    markClass(coreTypes.completerClass);
-    markMember(coreTypes.completerSyncConstructor);
-    markMember(coreTypes.syncIterableDefaultConstructor);
-    markMember(coreTypes.streamIteratorDefaultConstructor);
-    markMember(coreTypes.futureMicrotaskConstructor);
-    markMember(coreTypes.asyncStarStreamControllerDefaultConstructor);
-    markMember(coreTypes.printProcedure);
-    markMember(coreTypes.asyncThenWrapperHelperProcedure);
-    markMember(coreTypes.asyncErrorWrapperHelperProcedure);
-    markMember(coreTypes.awaitHelperProcedure);
-
-    // These are needed by the mixin transformer
-    markMember(coreTypes.invocationMirrorWithoutTypeConstructor);
-    markMember(coreTypes.listFromConstructor);
-  }
-
-  static bool _shouldKeepFieldInitializer(Field node) {
-    if (node.isConst) return true;
-    if (node.isFinal && !node.isStatic) {
-      var parent = node.parent;
-      if (parent is Class) {
-        for (var constructor in parent.constructors) {
-          if (constructor.isConst) return true;
-        }
-      }
-    }
-    return false;
-  }
-}
-
-/// [BinaryPrinter] that serializes outlines of all nodes in included
-/// libraries, and outlines of nodes that are marked in the [_RetainedData].
-class _TrimmedBinaryPrinter extends BinaryPrinter {
-  final bool Function(Uri uri) isIncluded;
-  final _RetainedData data;
-  final List<Library> librariesToWrite = <Library>[];
-  bool insideIncludedLibrary = false;
-
-  _TrimmedBinaryPrinter(Sink<List<int>> sink, this.isIncluded, this.data)
-      : super(sink);
-
-  @override
-  visitClass(Class node) {
-    var level = node.level;
-    node.level = ClassLevel.Hierarchy;
-    super.visitClass(node);
-    node.level = level;
-  }
-
-  @override
-  visitField(Field node) {
-    if (data.isFieldInitializerUsed(node)) {
-      super.visitField(node);
-    } else {
-      var initializer = node.initializer;
-      node.initializer = null;
-      super.visitField(node);
-      node.initializer = initializer;
-    }
-  }
-
-  @override
-  visitFunctionNode(FunctionNode node) {
-    var body = node.body;
-    node.body = null;
-    super.visitFunctionNode(node);
-    node.body = body;
-  }
-
-  @override
-  visitLibrary(Library node) {
-    insideIncludedLibrary = isIncluded(node.importUri);
-    if (insideIncludedLibrary) {
-      super.visitLibrary(node);
-    } else {
-      var isExternal = node.isExternal;
-      var dependencies = node.dependencies.toList();
-      var parts = node.parts.toList();
-
-      node.isExternal = true;
-      node.dependencies.clear();
-      node.parts.clear();
-      super.visitLibrary(node);
-
-      node.isExternal = isExternal;
-      node.dependencies.addAll(dependencies);
-      node.parts.addAll(parts);
-    }
-  }
-
-  @override
-  void writeAdditionalExports(List<Reference> additionalExports) {
-    super.writeAdditionalExports(
-        insideIncludedLibrary ? additionalExports : const <Reference>[]);
-  }
-
-  @override
-  void writeLibraries(Component component) {
-    for (var library in component.libraries) {
-      if (isIncluded(library.importUri) || data.isLibraryUsed(library)) {
-        librariesToWrite.add(library);
-      }
-    }
-    writeList(librariesToWrite, writeNode);
-  }
-
-  @override
-  void writeNodeList(List<Node> nodes) {
-    if (nodes.isEmpty) {
-      super.writeNodeList(nodes);
-    } else {
-      var newNodes = <Node>[];
-      for (var node in nodes) {
-        if (node is Class) {
-          if (data.isClassUsed(node)) {
-            newNodes.add(node);
-          }
-        } else if (node is Member) {
-          if (data.isMemberUsed(node)) {
-            newNodes.add(node);
-          }
-        } else if (node is Typedef) {
-          if (data.isTypedefUsed(node)) {
-            newNodes.add(node);
-          }
-        } else {
-          newNodes.add(node);
-        }
-      }
-      super.writeNodeList(newNodes);
-    }
-  }
-
-  @override
-  void writeComponentIndex(Component component, List<Library> libraries) {
-    super.writeComponentIndex(component, librariesToWrite);
-  }
-
-  @override
-  writeVariableDeclaration(VariableDeclaration node) {
-    if (data.isParameterInitializerUsed(node)) {
-      super.writeVariableDeclaration(node);
-    } else {
-      var initializer = node.initializer;
-      node.initializer = null;
-      super.writeVariableDeclaration(node);
-      node.initializer = initializer;
-    }
-  }
-}
-
-/// A helper visitor used to mark transitive types by the [_RetainedDataBuilder].
-class _TypeMarker extends DartTypeVisitor {
-  _RetainedDataBuilder data;
-
-  _TypeMarker(this.data);
-
-  visitFunctionType(FunctionType node) {
-    node.typeParameters.forEach((t) => t.bound.accept(this));
-    node.positionalParameters.forEach((t) => t.accept(this));
-    node.namedParameters.forEach((t) => t.type.accept(this));
-    node.returnType.accept(this);
-    data.markTypedef(node.typedefReference?.asTypedef);
-  }
-
-  visitInterfaceType(InterfaceType node) {
-    data.markClass(node.classNode);
-    node.typeArguments.forEach((t) => t.accept(this));
-  }
-
-  visitTypedefType(TypedefType node) {
-    node.typeArguments.forEach((t) => t.accept(this));
-  }
-
-  visitTypeParameterType(TypeParameterType node) {
-    // Note: node.parameter is marked by marking the enclosing element.
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index ed62a8a..935acb9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -60,9 +60,9 @@
 
 import 'kernel_builder.dart'
     show
-        Builder,
         ClassBuilder,
         ConstructorReferenceBuilder,
+        Declaration,
         FormalParameterBuilder,
         KernelFormalParameterBuilder,
         KernelLibraryBuilder,
@@ -217,7 +217,7 @@
   Member build(SourceLibraryBuilder library);
 
   void becomeNative(Loader loader) {
-    Builder constructor = loader.getNativeAnnotation();
+    Declaration constructor = loader.getNativeAnnotation();
     Arguments arguments =
         new Arguments(<Expression>[new StringLiteral(nativeMethodName)]);
     Expression annotation;
@@ -244,7 +244,7 @@
     return true;
   }
 
-  void reportPatchMismatch(Builder patch) {
+  void reportPatchMismatch(Declaration patch) {
     library.addCompileTimeError(messagePatchDeclarationMismatch,
         patch.charOffset, noLength, patch.fileUri, context: [
       messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
@@ -385,7 +385,7 @@
   }
 
   @override
-  void applyPatch(Builder patch) {
+  void applyPatch(Declaration patch) {
     if (patch is KernelProcedureBuilder) {
       if (checkPatch(patch)) {
         patch.actualOrigin = this;
@@ -450,6 +450,7 @@
       constructor.function.parent = constructor;
       constructor.function.fileOffset = charOpenParenOffset;
       constructor.function.fileEndOffset = constructor.fileEndOffset;
+      constructor.function.typeParameters = const <TypeParameter>[];
       constructor.isConst = isConst;
       constructor.isExternal = isExternal;
       constructor.name = new Name(name, library.target);
@@ -556,7 +557,7 @@
   }
 
   @override
-  void applyPatch(Builder patch) {
+  void applyPatch(Declaration patch) {
     if (patch is KernelConstructorBuilder) {
       if (checkPatch(patch)) {
         patch.actualOrigin = this;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 36b98a2..f72a8a2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -51,8 +51,7 @@
         FieldInitializerInferenceNode,
         IncludesTypeParametersCovariantly,
         InferenceNode,
-        TypeInferenceEngine,
-        TypeInferenceEngineImpl;
+        TypeInferenceEngine;
 
 import '../type_inference/type_inferrer.dart'
     show TypeInferrer, TypeInferrerDisabled, TypeInferrerImpl;
@@ -819,7 +818,7 @@
 
   @override
   void setInferredType(
-      TypeInferenceEngineImpl engine, Uri uri, DartType inferredType) {
+      TypeInferenceEngine engine, Uri uri, DartType inferredType) {
     type = inferredType;
   }
 
@@ -1434,7 +1433,7 @@
   void set _inferenceNode(InferenceNode value);
 
   void setInferredType(
-      TypeInferenceEngineImpl engine, Uri uri, DartType inferredType);
+      TypeInferenceEngine engine, Uri uri, DartType inferredType);
 
   static void resolveInferenceNode(Member member) {
     if (member is ShadowMember) {
@@ -1580,7 +1579,7 @@
 
   @override
   void setInferredType(
-      TypeInferenceEngineImpl engine, Uri uri, DartType inferredType) {
+      TypeInferenceEngine engine, Uri uri, DartType inferredType) {
     if (isSetter) {
       if (function.positionalParameters.length > 0) {
         function.positionalParameters[0].type = inferredType;
@@ -2027,7 +2026,7 @@
 
 /// Concrete implementation of [TypeInferenceEngine] specialized to work with
 /// kernel objects.
-class ShadowTypeInferenceEngine extends TypeInferenceEngineImpl {
+class ShadowTypeInferenceEngine extends TypeInferenceEngine {
   ShadowTypeInferenceEngine(Instrumentation instrumentation, bool strongMode)
       : super(instrumentation, strongMode);
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index f76f827..5a912e3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -76,8 +76,8 @@
 
 import 'kernel_builder.dart'
     show
-        Builder,
         ClassBuilder,
+        Declaration,
         InvalidTypeBuilder,
         KernelClassBuilder,
         KernelLibraryBuilder,
@@ -187,9 +187,9 @@
   void addDirectSupertype(ClassBuilder cls, Set<ClassBuilder> set) {
     if (cls == null) return;
     forEachDirectSupertype(cls, (NamedTypeBuilder type) {
-      Builder builder = type.builder;
-      if (builder is ClassBuilder) {
-        set.add(builder);
+      Declaration declaration = type.declaration;
+      if (declaration is ClassBuilder) {
+        set.add(declaration);
       }
     });
   }
@@ -199,7 +199,7 @@
     List<SourceClassBuilder> result = <SourceClassBuilder>[];
     loader.builders.forEach((Uri uri, LibraryBuilder library) {
       if (library.loader == loader) {
-        library.forEach((String name, Builder member) {
+        library.forEach((String name, Declaration member) {
           if (member is SourceClassBuilder && !member.isPatch) {
             result.add(member);
           }
@@ -252,15 +252,9 @@
       loader.resolveConstructors();
       component =
           link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
-      if (metadataCollector != null) {
-        component.addMetadataRepository(metadataCollector.repository);
-      }
       computeCoreTypes();
       loader.computeHierarchy();
-      if (!loader.target.disableTypeInference) {
-        loader.prepareTopLevelInference(myClasses);
-        loader.performTopLevelInference(myClasses);
-      }
+      loader.performTopLevelInference(myClasses);
       loader.checkOverrides(myClasses);
       loader.checkAbstractMembers(myClasses);
       loader.addNoSuchMethodForwarders(myClasses);
@@ -273,13 +267,14 @@
     return component;
   }
 
-  /// Build the kernel representation of the component loaded by this target. The
-  /// component will contain full bodies for the code loaded from sources, and
-  /// only references to the code loaded by the [DillTarget], which may or may
-  /// not include method bodies (depending on what was loaded into that target,
-  /// an outline or a full kernel component).
+  /// Build the kernel representation of the component loaded by this
+  /// target. The component will contain full bodies for the code loaded from
+  /// sources, and only references to the code loaded by the [DillTarget],
+  /// which may or may not include method bodies (depending on what was loaded
+  /// into that target, an outline or a full kernel component).
   ///
-  /// If [verify], run the default kernel verification on the resulting component.
+  /// If [verify], run the default kernel verification on the resulting
+  /// component.
   @override
   Future<Component> buildComponent({bool verify: false}) async {
     if (loader.first == null) return null;
@@ -385,16 +380,21 @@
         nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource);
     if (loader.first != null) {
       // TODO(sigmund): do only for full program
-      Builder builder = loader.first.exportScope.lookup("main", -1, null);
-      if (builder is KernelProcedureBuilder) {
-        component.mainMethod = builder.procedure;
-      } else if (builder is DillMemberBuilder) {
-        if (builder.member is Procedure) {
-          component.mainMethod = builder.member;
+      Declaration declaration =
+          loader.first.exportScope.lookup("main", -1, null);
+      if (declaration is KernelProcedureBuilder) {
+        component.mainMethod = declaration.procedure;
+      } else if (declaration is DillMemberBuilder) {
+        if (declaration.member is Procedure) {
+          component.mainMethod = declaration.member;
         }
       }
     }
 
+    if (metadataCollector != null) {
+      component.addMetadataRepository(metadataCollector.repository);
+    }
+
     ticker.logMs("Linked component");
     return component;
   }
@@ -403,21 +403,22 @@
     Class objectClass = this.objectClass;
     loader.builders.forEach((Uri uri, LibraryBuilder library) {
       if (library.loader == loader) {
-        library.forEach((String name, Builder builder) {
-          while (builder != null) {
-            if (builder is SourceClassBuilder) {
-              Class cls = builder.target;
+        library.forEach((String name, Declaration declaration) {
+          while (declaration != null) {
+            if (declaration is SourceClassBuilder) {
+              Class cls = declaration.target;
               if (cls != objectClass) {
                 cls.supertype ??= objectClass.asRawSupertype;
-                builder.supertype ??= new KernelNamedTypeBuilder("Object", null)
-                  ..bind(objectClassBuilder);
+                declaration.supertype ??=
+                    new KernelNamedTypeBuilder("Object", null)
+                      ..bind(objectClassBuilder);
               }
-              if (builder.isMixinApplication) {
-                cls.mixedInType = builder.mixedInType.buildMixedInType(
-                    library, builder.charOffset, builder.fileUri);
+              if (declaration.isMixinApplication) {
+                cls.mixedInType = declaration.mixedInType.buildMixedInType(
+                    library, declaration.charOffset, declaration.fileUri);
               }
             }
-            builder = builder.next;
+            declaration = declaration.next;
           }
         });
       }
@@ -435,7 +436,7 @@
     ticker.logMs("Installed default constructors");
   }
 
-  KernelClassBuilder get objectClassBuilder => objectType.builder;
+  KernelClassBuilder get objectClassBuilder => objectType.declaration;
 
   Class get objectClass => objectClassBuilder.cls;
 
@@ -463,7 +464,7 @@
         SourceClassBuilder named = supertype;
         TypeBuilder type = named.supertype;
         if (type is NamedTypeBuilder) {
-          supertype = type.builder;
+          supertype = type.declaration;
         } else {
           unhandled("${type.runtimeType}", "installDefaultConstructor",
               builder.charOffset, builder.fileUri);
@@ -620,7 +621,7 @@
     Map<Constructor, List<FieldInitializer>> fieldInitializers =
         <Constructor, List<FieldInitializer>>{};
     Constructor superTarget;
-    builder.constructors.forEach((String name, Builder member) {
+    builder.constructors.forEach((String name, Declaration member) {
       if (member.isFactory) return;
       MemberBuilder constructorBuilder = member;
       Constructor constructor = constructorBuilder.target;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart
index 65a3f94..fb688d1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart
@@ -6,15 +6,18 @@
 
 import 'package:kernel/ast.dart' show VariableDeclaration;
 
-import 'kernel_builder.dart' show Builder;
+import 'kernel_builder.dart' show Declaration;
 
-class KernelVariableBuilder extends Builder {
+class KernelVariableBuilder extends Declaration {
+  @override
+  final Declaration parent;
+
+  @override
+  final Uri fileUri;
+
   final VariableDeclaration variable;
 
-  KernelVariableBuilder(
-      VariableDeclaration variable, Builder parent, Uri fileUri)
-      : variable = variable,
-        super(parent, variable.fileOffset, fileUri);
+  KernelVariableBuilder(this.variable, this.parent, this.fileUri);
 
   @override
   int get charOffset => variable.fileOffset;
diff --git a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
index 67a9e22..571d7f9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
@@ -16,12 +16,12 @@
         ProcedureKind,
         ReturnStatement;
 
-import 'kernel_builder.dart' show Builder, KernelLibraryBuilder;
+import 'kernel_builder.dart' show Declaration, KernelLibraryBuilder;
 
 import 'forest.dart' show Forest;
 
 /// Builder to represent the `deferLibrary.loadLibrary` calls and tear-offs.
-class LoadLibraryBuilder extends Builder {
+class LoadLibraryBuilder extends Declaration {
   final KernelLibraryBuilder parent;
 
   final LibraryDependency importDependency;
@@ -33,8 +33,9 @@
   /// null, no tear-offs were seen in the code and no method is generated.
   Member tearoff;
 
-  LoadLibraryBuilder(this.parent, this.importDependency, this.charOffset)
-      : super(parent, charOffset, parent.fileUri);
+  LoadLibraryBuilder(this.parent, this.importDependency, this.charOffset);
+
+  Uri get fileUri => parent.fileUri;
 
   LoadLibrary createLoadLibrary(int charOffset, Forest forest) {
     return forest.loadLibrary(importDependency)..fileOffset = charOffset;
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index 1ba0f1e..0f1081f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -24,11 +24,11 @@
     Map<TypeVariableBuilder, KernelTypeBuilder> lowerSubstitution,
     {bool isCovariant = true}) {
   if (type is KernelNamedTypeBuilder) {
-    if (type.builder is KernelTypeVariableBuilder) {
+    if (type.declaration is KernelTypeVariableBuilder) {
       if (isCovariant) {
-        return upperSubstitution[type.builder] ?? type;
+        return upperSubstitution[type.declaration] ?? type;
       }
-      return lowerSubstitution[type.builder] ?? type;
+      return lowerSubstitution[type.declaration] ?? type;
     }
     if (type.arguments == null || type.arguments.length == 0) {
       return type;
@@ -45,7 +45,7 @@
     }
     if (arguments != null) {
       return new KernelNamedTypeBuilder(type.name, arguments)
-        ..bind(type.builder);
+        ..bind(type.declaration);
     }
     return type;
   }
@@ -201,9 +201,9 @@
 
     void collectReferencesFrom(int index, TypeBuilder type) {
       if (type is NamedTypeBuilder) {
-        if (type.builder is TypeVariableBuilder &&
-            this.variables.contains(type.builder)) {
-          edges[variableIndices[type.builder]].add(index);
+        if (type.declaration is TypeVariableBuilder &&
+            this.variables.contains(type.declaration)) {
+          edges[variableIndices[type.declaration]].add(index);
         }
         if (type.arguments != null) {
           for (TypeBuilder argument in type.arguments) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart b/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart
new file mode 100644
index 0000000..6949064
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/unlinked_scope.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2018, 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 'kernel_builder.dart' show Declaration, Scope;
+
+/// Scope that returns an [UnlinkedDeclaration] if a name can't be resolved.
+/// This is intended to be used as the `enclosingScope` in `BodyBuilder` to
+/// create ASTs with building outlines.
+class UnlinkedScope extends Scope {
+  UnlinkedScope() : super.top(isModifiable: false);
+
+  Declaration lookupIn(String name, int charOffset, Uri fileUri,
+      Map<String, Declaration> map, bool isInstanceScope) {
+    return new UnlinkedDeclaration(name, isInstanceScope, charOffset, fileUri);
+  }
+}
+
+class UnlinkedDeclaration extends Declaration {
+  final String name;
+
+  final bool isInstanceScope;
+
+  @override
+  final int charOffset;
+
+  @override
+  final Uri fileUri;
+
+  UnlinkedDeclaration(
+      this.name, this.isInstanceScope, this.charOffset, this.fileUri);
+
+  @override
+  Declaration get parent => null;
+
+  @override
+  String get fullNameForErrors => name;
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index d95f852..c799f7e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -61,6 +61,8 @@
   return byteSink.builder.takeBytes();
 }
 
+const String kDebugClassName = "#DebugClass";
+
 List<int> serializeProcedure(Procedure procedure) {
   Library fakeLibrary =
       new Library(new Uri(scheme: 'evaluate', path: 'source'));
@@ -70,7 +72,7 @@
 
     CloneVisitor cloner = new CloneVisitor();
 
-    Class fakeClass = new Class(name: realClass.name);
+    Class fakeClass = new Class(name: kDebugClassName);
     for (TypeParameter typeParam in realClass.typeParameters) {
       fakeClass.typeParameters.add(typeParam.accept(cloner));
     }
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index aaac6e7..d2e21c5 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -8,7 +8,7 @@
 
 import 'dart:collection' show Queue;
 
-import 'builder/builder.dart' show Builder, LibraryBuilder;
+import 'builder/builder.dart' show Declaration, LibraryBuilder;
 
 import 'deprecated_problems.dart' show firstSourceUri;
 
@@ -32,6 +32,8 @@
 
 import 'ticker.dart' show Ticker;
 
+import 'type_inference/type_inference_engine.dart' show TypeInferenceEngine;
+
 abstract class Loader<L> {
   final Map<Uri, LibraryBuilder> builders = <Uri, LibraryBuilder>{};
 
@@ -73,6 +75,8 @@
 
   Template<SummaryTemplate> get outlineSummaryTemplate;
 
+  TypeInferenceEngine get typeInferenceEngine => null;
+
   /// Look up a library builder by the name [uri], or if such doesn't
   /// exist, create one. The canonical URI of the library is [uri], and its
   /// actual location is [fileUri].
@@ -263,17 +267,17 @@
     return true;
   }
 
-  Builder getAbstractClassInstantiationError() {
+  Declaration getAbstractClassInstantiationError() {
     return target.getAbstractClassInstantiationError(this);
   }
 
-  Builder getCompileTimeError() => target.getCompileTimeError(this);
+  Declaration getCompileTimeError() => target.getCompileTimeError(this);
 
-  Builder getDuplicatedFieldInitializerError() {
+  Declaration getDuplicatedFieldInitializerError() {
     return target.getDuplicatedFieldInitializerError(this);
   }
 
-  Builder getNativeAnnotation() => target.getNativeAnnotation(this);
+  Declaration getNativeAnnotation() => target.getNativeAnnotation(this);
 
   void recordMessage(Severity severity, Message message, int charOffset,
       int length, Uri fileUri,
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 97944ad..601835b 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -63,6 +63,10 @@
   static const formalParameterDeclaration =
       const FormalParameterDeclarationIdentifierContext();
 
+  /// Identifier is a formal parameter being declared as part of a catch block
+  /// in a try/catch/finally statement.
+  static const catchParameter = const CatchParameterIdentifierContext();
+
   /// Identifier is the start of a library name (e.g. `foo` in the directive
   /// 'library foo;`).
   static const libraryName = const LibraryIdentifierContext();
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 28e85b6..e8cab59 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -16,6 +16,33 @@
 
 import 'util.dart' show isOneOfOrEof, optional;
 
+/// See [IdentifierContext.catchParameter].
+class CatchParameterIdentifierContext extends IdentifierContext {
+  const CatchParameterIdentifierContext() : super('catchParameter');
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    parser.reportRecoverableError(identifier, fasta.messageCatchSyntax);
+    if (looksLikeStartOfNextStatement(identifier) ||
+        isOneOfOrEof(identifier, const [',', ')'])) {
+      return parser.rewriter.insertSyntheticIdentifier(token);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.rewriter.insertSyntheticIdentifier(identifier);
+    }
+    return identifier;
+  }
+}
+
 /// See [IdentifierContext.classOrNamedMixinDeclaration].
 class ClassOrNamedMixinIdentifierContext extends IdentifierContext {
   const ClassOrNamedMixinIdentifierContext()
@@ -109,6 +136,7 @@
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       return identifier;
     }
 
@@ -342,6 +370,7 @@
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       return identifier;
     }
 
@@ -471,6 +500,7 @@
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       return identifier;
     }
 
@@ -501,6 +531,7 @@
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       return identifier;
     }
 
@@ -625,6 +656,7 @@
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       return identifier;
     }
 
@@ -702,6 +734,7 @@
     Token identifier = token.next;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       return identifier;
     }
 
@@ -872,18 +905,25 @@
     }
 
     // Recovery
-    parser.reportRecoverableErrorWithToken(
-        identifier, fasta.templateExpectedIdentifier);
     const followingValues = const ['<', '>', ';', '}', 'extends', 'super'];
     if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
         looksLikeStartOfNextClassMember(identifier) ||
         looksLikeStartOfNextStatement(identifier) ||
         isOneOfOrEof(identifier, followingValues)) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateExpectedIdentifier);
       identifier = parser.rewriter.insertSyntheticIdentifier(token);
+    } else if (identifier.type.isBuiltIn) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateBuiltInIdentifierInDeclaration);
     } else {
-      // When in doubt, consume the token to ensure we make progress
-      // but insert a synthetic identifier to satisfy listeners.
-      identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
     }
     return identifier;
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 1375174..d1d73b2 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -2467,7 +2467,7 @@
 
     bool isGetter = false;
     if (getOrSet == null) {
-      token = computeTypeParamOrArg(name, true).parseVariables(name, this);
+      token = parseMethodTypeVar(name);
     } else {
       isGetter = optional("get", getOrSet);
       token = name;
@@ -2487,6 +2487,22 @@
     return token;
   }
 
+  Token parseMethodTypeVar(Token name) {
+    TypeParamOrArgInfo typeVar = computeTypeParamOrArg(name, true);
+    Token token;
+    if (typeVar == noTypeParamOrArg || name.next.endGroup != null) {
+      token = typeVar.parseVariables(name, this);
+    } else {
+      // Recovery
+      token = typeVar.parseVariables(name, this);
+      if (optional('=', token.next)) {
+        token = token.next;
+        reportRecoverableErrorWithToken(token, fasta.templateUnexpectedToken);
+      }
+    }
+    return token;
+  }
+
   void checkFormals(Token name, bool isGetter, Token token, MemberKind kind) {
     if (optional("(", token)) {
       if (isGetter) {
@@ -3149,7 +3165,7 @@
 
     bool isGetter = false;
     if (getOrSet == null) {
-      token = computeTypeParamOrArg(token, true).parseVariables(token, this);
+      token = parseMethodTypeVar(token);
     } else {
       isGetter = optional("get", getOrSet);
       listener.handleNoTypeVariables(token.next);
@@ -3291,8 +3307,9 @@
   Token parseFunctionLiteral(
       final Token start, TypeInfo typeInfo, IdentifierContext context) {
     Token beforeName = typeInfo.skipType(start);
-    assert(beforeName.next.isIdentifier);
-    Token formals = parseTypeVariablesOpt(beforeName.next);
+    Token name = beforeName.next;
+    assert(name.isIdentifier);
+    Token formals = computeTypeParamOrArg(name).parseVariables(name, this);
     listener.beginNamedFunctionExpression(start.next);
     typeInfo.parseType(start, this);
     return parseNamedFunctionRest(beforeName, start.next, formals, true);
@@ -4374,7 +4391,7 @@
     if (constKeyword == null &&
         closeBrace != null &&
         identical(closeBrace.next.kind, OPEN_PAREN_TOKEN)) {
-      token = parseTypeVariablesOpt(token);
+      token = computeTypeParamOrArg(token).parseVariables(token, this);
       return parseLiteralFunctionSuffix(token);
     } else {
       token = computeTypeParamOrArg(token).parseArguments(token, this);
@@ -5466,32 +5483,56 @@
         }
 
         Token exceptionName = openParens.next;
-        if (!exceptionName.isIdentifier) {
-          reportRecoverableError(exceptionName, fasta.messageCatchSyntax);
-          if (!exceptionName.isKeywordOrIdentifier) {
-            exceptionName = new SyntheticStringToken(
-                TokenType.IDENTIFIER, '', exceptionName.charOffset, 0);
-            rewriter.insertTokenAfter(openParens, exceptionName);
-          }
+        if (exceptionName.kind != IDENTIFIER_TOKEN) {
+          exceptionName = IdentifierContext.catchParameter
+              .ensureIdentifier(openParens, this);
         }
 
-        Token commaOrCloseParens = exceptionName.next;
-        if (optional(")", commaOrCloseParens)) {
+        if (optional(")", exceptionName.next)) {
           // OK: `catch (identifier)`.
-        } else if (!optional(",", commaOrCloseParens)) {
-          reportRecoverableError(exceptionName, fasta.messageCatchSyntax);
         } else {
-          comma = commaOrCloseParens;
-          Token traceName = comma.next;
-          if (!traceName.isIdentifier) {
-            reportRecoverableError(exceptionName, fasta.messageCatchSyntax);
-            if (!traceName.isKeywordOrIdentifier) {
-              traceName = new SyntheticStringToken(
-                  TokenType.IDENTIFIER, '', traceName.charOffset, 0);
-              rewriter.insertTokenAfter(comma, traceName);
+          comma = exceptionName.next;
+          if (!optional(",", comma)) {
+            // Recovery
+            if (!exceptionName.isSynthetic) {
+              reportRecoverableError(comma, fasta.messageCatchSyntax);
             }
-          } else if (!optional(")", traceName.next)) {
-            reportRecoverableError(exceptionName, fasta.messageCatchSyntax);
+            // TODO(danrubel): Consider inserting synthetic identifier if
+            // exceptionName is a non-synthetic identifier followed by `.`.
+            // Then this
+            //   } catch (
+            //   e.f();
+            // will recover to
+            //   } catch (_s_) {}
+            //   e.f();
+            // rather than
+            //   } catch (e) {}
+            //   _s_.f();
+            if (openParens.endGroup.isSynthetic) {
+              // The scanner did not place the synthetic ')' correctly.
+              rewriter.moveSynthetic(exceptionName, openParens.endGroup);
+              comma = null;
+            } else {
+              comma = rewriter.insertTokenAfter(exceptionName,
+                  new SyntheticToken(TokenType.COMMA, comma.charOffset));
+            }
+          }
+          if (comma != null) {
+            Token traceName = comma.next;
+            if (traceName.kind != IDENTIFIER_TOKEN) {
+              traceName = IdentifierContext.catchParameter
+                  .ensureIdentifier(comma, this);
+            }
+            if (!optional(")", traceName.next)) {
+              // Recovery
+              if (!traceName.isSynthetic) {
+                reportRecoverableError(exceptionName, fasta.messageCatchSyntax);
+              }
+              if (openParens.endGroup.isSynthetic) {
+                // The scanner did not place the synthetic ')' correctly.
+                rewriter.moveSynthetic(traceName, openParens.endGroup);
+              }
+            }
           }
         }
         lastConsumed = parseFormalParameters(catchKeyword, MemberKind.Catch);
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 461ebcc..771ed1c 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -238,36 +238,6 @@
   return false;
 }
 
-Token skipTypeVariables(Token token) {
-  assert(optional('<', token));
-  Token endGroup = token.endGroup;
-  if (endGroup == null) {
-    return null;
-  }
-
-  // The scanner sets the endGroup in situations like this: C<T && T>U;
-  // Scan the type arguments to assert there are no operators.
-  // TODO(danrubel): Fix the scanner to do this scanning.
-  token = token.next;
-  while (token != endGroup) {
-    if (token.isKeywordOrIdentifier ||
-        optional(',', token) ||
-        optional('.', token) ||
-        optional('<', token) ||
-        optional('>', token) ||
-        optional('>>', token) ||
-        optional('@', token)) {
-      // ok
-    } else if (optional('(', token)) {
-      token = token.endGroup;
-    } else {
-      return null;
-    }
-    token = token.next;
-  }
-  return endGroup;
-}
-
 /// Instances of [ComplexTypeInfo] are returned by [computeType] to represent
 /// type references that cannot be represented by the constants above.
 class ComplexTypeInfo implements TypeInfo {
@@ -280,9 +250,8 @@
   /// The last token in the type reference.
   Token end;
 
-  /// The tokens before the start of type variables of function types seen
-  /// during analysis. Notice that the tokens in this list might precede
-  /// either `'<'` or `'('` as not all function types have type parameters.
+  /// The `Function` tokens before the start of type variables of function types
+  /// as seen during analysis.
   Link<Token> typeVariableStarters = const Link<Token>();
 
   /// If the receiver represents a generalized function type then this indicates
@@ -318,7 +287,7 @@
     }
 
     for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
-      parser.parseTypeVariablesOpt(t.head);
+      computeTypeParamOrArg(t.head, true).parseVariables(t.head, parser);
       parser.listener.beginFunctionType(start);
     }
 
@@ -477,15 +446,9 @@
   void computeRest(Token token, bool required) {
     while (optional('Function', token)) {
       Token typeVariableStart = token;
+      // TODO(danrubel): Consider caching TypeParamOrArgInfo
+      token = computeTypeParamOrArg(token, true).skip(token);
       token = token.next;
-      if (optional('<', token)) {
-        token = skipTypeVariables(token);
-        if (token == null) {
-          break; // Not a function type.
-        }
-        assert(optional('>', token) || optional('>>', token));
-        token = token.next;
-      }
       if (!optional('(', token)) {
         break; // Not a function type.
       }
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index f6b3309..aae07ff 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -4,7 +4,7 @@
 
 library fasta.scope;
 
-import 'builder/builder.dart' show Builder, TypeVariableBuilder;
+import 'builder/builder.dart' show Declaration, TypeVariableBuilder;
 
 import 'fasta_codes.dart'
     show
@@ -19,10 +19,10 @@
 
 class MutableScope {
   /// Names declared in this scope.
-  Map<String, Builder> local;
+  Map<String, Declaration> local;
 
   /// Setters declared in this scope.
-  Map<String, Builder> setters;
+  Map<String, Declaration> setters;
 
   /// The scope that this scope is nested within, or `null` if this is the top
   /// level scope.
@@ -42,28 +42,28 @@
   /// succeed.
   final bool isModifiable;
 
-  Map<String, Builder> labels;
+  Map<String, Declaration> labels;
 
-  Map<String, Builder> forwardDeclaredLabels;
+  Map<String, Declaration> forwardDeclaredLabels;
 
   Map<String, int> usedNames;
 
-  Scope(Map<String, Builder> local, Map<String, Builder> setters, Scope parent,
-      String debugName, {this.isModifiable: true})
-      : super(local, setters = setters ?? const <String, Builder>{}, parent,
+  Scope(Map<String, Declaration> local, Map<String, Declaration> setters,
+      Scope parent, String debugName, {this.isModifiable: true})
+      : super(local, setters = setters ?? const <String, Declaration>{}, parent,
             debugName);
 
   Scope.top({bool isModifiable: false})
-      : this(<String, Builder>{}, <String, Builder>{}, null, "top",
+      : this(<String, Declaration>{}, <String, Declaration>{}, null, "top",
             isModifiable: isModifiable);
 
   Scope.immutable()
-      : this(const <String, Builder>{}, const <String, Builder>{}, null,
+      : this(const <String, Declaration>{}, const <String, Declaration>{}, null,
             "immutable",
             isModifiable: false);
 
   Scope.nested(Scope parent, String debugName, {bool isModifiable: true})
-      : this(<String, Builder>{}, null, parent, debugName,
+      : this(<String, Declaration>{}, null, parent, debugName,
             isModifiable: isModifiable);
 
   Scope copyWithParent(Scope parent, String debugName) {
@@ -122,9 +122,9 @@
     }
   }
 
-  Builder lookupIn(String name, int charOffset, Uri fileUri,
-      Map<String, Builder> map, bool isInstanceScope) {
-    Builder builder = map[name];
+  Declaration lookupIn(String name, int charOffset, Uri fileUri,
+      Map<String, Declaration> map, bool isInstanceScope) {
+    Declaration builder = map[name];
     if (builder == null) return null;
     if (builder.next != null) {
       return new AmbiguousBuilder(name, builder, charOffset, fileUri);
@@ -135,10 +135,10 @@
     }
   }
 
-  Builder lookup(String name, int charOffset, Uri fileUri,
+  Declaration lookup(String name, int charOffset, Uri fileUri,
       {bool isInstanceScope: true}) {
     recordUse(name, charOffset, fileUri);
-    Builder builder =
+    Declaration builder =
         lookupIn(name, charOffset, fileUri, local, isInstanceScope);
     if (builder != null) return builder;
     builder = lookupIn(name, charOffset, fileUri, setters, isInstanceScope);
@@ -152,10 +152,10 @@
     return builder ?? parent?.lookup(name, charOffset, fileUri);
   }
 
-  Builder lookupSetter(String name, int charOffset, Uri fileUri,
+  Declaration lookupSetter(String name, int charOffset, Uri fileUri,
       {bool isInstanceScope: true}) {
     recordUse(name, charOffset, fileUri);
-    Builder builder =
+    Declaration builder =
         lookupIn(name, charOffset, fileUri, setters, isInstanceScope);
     if (builder != null) return builder;
     builder = lookupIn(name, charOffset, fileUri, local, isInstanceScope);
@@ -171,9 +171,9 @@
 
   bool hasLocalLabel(String name) => labels != null && labels.containsKey(name);
 
-  void declareLabel(String name, Builder target) {
+  void declareLabel(String name, Declaration target) {
     if (isModifiable) {
-      labels ??= <String, Builder>{};
+      labels ??= <String, Declaration>{};
       labels[name] = target;
     } else {
       internalProblem(
@@ -181,9 +181,9 @@
     }
   }
 
-  void forwardDeclareLabel(String name, Builder target) {
+  void forwardDeclareLabel(String name, Declaration target) {
     declareLabel(name, target);
-    forwardDeclaredLabels ??= <String, Builder>{};
+    forwardDeclaredLabels ??= <String, Declaration>{};
     forwardDeclaredLabels[name] = target;
   }
 
@@ -196,11 +196,11 @@
     return true;
   }
 
-  Map<String, Builder> get unclaimedForwardDeclarations {
+  Map<String, Declaration> get unclaimedForwardDeclarations {
     return forwardDeclaredLabels;
   }
 
-  Builder lookupLabel(String name) {
+  Declaration lookupLabel(String name) {
     return (labels == null ? null : labels[name]) ?? parent?.lookupLabel(name);
   }
 
@@ -210,7 +210,7 @@
   /// that can be used as context for reporting a compile-time error about
   /// [name] being used before its declared. [fileUri] is used to bind the
   /// location of this message.
-  LocatedMessage declare(String name, Builder builder, Uri fileUri) {
+  LocatedMessage declare(String name, Declaration builder, Uri fileUri) {
     if (isModifiable) {
       if (usedNames?.containsKey(name) ?? false) {
         return templateDuplicatedNamePreviouslyUsedCause
@@ -225,15 +225,17 @@
     return null;
   }
 
-  void merge(Scope scope,
-      buildAmbiguousBuilder(String name, Builder existing, Builder member)) {
-    Map<String, Builder> map = local;
+  void merge(
+      Scope scope,
+      Declaration computeAmbiguousDeclaration(
+          String name, Declaration existing, Declaration member)) {
+    Map<String, Declaration> map = local;
 
-    void mergeMember(String name, Builder member) {
-      Builder existing = map[name];
+    void mergeMember(String name, Declaration member) {
+      Declaration existing = map[name];
       if (existing != null) {
         if (existing != member) {
-          member = buildAmbiguousBuilder(name, existing, member);
+          member = computeAmbiguousDeclaration(name, existing, member);
         }
       }
       map[name] = member;
@@ -244,7 +246,7 @@
     scope.setters.forEach(mergeMember);
   }
 
-  void forEach(f(String name, Builder member)) {
+  void forEach(f(String name, Declaration member)) {
     local.forEach(f);
     setters.forEach(f);
   }
@@ -262,10 +264,10 @@
     int nestingLevel = (parent?.writeOn(sink) ?? -1) + 1;
     String indent = "  " * nestingLevel;
     sink.writeln("$indent{");
-    local.forEach((String name, Builder member) {
+    local.forEach((String name, Declaration member) {
       sink.writeln("$indent  $name");
     });
-    setters.forEach((String name, Builder member) {
+    setters.forEach((String name, Declaration member) {
       sink.writeln("$indent  $name=");
     });
     return nestingLevel;
@@ -277,24 +279,27 @@
 
   ScopeBuilder(this.scope);
 
-  void addMember(String name, Builder builder) {
+  void addMember(String name, Declaration builder) {
     scope.local[name] = builder;
   }
 
-  void addSetter(String name, Builder builder) {
+  void addSetter(String name, Declaration builder) {
     scope.setters[name] = builder;
   }
 
-  Builder operator [](String name) => scope.local[name];
+  Declaration operator [](String name) => scope.local[name];
 }
 
-abstract class ProblemBuilder extends Builder {
+abstract class ProblemBuilder extends Declaration {
   final String name;
 
-  final Builder builder;
+  final Declaration builder;
 
-  ProblemBuilder(this.name, this.builder, int charOffset, Uri fileUri)
-      : super(null, charOffset, fileUri);
+  final int charOffset;
+
+  final Uri fileUri;
+
+  ProblemBuilder(this.name, this.builder, this.charOffset, this.fileUri);
 
   get target => null;
 
@@ -309,10 +314,11 @@
 /// Represents a [builder] that's being accessed incorrectly. For example, an
 /// attempt to write to a final field, or to read from a setter.
 class AccessErrorBuilder extends ProblemBuilder {
-  AccessErrorBuilder(String name, Builder builder, int charOffset, Uri fileUri)
+  AccessErrorBuilder(
+      String name, Declaration builder, int charOffset, Uri fileUri)
       : super(name, builder, charOffset, fileUri);
 
-  Builder get parent => builder;
+  Declaration get parent => builder;
 
   bool get isFinal => builder.isFinal;
 
@@ -338,8 +344,11 @@
 }
 
 class AmbiguousBuilder extends ProblemBuilder {
-  AmbiguousBuilder(String name, Builder builder, int charOffset, Uri fileUri)
+  AmbiguousBuilder(
+      String name, Declaration builder, int charOffset, Uri fileUri)
       : super(name, builder, charOffset, fileUri);
 
+  Declaration get parent => null;
+
   Message get message => templateDuplicatedName.withArguments(name);
 }
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 58f6ebc..a00fc34 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -211,7 +211,7 @@
     String name = pop();
     Token metadata = pop();
 
-    Builder typedefBuilder = lookupBuilder(typedefKeyword, null, name);
+    Declaration typedefBuilder = lookupBuilder(typedefKeyword, null, name);
     Typedef target = typedefBuilder.target;
     var metadataConstants = parseMetadata(typedefBuilder, metadata);
     if (metadataConstants != null) {
@@ -569,12 +569,15 @@
   void buildFields(int count, Token token, bool isTopLevel) {
     List<String> names =
         popList(count, new List<String>.filled(count, null, growable: true));
-    Builder builder = lookupBuilder(token, null, names.first);
+    Declaration declaration = lookupBuilder(token, null, names.first);
     Token metadata = pop();
     // TODO(paulberry): don't re-parse the field if we've already parsed it
     // for type inference.
-    parseFields(createListener(builder, memberScope, builder.isInstanceMember),
-        token, metadata, isTopLevel);
+    parseFields(
+        createListener(declaration, memberScope, declaration.isInstanceMember),
+        token,
+        metadata,
+        isTopLevel);
   }
 
   @override
@@ -604,7 +607,7 @@
     assert(currentClass == null);
     assert(memberScope == library.scope);
 
-    Builder classBuilder = lookupBuilder(token, null, name);
+    Declaration classBuilder = lookupBuilder(token, null, name);
     Class target = classBuilder.target;
     var metadataConstants = parseMetadata(classBuilder, metadata);
     if (metadataConstants != null) {
@@ -651,10 +654,10 @@
     for (int i = 0; i < metadataAndValues.length; i += 2) {
       Token metadata = metadataAndValues[i];
       String valueName = metadataAndValues[i + 1];
-      Builder builder = enumBuilder.scope.local[valueName];
+      Declaration declaration = enumBuilder.scope.local[valueName];
       if (metadata != null) {
-        Field field = builder.target;
-        for (var annotation in parseMetadata(builder, metadata)) {
+        Field field = declaration.target;
+        for (var annotation in parseMetadata(declaration, metadata)) {
           field.addAnnotation(annotation);
         }
       }
@@ -671,7 +674,7 @@
     String name = pop();
     Token metadata = pop();
 
-    Builder classBuilder = lookupBuilder(classKeyword, null, name);
+    Declaration classBuilder = lookupBuilder(classKeyword, null, name);
     Class target = classBuilder.target;
     var metadataConstants = parseMetadata(classBuilder, metadata);
     if (metadataConstants != null) {
@@ -754,9 +757,9 @@
     listener.checkEmpty(token.charOffset);
   }
 
-  Builder lookupBuilder(Token token, Token getOrSet, String name) {
+  Declaration lookupBuilder(Token token, Token getOrSet, String name) {
     // TODO(ahe): Can I move this to Scope or ScopeBuilder?
-    Builder builder;
+    Declaration declaration;
     if (currentClass != null) {
       if (uri != currentClass.fileUri) {
         unexpected("$uri", "${currentClass.fileUri}", currentClass.charOffset,
@@ -764,22 +767,22 @@
       }
 
       if (getOrSet != null && optional("set", getOrSet)) {
-        builder = currentClass.scope.setters[name];
+        declaration = currentClass.scope.setters[name];
       } else {
-        builder = currentClass.scope.local[name];
+        declaration = currentClass.scope.local[name];
       }
     } else if (getOrSet != null && optional("set", getOrSet)) {
-      builder = library.scope.setters[name];
+      declaration = library.scope.setters[name];
     } else {
-      builder = library.scopeBuilder[name];
+      declaration = library.scopeBuilder[name];
     }
-    checkBuilder(token, builder, name);
-    return builder;
+    checkBuilder(token, declaration, name);
+    return declaration;
   }
 
-  Builder lookupConstructor(Token token, Object nameOrQualified) {
+  Declaration lookupConstructor(Token token, Object nameOrQualified) {
     assert(currentClass != null);
-    Builder builder;
+    Declaration declaration;
     String name;
     String suffix;
     if (nameOrQualified is QualifiedName) {
@@ -789,22 +792,22 @@
       name = nameOrQualified;
       suffix = name == currentClass.name ? "" : name;
     }
-    builder = currentClass.constructors.local[suffix];
-    checkBuilder(token, builder, nameOrQualified);
-    return builder;
+    declaration = currentClass.constructors.local[suffix];
+    checkBuilder(token, declaration, nameOrQualified);
+    return declaration;
   }
 
-  void checkBuilder(Token token, Builder builder, Object name) {
-    if (builder == null) {
+  void checkBuilder(Token token, Declaration declaration, Object name) {
+    if (declaration == null) {
       internalProblem(templateInternalProblemNotFound.withArguments("$name"),
           token.charOffset, uri);
     }
-    if (builder.next != null) {
+    if (declaration.next != null) {
       deprecated_inputError(uri, token.charOffset, "Duplicated name: $name");
     }
-    if (uri != builder.fileUri) {
-      unexpected(
-          "$uri", "${builder.fileUri}", builder.charOffset, builder.fileUri);
+    if (uri != declaration.fileUri) {
+      unexpected("$uri", "${declaration.fileUri}", declaration.charOffset,
+          declaration.fileUri);
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 64f66b9..5086d9e 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -21,6 +21,7 @@
         messageConstConstructorWithBody,
         messageConstMethod,
         messageConstructorWithReturnType,
+        messageConstructorWithTypeParameters,
         messageExpectedBlockToSkip,
         messageInterpolationInUri,
         messageOperatorWithOptionalFormals,
@@ -56,7 +57,14 @@
         operatorRequiredArgumentCount;
 
 import '../parser.dart'
-    show Assert, FormalParameterKind, IdentifierContext, MemberKind, optional;
+    show
+        Assert,
+        FormalParameterKind,
+        IdentifierContext,
+        lengthOfSpan,
+        MemberKind,
+        offsetForToken,
+        optional;
 
 import '../problems.dart' show unhandled;
 
@@ -86,6 +94,8 @@
 
   final bool enableNative;
   final bool stringExpectedAfterNative;
+  bool inConstructor = false;
+  bool inConstructorName = false;
 
   String nativeMethodName;
 
@@ -284,6 +294,9 @@
       super.handleIdentifier(token, context);
       push(token.charOffset);
     }
+    if (inConstructor && context == IdentifierContext.methodDeclaration) {
+      inConstructorName = true;
+    }
   }
 
   @override
@@ -555,12 +568,13 @@
   @override
   void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
       Token varFinalOrConst, Token name) {
+    inConstructor = name?.lexeme == library.currentDeclaration.name;
     List<Modifier> modifiers = <Modifier>[];
     if (externalToken != null) {
       modifiers.add(External);
     }
     if (staticToken != null) {
-      if (name?.lexeme == library.currentDeclaration.name) {
+      if (inConstructor) {
         handleRecoverableError(
             messageStaticConstructor, staticToken, staticToken);
       } else {
@@ -718,6 +732,7 @@
           isTopLevel: false);
     }
     nativeMethodName = null;
+    inConstructor = false;
   }
 
   @override
@@ -786,6 +801,17 @@
             new List<KernelTypeVariableBuilder>.filled(count, null,
                 growable: true)) ??
         NullValue.TypeVariables);
+    if (inConstructorName) {
+      addProblem(messageConstructorWithTypeParameters,
+          offsetForToken(beginToken), lengthOfSpan(beginToken, endToken));
+      inConstructorName = false;
+    }
+  }
+
+  @override
+  void handleNoTypeVariables(Token token) {
+    super.handleNoTypeVariables(token);
+    inConstructorName = false;
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index eb8e9c5..ebb30da 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -23,9 +23,9 @@
 
 import '../kernel/kernel_builder.dart'
     show
-        Builder,
-        ClassBuilder,
         ConstructorReferenceBuilder,
+        Declaration,
+        FieldBuilder,
         KernelClassBuilder,
         KernelFieldBuilder,
         KernelFunctionBuilder,
@@ -42,8 +42,6 @@
 
 import '../problems.dart' show unexpected, unhandled;
 
-import 'source_library_builder.dart' show SourceLibraryBuilder;
-
 ShadowClass initializeClass(
     ShadowClass cls,
     List<TypeVariableBuilder> typeVariables,
@@ -100,32 +98,36 @@
     ShadowClass.setBuilder(this.cls, this);
   }
 
-  Class get cls => origin.actualCls;
+  @override
+  ShadowClass get cls => origin.actualCls;
+
+  @override
+  KernelLibraryBuilder get library => super.library;
 
   Class build(KernelLibraryBuilder library, LibraryBuilder coreLibrary) {
-    void buildBuilders(String name, Builder builder) {
+    void buildBuilders(String name, Declaration declaration) {
       do {
-        if (builder.parent != this) {
+        if (declaration.parent != this) {
           unexpected(
-              "$fileUri", "${builder.parent.fileUri}", charOffset, fileUri);
-        } else if (builder is KernelFieldBuilder) {
+              "$fileUri", "${declaration.parent.fileUri}", charOffset, fileUri);
+        } else if (declaration is KernelFieldBuilder) {
           // TODO(ahe): It would be nice to have a common interface for the
           // build method to avoid duplicating these two cases.
-          Member field = builder.build(library);
-          if (!builder.isPatch) {
+          Member field = declaration.build(library);
+          if (!declaration.isPatch) {
             cls.addMember(field);
           }
-        } else if (builder is KernelFunctionBuilder) {
-          Member function = builder.build(library);
-          if (!builder.isPatch) {
+        } else if (declaration is KernelFunctionBuilder) {
+          Member function = declaration.build(library);
+          if (!declaration.isPatch) {
             cls.addMember(function);
           }
         } else {
-          unhandled("${builder.runtimeType}", "buildBuilders",
-              builder.charOffset, builder.fileUri);
+          unhandled("${declaration.runtimeType}", "buildBuilders",
+              declaration.charOffset, declaration.fileUri);
         }
-        builder = builder.next;
-      } while (builder != null);
+        declaration = declaration.next;
+      } while (declaration != null);
     }
 
     scope.forEach(buildBuilders);
@@ -148,8 +150,8 @@
       }
     }
 
-    constructors.forEach((String name, Builder constructor) {
-      Builder member = scopeBuilder[name];
+    constructors.forEach((String name, Declaration constructor) {
+      Declaration member = scopeBuilder[name];
       if (member == null) return;
       // TODO(ahe): Revisit these messages. It seems like the last two should
       // be `context` parameter to this message.
@@ -169,8 +171,8 @@
       }
     });
 
-    scope.setters.forEach((String name, Builder setter) {
-      Builder member = scopeBuilder[name];
+    scope.setters.forEach((String name, Declaration setter) {
+      Declaration member = scopeBuilder[name];
       if (member == null || !member.isField || member.isFinal) return;
       if (member.isInstanceMember == setter.isInstanceMember) {
         addProblem(templateConflictsWithMember.withArguments(name),
@@ -201,17 +203,19 @@
   }
 
   @override
-  void prepareTopLevelInference(
-      SourceLibraryBuilder library, ClassBuilder currentClass) {
-    scope.forEach((name, builder) {
-      builder.prepareTopLevelInference(library, this);
+  void prepareTopLevelInference() {
+    scope.forEach((String name, Declaration declaration) {
+      if (declaration is FieldBuilder) {
+        declaration.prepareTopLevelInference();
+      }
     });
+    cls.setupApiMembers(library.loader.interfaceResolver);
   }
 
   @override
   void instrumentTopLevelInference(Instrumentation instrumentation) {
-    scope.forEach((name, builder) {
-      builder.instrumentTopLevelInference(instrumentation);
+    scope.forEach((name, declaration) {
+      declaration.instrumentTopLevelInference(instrumentation);
     });
   }
 
@@ -224,11 +228,11 @@
     cls.annotations.forEach((m) => m.fileOffset = origin.cls.fileOffset);
 
     int count = 0;
-    scope.forEach((String name, Builder builder) {
-      count += builder.finishPatch();
+    scope.forEach((String name, Declaration declaration) {
+      count += declaration.finishPatch();
     });
-    constructors.forEach((String name, Builder builder) {
-      count += builder.finishPatch();
+    constructors.forEach((String name, Declaration declaration) {
+      count += declaration.finishPatch();
     });
     return count;
   }
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 25be339..8e28bcc 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -14,9 +14,9 @@
 
 import '../builder/builder.dart'
     show
-        Builder,
         ClassBuilder,
         ConstructorReferenceBuilder,
+        Declaration,
         FormalParameterBuilder,
         FunctionTypeBuilder,
         LibraryBuilder,
@@ -89,6 +89,7 @@
 
   /// Indicates whether type inference (and type promotion) should be disabled
   /// for this library.
+  @override
   final bool disableTypeInference;
 
   String documentationComment;
@@ -436,49 +437,49 @@
 
   TypeVariableBuilder addTypeVariable(String name, T bound, int charOffset);
 
-  Builder addBuilder(String name, Builder builder, int charOffset) {
+  Declaration addBuilder(String name, Declaration declaration, int charOffset) {
     // TODO(ahe): Set the parent correctly here. Could then change the
     // implementation of MemberBuilder.isTopLevel to test explicitly for a
     // LibraryBuilder.
     if (currentDeclaration == libraryDeclaration) {
-      if (builder is MemberBuilder) {
-        builder.parent = this;
-      } else if (builder is TypeDeclarationBuilder) {
-        builder.parent = this;
-      } else if (builder is PrefixBuilder) {
-        assert(builder.parent == this);
+      if (declaration is MemberBuilder) {
+        declaration.parent = this;
+      } else if (declaration is TypeDeclarationBuilder) {
+        declaration.parent = this;
+      } else if (declaration is PrefixBuilder) {
+        assert(declaration.parent == this);
       } else {
         return unhandled(
-            "${builder.runtimeType}", "addBuilder", charOffset, fileUri);
+            "${declaration.runtimeType}", "addBuilder", charOffset, fileUri);
       }
     } else {
       assert(currentDeclaration.parent == libraryDeclaration);
     }
-    bool isConstructor = builder is ProcedureBuilder &&
-        (builder.isConstructor || builder.isFactory);
+    bool isConstructor = declaration is ProcedureBuilder &&
+        (declaration.isConstructor || declaration.isFactory);
     if (!isConstructor &&
-        !builder.isSetter &&
+        !declaration.isSetter &&
         name == currentDeclaration.name) {
       addCompileTimeError(
           messageMemberWithSameNameAsClass, charOffset, noLength, fileUri);
     }
-    Map<String, Builder> members = isConstructor
+    Map<String, Declaration> members = isConstructor
         ? currentDeclaration.constructors
-        : (builder.isSetter
+        : (declaration.isSetter
             ? currentDeclaration.setters
             : currentDeclaration.members);
-    Builder existing = members[name];
-    builder.next = existing;
-    if (builder is PrefixBuilder && existing is PrefixBuilder) {
+    Declaration existing = members[name];
+    declaration.next = existing;
+    if (declaration is PrefixBuilder && existing is PrefixBuilder) {
       assert(existing.next == null);
-      Builder deferred;
-      Builder other;
-      if (builder.deferred) {
-        deferred = builder;
+      Declaration deferred;
+      Declaration other;
+      if (declaration.deferred) {
+        deferred = declaration;
         other = existing;
       } else if (existing.deferred) {
         deferred = existing;
-        other = builder;
+        other = declaration;
       }
       if (deferred != null) {
         addCompileTimeError(
@@ -493,20 +494,21 @@
             ]);
       }
       return existing
-        ..exportScope.merge(builder.exportScope,
-            (String name, Builder existing, Builder member) {
-          return buildAmbiguousBuilder(name, existing, member, charOffset);
+        ..exportScope.merge(declaration.exportScope,
+            (String name, Declaration existing, Declaration member) {
+          return computeAmbiguousDeclaration(
+              name, existing, member, charOffset);
         });
-    } else if (isDuplicatedDefinition(existing, builder)) {
+    } else if (isDuplicatedDefinition(existing, declaration)) {
       addCompileTimeError(templateDuplicatedDefinition.withArguments(name),
           charOffset, noLength, fileUri);
     }
-    return members[name] = builder;
+    return members[name] = declaration;
   }
 
-  bool isDuplicatedDefinition(Builder existing, Builder other) {
+  bool isDuplicatedDefinition(Declaration existing, Declaration other) {
     if (existing == null) return false;
-    Builder next = existing.next;
+    Declaration next = existing.next;
     if (next == null) {
       if (existing.isGetter && other.isSetter) return false;
       if (existing.isSetter && other.isGetter) return false;
@@ -523,28 +525,28 @@
     return true;
   }
 
-  void buildBuilder(Builder builder, LibraryBuilder coreLibrary);
+  void buildBuilder(Declaration declaration, LibraryBuilder coreLibrary);
 
   R build(LibraryBuilder coreLibrary) {
     assert(implementationBuilders.isEmpty);
     canAddImplementationBuilders = true;
-    forEach((String name, Builder builder) {
+    forEach((String name, Declaration declaration) {
       do {
-        buildBuilder(builder, coreLibrary);
-        builder = builder.next;
-      } while (builder != null);
+        buildBuilder(declaration, coreLibrary);
+        declaration = declaration.next;
+      } while (declaration != null);
     });
     for (List list in implementationBuilders) {
       String name = list[0];
-      Builder builder = list[1];
+      Declaration declaration = list[1];
       int charOffset = list[2];
-      addBuilder(name, builder, charOffset);
-      buildBuilder(builder, coreLibrary);
+      addBuilder(name, declaration, charOffset);
+      buildBuilder(declaration, coreLibrary);
     }
     canAddImplementationBuilders = false;
 
-    scope.setters.forEach((String name, Builder setter) {
-      Builder member = scopeBuilder[name];
+    scope.setters.forEach((String name, Declaration setter) {
+      Declaration member = scopeBuilder[name];
       if (member == null || !member.isField || member.isFinal) return;
       addCompileTimeError(templateConflictsWithMember.withArguments(name),
           setter.charOffset, noLength, fileUri);
@@ -560,9 +562,10 @@
   /// Currently, only anonymous mixins are using implementation builders (see
   /// [KernelMixinApplicationBuilder]
   /// (../kernel/kernel_mixin_application_builder.dart)).
-  void addImplementationBuilder(String name, Builder builder, int charOffset) {
+  void addImplementationBuilder(
+      String name, Declaration declaration, int charOffset) {
     assert(canAddImplementationBuilders, "$uri");
-    implementationBuilders.add([name, builder, charOffset]);
+    implementationBuilders.add([name, declaration, charOffset]);
   }
 
   void validatePart() {
@@ -631,14 +634,14 @@
             -1, noLength, fileUri);
       }
     }
-    part.forEach((String name, Builder builder) {
-      if (builder.next != null) {
+    part.forEach((String name, Declaration declaration) {
+      if (declaration.next != null) {
         // TODO(ahe): This shouldn't be necessary as setters have been added to
         // their own scope.
-        assert(builder.next.next == null);
-        addBuilder(name, builder.next, builder.next.charOffset);
+        assert(declaration.next.next == null);
+        addBuilder(name, declaration.next, declaration.next.charOffset);
       }
-      addBuilder(name, builder, builder.charOffset);
+      addBuilder(name, declaration, declaration.charOffset);
     });
     types.addAll(part.types);
     constructorReferences.addAll(part.constructorReferences);
@@ -660,20 +663,22 @@
       import.finalizeImports(this);
     }
     if (!explicitCoreImport) {
-      loader.coreLibrary.exportScope.forEach((String name, Builder member) {
+      loader.coreLibrary.exportScope.forEach((String name, Declaration member) {
         addToScope(name, member, -1, true);
       });
     }
   }
 
   @override
-  void addToScope(String name, Builder member, int charOffset, bool isImport) {
-    Map<String, Builder> map =
+  void addToScope(
+      String name, Declaration member, int charOffset, bool isImport) {
+    Map<String, Declaration> map =
         member.isSetter ? importScope.setters : importScope.local;
-    Builder existing = map[name];
+    Declaration existing = map[name];
     if (existing != null) {
       if (existing != member) {
-        map[name] = buildAmbiguousBuilder(name, existing, member, charOffset,
+        map[name] = computeAmbiguousDeclaration(
+            name, existing, member, charOffset,
             isImport: isImport);
       }
     } else {
@@ -700,7 +705,7 @@
   @override
   int resolveConstructors(_) {
     int count = 0;
-    forEach((String name, Builder member) {
+    forEach((String name, Declaration member) {
       count += member.resolveConstructors(this);
     });
     return count;
@@ -720,20 +725,8 @@
   }
 
   @override
-  void prepareTopLevelInference(
-      SourceLibraryBuilder library, ClassBuilder currentClass) {
-    forEach((String name, Builder member) {
-      if (member is ClassBuilder) {
-        // Classes are handled separately, in class hierarchy order.
-        return;
-      }
-      member.prepareTopLevelInference(library, currentClass);
-    });
-  }
-
-  @override
   void instrumentTopLevelInference(Instrumentation instrumentation) {
-    forEach((String name, Builder member) {
+    forEach((String name, Declaration member) {
       member.instrumentTopLevelInference(instrumentation);
     });
   }
@@ -744,11 +737,11 @@
 class DeclarationBuilder<T extends TypeBuilder> {
   final DeclarationBuilder<T> parent;
 
-  final Map<String, Builder> members;
+  final Map<String, Declaration> members;
 
-  final Map<String, Builder> constructors;
+  final Map<String, Declaration> constructors;
 
-  final Map<String, Builder> setters;
+  final Map<String, Declaration> setters;
 
   final List<UnresolvedType<T>> types = <UnresolvedType<T>>[];
 
@@ -762,7 +755,8 @@
   }
 
   DeclarationBuilder.library()
-      : this(<String, Builder>{}, <String, Builder>{}, null, "library", null);
+      : this(<String, Declaration>{}, <String, Declaration>{}, null, "library",
+            null);
 
   DeclarationBuilder createNested(String name, bool hasMembers) {
     return new DeclarationBuilder<T>(
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 7507777..7d6952a 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -34,9 +34,10 @@
 
 import '../builder/builder.dart'
     show
-        Builder,
         ClassBuilder,
+        Declaration,
         EnumBuilder,
+        FieldBuilder,
         LibraryBuilder,
         NamedTypeBuilder,
         TypeBuilder;
@@ -115,6 +116,7 @@
   ClassHierarchy hierarchy;
   CoreTypes coreTypes;
 
+  @override
   TypeInferenceEngine typeInferenceEngine;
 
   InterfaceResolver interfaceResolver;
@@ -223,9 +225,10 @@
     if (token == null) return null;
     DietListener dietListener = createDietListener(library);
 
-    Builder parent = library;
+    Declaration parent = library;
     if (enclosingClass != null) {
-      Builder cls = dietListener.memberScope.lookup(enclosingClass, -1, null);
+      Declaration cls =
+          dietListener.memberScope.lookup(enclosingClass, -1, null);
       if (cls is ClassBuilder) {
         parent = cls;
         dietListener
@@ -304,7 +307,7 @@
       wasChanged = false;
       for (SourceLibraryBuilder exported in both) {
         for (Export export in exported.exporters) {
-          exported.exportScope.forEach((String name, Builder member) {
+          exported.exportScope.forEach((String name, Declaration member) {
             if (export.addToExportScope(name, member)) {
               wasChanged = true;
             }
@@ -333,15 +336,15 @@
     // TODO(sigmund): should be `covarint SourceLibraryBuilder`.
     builders.forEach((Uri uri, dynamic l) {
       SourceLibraryBuilder library = l;
-      Set<Builder> members = new Set<Builder>();
-      library.forEach((String name, Builder member) {
+      Set<Declaration> members = new Set<Declaration>();
+      library.forEach((String name, Declaration member) {
         while (member != null) {
           members.add(member);
           member = member.next;
         }
       });
       List<String> exports = <String>[];
-      library.exportScope.forEach((String name, Builder member) {
+      library.exportScope.forEach((String name, Declaration member) {
         while (member != null) {
           if (!members.contains(member)) {
             exports.add(name);
@@ -553,10 +556,11 @@
       if (mixedInType != null) {
         bool isClassBuilder = false;
         if (mixedInType is NamedTypeBuilder) {
-          var builder = mixedInType.builder;
+          var builder = mixedInType.declaration;
           if (builder is ClassBuilder) {
             isClassBuilder = true;
-            for (Builder constructory in builder.constructors.local.values) {
+            for (Declaration constructory
+                in builder.constructors.local.values) {
               if (constructory.isConstructor && !constructory.isSynthetic) {
                 cls.addCompileTimeError(
                     templateIllegalMixinDueToConstructors
@@ -720,11 +724,13 @@
         new ShadowTypeInferenceEngine(instrumentation, target.strongMode);
   }
 
-  /// Performs the first phase of top level initializer inference, which
-  /// consists of creating kernel objects for all fields and top level variables
-  /// that might be subject to type inference, and records dependencies between
-  /// them.
-  void prepareTopLevelInference(List<SourceClassBuilder> sourceClasses) {
+  void performTopLevelInference(List<SourceClassBuilder> sourceClasses) {
+    if (target.disableTypeInference) return;
+
+    /// The first phase of top level initializer inference, which consists of
+    /// creating kernel objects for all fields and top level variables that
+    /// might be subject to type inference, and records dependencies between
+    /// them.
     typeInferenceEngine.prepareTopLevel(coreTypes, hierarchy);
     interfaceResolver = new InterfaceResolver(
         typeInferenceEngine,
@@ -733,30 +739,38 @@
         target.strongMode);
     builders.forEach((Uri uri, LibraryBuilder library) {
       if (library.loader == this) {
-        library.prepareTopLevelInference(library, null);
+        library.forEach((String name, Declaration member) {
+          if (member is FieldBuilder) {
+            member.prepareTopLevelInference();
+          }
+        });
       }
     });
-    // Note: we need to create a list before iterating, since calling
-    // builder.prepareTopLevelInference causes further class hierarchy queries
-    // to be made which would otherwise result in a concurrent modification
-    // exception.
-    orderedClasses = hierarchy
-        .getOrderedClasses(sourceClasses.map((builder) => builder.target))
-        .map((class_) => ShadowClass.getClassInferenceInfo(class_).builder)
-        .toList();
-    for (var builder in orderedClasses) {
-      ShadowClass class_ = builder.target;
-      builder.prepareTopLevelInference(builder.library, builder);
-      class_.setupApiMembers(interfaceResolver);
+    {
+      // Note: we need to create a list before iterating, since calling
+      // builder.prepareTopLevelInference causes further class hierarchy
+      // queries to be made which would otherwise result in a concurrent
+      // modification exception.
+      List<Class> classes = new List<Class>(sourceClasses.length);
+      for (int i = 0; i < sourceClasses.length; i++) {
+        classes[i] = sourceClasses[i].target;
+      }
+      List<ClassBuilder> result = new List<ClassBuilder>(sourceClasses.length);
+      int i = 0;
+      for (Class cls in hierarchy.getOrderedClasses(classes)) {
+        result[i++] = ShadowClass.getClassInferenceInfo(cls).builder;
+      }
+      orderedClasses = result;
+    }
+    for (ClassBuilder cls in orderedClasses) {
+      cls.prepareTopLevelInference();
     }
     typeInferenceEngine.isTypeInferencePrepared = true;
     ticker.logMs("Prepared top level inference");
-  }
 
-  /// Performs the second phase of top level initializer inference, which is to
-  /// visit fields and top level variables in topologically-sorted order and
-  /// assign their types.
-  void performTopLevelInference(List<SourceClassBuilder> sourceClasses) {
+    /// The second phase of top level initializer inference, which is to visit
+    /// fields and top level variables in topologically-sorted order and assign
+    /// their types.
     typeInferenceEngine.finishTopLevelFields();
     List<Class> changedClasses = new List<Class>();
     for (var builder in orderedClasses) {
diff --git a/pkg/front_end/lib/src/fasta/target.dart b/pkg/front_end/lib/src/fasta/target.dart
index 30b3754..ecf29f9 100644
--- a/pkg/front_end/lib/src/fasta/target.dart
+++ b/pkg/front_end/lib/src/fasta/target.dart
@@ -12,8 +12,8 @@
 /// A compilation target.
 ///
 /// A target reads source files with [read], builds outlines when
-/// [buildOutlines] is called and builds the full component when [buildComponent]
-/// is called.
+/// [buildOutlines] is called and builds the full component when
+/// [buildComponent] is called.
 abstract class Target {
   final Ticker ticker;
 
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 5abbd00..3361321 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -6,7 +6,7 @@
 
 import 'package:kernel/target/targets.dart' as backend show Target;
 
-import 'builder/builder.dart' show Builder, ClassBuilder, LibraryBuilder;
+import 'builder/builder.dart' show Declaration, ClassBuilder, LibraryBuilder;
 
 import 'compiler_context.dart' show CompilerContext;
 
@@ -26,12 +26,12 @@
 
   final CompilerContext context = CompilerContext.current;
 
-  Builder cachedAbstractClassInstantiationError;
-  Builder cachedCompileTimeError;
-  Builder cachedDuplicatedFieldInitializerError;
-  Builder cachedFallThroughError;
-  Builder cachedNativeAnnotation;
-  Builder cachedNativeExtensionAnnotation;
+  Declaration cachedAbstractClassInstantiationError;
+  Declaration cachedCompileTimeError;
+  Declaration cachedDuplicatedFieldInitializerError;
+  Declaration cachedFallThroughError;
+  Declaration cachedNativeAnnotation;
+  Declaration cachedNativeExtensionAnnotation;
 
   TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
       : super(ticker);
@@ -60,7 +60,7 @@
   /// [AbstractClassInstantiationError] error.  The constructor is expected to
   /// accept a single argument of type String, which is the name of the
   /// abstract class.
-  Builder getAbstractClassInstantiationError(Loader loader) {
+  Declaration getAbstractClassInstantiationError(Loader loader) {
     if (cachedAbstractClassInstantiationError != null) {
       return cachedAbstractClassInstantiationError;
     }
@@ -71,7 +71,7 @@
   /// Returns a reference to the constructor used for creating a compile-time
   /// error. The constructor is expected to accept a single argument of type
   /// String, which is the compile-time error message.
-  Builder getCompileTimeError(Loader loader) {
+  Declaration getCompileTimeError(Loader loader) {
     if (cachedCompileTimeError != null) return cachedCompileTimeError;
     return cachedCompileTimeError = loader.coreLibrary
         .getConstructor("_CompileTimeError", bypassLibraryPrivacy: true);
@@ -80,7 +80,7 @@
   /// Returns a reference to the constructor used for creating a runtime error
   /// when a final field is initialized twice. The constructor is expected to
   /// accept a single argument which is the name of the field.
-  Builder getDuplicatedFieldInitializerError(Loader loader) {
+  Declaration getDuplicatedFieldInitializerError(Loader loader) {
     if (cachedDuplicatedFieldInitializerError != null) {
       return cachedDuplicatedFieldInitializerError;
     }
@@ -92,7 +92,7 @@
   /// Returns a reference to the constructor used for creating `native`
   /// annotations. The constructor is expected to accept a single argument of
   /// type String, which is the name of the native method.
-  Builder getNativeAnnotation(Loader loader) {
+  Declaration getNativeAnnotation(Loader loader) {
     if (cachedNativeAnnotation != null) return cachedNativeAnnotation;
     LibraryBuilder internal = loader.read(Uri.parse("dart:_internal"), -1);
     return cachedNativeAnnotation = internal.getConstructor("ExternalName");
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index 0333163..dd6fb0f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -610,7 +610,7 @@
 /// infer covariance annotations, and to create forwarwding stubs when necessary
 /// to meet covariance requirements.
 class InterfaceResolver {
-  final TypeInferenceEngineImpl _typeInferenceEngine;
+  final TypeInferenceEngine _typeInferenceEngine;
 
   final TypeEnvironment _typeEnvironment;
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index a6f0aee..0b8d427 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -227,10 +227,10 @@
       var subtypeArg = subtype.typeArguments[0];
       if (supertype is InterfaceType &&
           identical(supertype.classNode, environment.futureOrClass)) {
-        // `FutureOr<P>` is a subtype match for `FutureOr<Q>` with respect to `L`
-        // under constraints `C`:
-        // - If `P` is a subtype match for `Q` with respect to `L` under constraints
-        //   `C`.
+        // `FutureOr<P>` is a subtype match for `FutureOr<Q>` with respect to
+        // `L` under constraints `C`:
+        // - If `P` is a subtype match for `Q` with respect to `L` under
+        //   constraints `C`.
         var supertypeArg = supertype.typeArguments[0];
         return _isSubtypeMatch(subtypeArg, supertypeArg);
       }
@@ -252,8 +252,8 @@
       // constraints `C`:
       // - If `P` is a subtype match for `Future<Q>` with respect to `L` under
       //   constraints `C`.
-      // - Or `P` is not a subtype match for `Future<Q>` with respect to `L` under
-      //   constraints `C`
+      // - Or `P` is not a subtype match for `Future<Q>` with respect to `L`
+      //   under constraints `C`
       //   - And `P` is a subtype match for `Q` with respect to `L` under
       //     constraints `C`
       var supertypeArg = supertype.typeArguments[0];
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index e1cb6ea..5a52a48 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -37,7 +37,7 @@
 /// Concrete class derived from [InferenceNode] to represent type inference of a
 /// field based on its initializer.
 class FieldInitializerInferenceNode extends InferenceNode {
-  final TypeInferenceEngineImpl _typeInferenceEngine;
+  final TypeInferenceEngine _typeInferenceEngine;
 
   /// The field whose type should be inferred.
   final ShadowField field;
@@ -200,16 +200,24 @@
 /// (e.g. DietListener).  Derived classes should derive from
 /// [TypeInferenceEngineImpl].
 abstract class TypeInferenceEngine {
-  ClassHierarchy get classHierarchy;
+  ClassHierarchy classHierarchy;
 
-  void set classHierarchy(ClassHierarchy classHierarchy);
-
-  CoreTypes get coreTypes;
+  CoreTypes coreTypes;
 
   /// Indicates whether the "prepare" phase of type inference is complete.
-  void set isTypeInferencePrepared(bool value);
+  bool isTypeInferencePrepared = false;
 
-  TypeSchemaEnvironment get typeSchemaEnvironment;
+  TypeSchemaEnvironment typeSchemaEnvironment;
+
+  final staticInferenceNodes = <FieldInitializerInferenceNode>[];
+
+  final initializingFormals = <ShadowVariableDeclaration>[];
+
+  final Instrumentation instrumentation;
+
+  final bool strongMode;
+
+  TypeInferenceEngine(this.instrumentation, this.strongMode);
 
   /// Creates a disabled type inferrer (intended for debugging and profiling
   /// only).
@@ -225,58 +233,13 @@
   TypeInferrer createTopLevelTypeInferrer(
       InterfaceType thisType, ShadowField field);
 
+  /// Retrieve the [TypeInferrer] for the given [field], which was created by
+  /// a previous call to [createTopLevelTypeInferrer].
+  TypeInferrerImpl getFieldTypeInferrer(ShadowField field);
+
   /// Performs the second phase of top level initializer inference, which is to
   /// visit all accessors and top level variables that were passed to
   /// [recordAccessor] in topologically-sorted order and assign their types.
-  void finishTopLevelFields();
-
-  /// Performs the third phase of top level inference, which is to visit all
-  /// initializing formals and infer their types (if necessary) from the
-  /// corresponding fields.
-  void finishTopLevelInitializingFormals();
-
-  /// Gets ready to do top level type inference for the component having the given
-  /// [hierarchy], using the given [coreTypes].
-  void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy);
-
-  /// Records that the given initializing [formal] will need top level type
-  /// inference.
-  void recordInitializingFormal(ShadowVariableDeclaration formal);
-
-  /// Records that the given static [field] will need top level type inference.
-  void recordStaticFieldInferenceCandidate(
-      ShadowField field, LibraryBuilder library);
-}
-
-/// Derived class containing generic implementations of
-/// [TypeInferenceEngineImpl].
-///
-/// This class contains as much of the implementation of type inference as
-/// possible without knowing the identity of the type parameter.  It defers to
-/// abstract methods for everything else.
-abstract class TypeInferenceEngineImpl extends TypeInferenceEngine {
-  final Instrumentation instrumentation;
-
-  final bool strongMode;
-
-  final staticInferenceNodes = <FieldInitializerInferenceNode>[];
-
-  final initializingFormals = <ShadowVariableDeclaration>[];
-
-  @override
-  CoreTypes coreTypes;
-
-  @override
-  ClassHierarchy classHierarchy;
-
-  TypeSchemaEnvironment typeSchemaEnvironment;
-
-  @override
-  bool isTypeInferencePrepared = false;
-
-  TypeInferenceEngineImpl(this.instrumentation, this.strongMode);
-
-  @override
   void finishTopLevelFields() {
     for (var node in staticInferenceNodes) {
       node.resolve();
@@ -284,7 +247,9 @@
     staticInferenceNodes.clear();
   }
 
-  @override
+  /// Performs the third phase of top level inference, which is to visit all
+  /// initializing formals and infer their types (if necessary) from the
+  /// corresponding fields.
   void finishTopLevelInitializingFormals() {
     for (ShadowVariableDeclaration formal in initializingFormals) {
       try {
@@ -300,11 +265,8 @@
     }
   }
 
-  /// Retrieve the [TypeInferrer] for the given [field], which was created by
-  /// a previous call to [createTopLevelTypeInferrer].
-  TypeInferrerImpl getFieldTypeInferrer(ShadowField field);
-
-  @override
+  /// Gets ready to do top level type inference for the component having the
+  /// given [hierarchy], using the given [coreTypes].
   void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) {
     this.coreTypes = coreTypes;
     this.classHierarchy = hierarchy;
@@ -312,11 +274,13 @@
         new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode);
   }
 
-  @override
+  /// Records that the given initializing [formal] will need top level type
+  /// inference.
   void recordInitializingFormal(ShadowVariableDeclaration formal) {
     initializingFormals.add(formal);
   }
 
+  /// Records that the given static [field] will need top level type inference.
   void recordStaticFieldInferenceCandidate(
       ShadowField field, LibraryBuilder library) {
     var node = new FieldInitializerInferenceNode(this, field, library);
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 361dd77..e9b987e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -89,7 +89,7 @@
 import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
 
 import 'type_inference_engine.dart'
-    show IncludesTypeParametersCovariantly, TypeInferenceEngineImpl;
+    show IncludesTypeParametersCovariantly, TypeInferenceEngine;
 
 import 'type_promotion.dart' show TypePromoter, TypePromoterDisabled;
 
@@ -395,7 +395,7 @@
   static final FunctionType unknownFunction =
       new FunctionType(const [], const DynamicType());
 
-  final TypeInferenceEngineImpl engine;
+  final TypeInferenceEngine engine;
 
   @override
   final Uri uri;
@@ -547,8 +547,14 @@
   /// Finds a member of [receiverType] called [name], and if it is found,
   /// reports it through instrumentation using [fileOffset].
   ///
-  /// For the special case where [receiverType] is a [FunctionType], and the
-  /// method name is `call`, the string `call` is returned as a sentinel object.
+  /// For the case where [receiverType] is a [FunctionType], and the name
+  /// is `call`, the string 'call' is returned as a sentinel object.
+  ///
+  /// For the case where [receiverType] is `dynamic`, and the name is declared
+  /// in Object, the member from Object is returned though the call may not end
+  /// up targeting it if the arguments do not match (the basic principle is that
+  /// the Object member is used for inferring types only if noSuchMethod cannot
+  /// be targeted due to, e.g., an incorrect argument count).
   Object findInterfaceMember(DartType receiverType, Name name, int fileOffset,
       {Template<Message Function(String, DartType)> errorTemplate,
       Expression expression,
@@ -568,16 +574,15 @@
       return 'call';
     }
 
-    Member interfaceMember;
-    if (receiverType is! DynamicType) {
-      Class classNode = receiverType is InterfaceType
-          ? receiverType.classNode
-          : coreTypes.objectClass;
-      interfaceMember = _getInterfaceMember(classNode, name, setter);
-      if (!silent && interfaceMember != null) {
-        instrumentation?.record(uri, fileOffset, 'target',
-            new InstrumentationValueForMember(interfaceMember));
-      }
+    Class classNode = receiverType is InterfaceType
+        ? receiverType.classNode
+        : coreTypes.objectClass;
+    Member interfaceMember = _getInterfaceMember(classNode, name, setter);
+    if (!silent &&
+        receiverType != const DynamicType() &&
+        interfaceMember != null) {
+      instrumentation?.record(uri, fileOffset, 'target',
+          new InstrumentationValueForMember(interfaceMember));
     }
 
     if (!isTopLevel &&
@@ -600,8 +605,8 @@
     return interfaceMember;
   }
 
-  /// Finds a member of [receiverType] called [name], and if it is found,
-  /// reports it through instrumentation and records it in [methodInvocation].
+  /// Finds a member of [receiverType] called [name] and records it in
+  /// [methodInvocation].
   Object findMethodInvocationMember(
       DartType receiverType, InvocationExpression methodInvocation,
       {bool silent: false}) {
@@ -614,11 +619,31 @@
           expression: methodInvocation,
           receiver: methodInvocation.receiver,
           silent: silent);
-      if (strongMode && interfaceMember is Member) {
+      if (receiverType == const DynamicType() && interfaceMember is Procedure) {
+        var arguments = methodInvocation.arguments;
+        var signature = interfaceMember.function;
+        if (arguments.positional.length < signature.requiredParameterCount ||
+            arguments.positional.length >
+                signature.positionalParameters.length) {
+          return null;
+        }
+        for (var argument in arguments.named) {
+          if (!signature.namedParameters
+              .any((declaration) => declaration.name == argument.name)) {
+            return null;
+          }
+        }
+        if (instrumentation != null && !silent) {
+          instrumentation.record(uri, methodInvocation.fileOffset, 'target',
+              new InstrumentationValueForMember(interfaceMember));
+        }
+        methodInvocation.interfaceTarget = interfaceMember;
+      } else if (strongMode && interfaceMember is Member) {
         methodInvocation.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
     } else if (methodInvocation is SuperMethodInvocation) {
+      assert(receiverType != const DynamicType());
       var interfaceMember = findInterfaceMember(
           receiverType, methodInvocation.name, methodInvocation.fileOffset,
           silent: silent);
@@ -646,10 +671,17 @@
           receiver: propertyGet.receiver,
           silent: silent);
       if (strongMode && interfaceMember is Member) {
+        if (instrumentation != null &&
+            !silent &&
+            receiverType == const DynamicType()) {
+          instrumentation.record(uri, propertyGet.fileOffset, 'target',
+              new InstrumentationValueForMember(interfaceMember));
+        }
         propertyGet.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
     } else if (propertyGet is SuperPropertyGet) {
+      assert(receiverType != const DynamicType());
       var interfaceMember = findInterfaceMember(
           receiverType, propertyGet.name, propertyGet.fileOffset,
           silent: silent);
@@ -676,10 +708,17 @@
           setter: true,
           silent: silent);
       if (strongMode && interfaceMember is Member) {
+        if (instrumentation != null &&
+            !silent &&
+            receiverType == const DynamicType()) {
+          instrumentation.record(uri, propertySet.fileOffset, 'target',
+              new InstrumentationValueForMember(interfaceMember));
+        }
         propertySet.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
     } else if (propertySet is SuperPropertySet) {
+      assert(receiverType != const DynamicType());
       var interfaceMember = findInterfaceMember(
           receiverType, propertySet.name, propertySet.fileOffset,
           setter: true, silent: silent);
@@ -1353,7 +1392,11 @@
           errorTemplate: templateUndefinedGetter,
           expression: expression,
           receiver: receiver);
-      if (interfaceMember is Member) {
+      if (strongMode && interfaceMember is Member) {
+        if (instrumentation != null && receiverType == const DynamicType()) {
+          instrumentation.record(uri, desugaredGet.fileOffset, 'target',
+              new InstrumentationValueForMember(interfaceMember));
+        }
         desugaredGet.interfaceTarget = interfaceMember;
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
index fa4b1ea..0665ed5 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
@@ -483,16 +483,16 @@
 /// represents all facts that are known to hold at a certain point in the
 /// component.
 ///
-/// The fact is said to "apply" to a given point in the execution of the component
-/// if the fact is part of the current fact state at the point the parser
-/// reaches that point in the component.
+/// The fact is said to "apply" to a given point in the execution of the
+/// component if the fact is part of the current fact state at the point the
+/// parser reaches that point in the component.
 ///
-/// Note: just because a fact "applies" to a given point in the execution of the
-/// component doesn't mean a type will be promoted--it simply means that the fact
-/// was deduced at a previous point in the straight line execution of the code.
-/// It's possible that the fact will be overshadowed by a later fact, or its
-/// effect will be cancelled by a later assignment.  The final detemination of
-/// whether promotion occurs is left to [_computePromotedType].
+/// Note: just because a fact "applies" to a given point in the execution of
+/// the component doesn't mean a type will be promoted--it simply means that
+/// the fact was deduced at a previous point in the straight line execution of
+/// the code.  It's possible that the fact will be overshadowed by a later
+/// fact, or its effect will be cancelled by a later assignment.  The final
+/// detemination of whether promotion occurs is left to [_computePromotedType].
 abstract class TypePromotionFact {
   /// The variable this fact records information about, or `null` if this fact
   /// records information about general flow control.
diff --git a/pkg/front_end/lib/src/scanner/errors.dart b/pkg/front_end/lib/src/scanner/errors.dart
index 454163c..6d3fb51 100644
--- a/pkg/front_end/lib/src/scanner/errors.dart
+++ b/pkg/front_end/lib/src/scanner/errors.dart
@@ -49,7 +49,8 @@
       const ScannerErrorCode(
           'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment.",
           correction: "Try terminating the comment with '*/', or "
-              "removing any unbalanced occurances of '/*' (because comments nest in Dart).");
+              "removing any unbalanced occurances of '/*'"
+              " (because comments nest in Dart).");
 
   static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
       const ScannerErrorCode(
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 02eedd8..c836042 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -85,6 +85,7 @@
 ConstFieldWithoutInitializer/example: Fail
 ConstructorNotFound/analyzerCode: Fail
 ConstructorNotFound/example: Fail
+ConstructorWithTypeParameters/analyzerCode: Fail # No corresponding analyzer message
 ContinueOutsideOfLoop/script1: Fail
 ContinueWithoutLabelInCase/script1: Fail
 CouldNotParseUri/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 440aab5..e37ae4a 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1022,6 +1022,13 @@
   script:
     - "class C { int C() {} }"
 
+ConstructorWithTypeParameters:
+  template: "Constructors can't have type parameters."
+  severity: ERROR
+  script:
+    - "class C { C<T>() {} }"
+    - "class C { C.foo<T>() {} }"
+
 FieldInitializerOutsideConstructor:
   template: "Field formal parameters can only be used in a constructor."
   tip: "Try removing 'this.'."
@@ -2207,3 +2214,19 @@
   template: "A for-in loop can't have more than one loop variable."
   severity: ERROR
   statement: "for (var x, y in []) {}"
+
+InitializingFormalTypeMismatch:
+  template: "The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2)."
+  tip: "Try changing the type of parameter '#name' to a subtype of #type2."
+  severity: ERROR_LEGACY_WARNING
+  analyzerCode: INVALID_PARAMETER_DECLARATION
+  dart2jsCode: "*fatal*"
+  script: >
+    class C {
+      int x;
+      C(num this.x);
+    }
+
+InitializingFormalTypeMismatchField:
+  template: "The field that corresponds to the parameter."
+  severity: CONTEXT
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 64cdab5..4ba2dc2 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,7 +1,7 @@
 name: front_end
 # Currently, front_end API is not stable and users should not
 # depend on semver semantics when depending on this package.
-version: 0.1.1-alpha.0
+version: 0.1.1
 author: Dart Team <misc@dartlang.org>
 description: Front end for compilation of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
@@ -11,7 +11,7 @@
   charcode: '^1.1.1'
   convert: '^2.0.1'
   crypto: '^2.0.2'
-  kernel: 0.3.1-alpha.0
+  kernel: 0.3.1
   meta: '^1.1.1'
   package_config: '^1.0.1'
   path: '^1.3.9'
diff --git a/pkg/front_end/test/fasta/ast_builder_test.dart b/pkg/front_end/test/fasta/ast_builder_test.dart
deleted file mode 100644
index 8a1c315..0000000
--- a/pkg/front_end/test/fasta/ast_builder_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'dart:async' show Future;
-
-import 'testing/suite.dart';
-
-Future<FastaContext> createContext(
-    Chain suite, Map<String, String> environment) {
-  environment[ENABLE_FULL_COMPILE] = "";
-  environment[AST_KIND_INDEX] = "${AstKind.Analyzer.index}";
-  environment[STRONG_MODE] = "";
-  return FastaContext.create(suite, environment);
-}
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, "../../testing.json");
diff --git a/pkg/front_end/test/fasta/compile_test.dart b/pkg/front_end/test/fasta/compile_test.dart
index 02a64d0..e56e918 100644
--- a/pkg/front_end/test/fasta/compile_test.dart
+++ b/pkg/front_end/test/fasta/compile_test.dart
@@ -11,7 +11,6 @@
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) {
   environment[ENABLE_FULL_COMPILE] = "";
-  environment[AST_KIND_INDEX] = "${AstKind.Kernel.index}";
   return FastaContext.create(suite, environment);
 }
 
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 50c8ffc..8d1dad4 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -37,7 +37,8 @@
         KernelTypeVariableBuilder,
         LoadLibraryBuilder,
         PrefixBuilder,
-        TypeDeclarationBuilder;
+        TypeDeclarationBuilder,
+        UnlinkedDeclaration;
 
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
     show KernelTarget;
@@ -70,11 +71,12 @@
         KernelThisIndexedAccessGenerator,
         KernelThisPropertyAccessGenerator,
         KernelTypeUseGenerator,
+        KernelUnlinkedGenerator,
+        KernelUnresolvedNameGenerator,
         KernelVariableUseGenerator,
         ParenthesizedExpressionGenerator,
         SendAccessGenerator,
-        ThisAccessGenerator,
-        UnresolvedNameGenerator;
+        ThisAccessGenerator;
 
 import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
 
@@ -228,6 +230,10 @@
         new KernelTypeUseGenerator(
             helper, token, prefixBuilder, -1, declaration, "foo"));
     check("UnresolvedNameGenerator(offset: 4, name: bar)",
-        new UnresolvedNameGenerator(helper, token, name));
+        new KernelUnresolvedNameGenerator(helper, token, name));
+    check(
+        "UnlinkedGenerator(offset: 4, name: foo)",
+        new KernelUnlinkedGenerator(
+            helper, token, new UnlinkedDeclaration("foo", false, -1, null)));
   });
 }
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index d2d53a5..f208149 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -333,7 +333,8 @@
       'handleType int )',
       'handleNoName )',
       'handleFormalParameterWithoutValue )',
-      'beginTypeVariables null null ) FormalParameterKind.mandatory MemberKind.GeneralizedFunctionType',
+      'beginTypeVariables null null ) FormalParameterKind.mandatory'
+          ' MemberKind.GeneralizedFunctionType',
       'endFormalParameters 1 ( ) MemberKind.GeneralizedFunctionType',
       'endFunctionType Function m',
     ]);
diff --git a/pkg/front_end/test/fasta/sdk_test.dart b/pkg/front_end/test/fasta/sdk_test.dart
index 8519c8e..90c2a5f 100644
--- a/pkg/front_end/test/fasta/sdk_test.dart
+++ b/pkg/front_end/test/fasta/sdk_test.dart
@@ -11,7 +11,6 @@
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) async {
   environment[ENABLE_FULL_COMPILE] = "";
-  environment[AST_KIND_INDEX] = "${AstKind.Kernel.index}";
   environment["skipVm"] ??= "true";
   environment["onlyCrashes"] ??= "true";
   environment["ignoreExpectations"] ??= "true";
diff --git a/pkg/front_end/test/fasta/shaker_test.dart b/pkg/front_end/test/fasta/shaker_test.dart
deleted file mode 100644
index 1952495..0000000
--- a/pkg/front_end/test/fasta/shaker_test.dart
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-/// Tests basic functionality of the API tree-shaker.
-///
-/// Each input file is built and tree-shaken, then we check that the set of
-/// libraries, classes, and members that are retained match those declared in an
-/// expectations file.
-///
-/// Input files may contain markers to turn on flags that configure this
-/// runner. Currently only the following marker is recognized:
-///   @@SHOW_CORE_LIBRARIES@@ - whether to check for retained information from
-///      the core libraries. By default this runner only checks for members of
-///      pkg/front_end/testcases/shaker/lib/lib.dart.
-library fasta.test.shaker_test;
-
-import 'dart:async' show Future;
-import 'dart:convert' show jsonDecode;
-import 'dart:io' show File;
-
-export 'package:testing/testing.dart' show Chain, runMe;
-import 'package:front_end/src/api_prototype/compiler_options.dart';
-import 'package:front_end/src/base/processed_options.dart';
-import 'package:front_end/src/compute_platform_binaries_location.dart';
-import 'package:front_end/src/fasta/compiler_context.dart';
-import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
-import 'package:front_end/src/fasta/deprecated_problems.dart'
-    show deprecated_InputError;
-import 'package:front_end/src/fasta/kernel/kernel_outline_shaker.dart';
-import 'package:front_end/src/fasta/kernel/kernel_target.dart'
-    show KernelTarget;
-import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
-import 'package:front_end/src/fasta/testing/kernel_chain.dart'
-    show BytesCollector, runDiff;
-import 'package:front_end/src/fasta/util/relativize.dart' show relativizeUri;
-import 'package:kernel/ast.dart' show Component;
-import 'package:kernel/binary/ast_from_binary.dart';
-import 'package:kernel/kernel.dart' show loadComponentFromBytes;
-import 'package:kernel/target/targets.dart' show TargetFlags;
-import 'package:kernel/target/vm.dart' show VmTarget;
-import 'package:kernel/text/ast_to_text.dart';
-import 'package:testing/testing.dart'
-    show Chain, ChainContext, ExpectationSet, Result, Step, TestDescription;
-import 'testing/suite.dart';
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, "../../testing.json");
-
-Future<TreeShakerContext> createContext(
-    Chain suite, Map<String, String> environment) {
-  return TreeShakerContext.create(environment);
-}
-
-/// Context used to run the tree-shaking test suite.
-class TreeShakerContext extends ChainContext {
-  final ProcessedOptions options;
-  final Uri outlineUri;
-  final List<Step> steps;
-  final List<int> outlineBytes;
-
-  final ExpectationSet expectationSet =
-      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
-
-  TreeShakerContext(
-      this.outlineUri, this.options, this.outlineBytes, bool updateExpectations)
-      : steps = <Step>[
-          const BuildProgram(),
-          new CheckShaker(updateExpectations: updateExpectations),
-          new CheckOutline(updateExpectations: updateExpectations),
-        ];
-
-  Component loadPlatformOutline() {
-    // Note: we rebuild the platform outline on every test because the
-    // tree-shaker mutates the in-memory representation of the component without
-    // cloning it.
-    return loadComponentFromBytes(outlineBytes);
-  }
-
-  static create(Map<String, String> environment) async {
-    environment[ENABLE_FULL_COMPILE] = "";
-    environment[AST_KIND_INDEX] = "${AstKind.Kernel.index}";
-    bool updateExpectations = environment["updateExpectations"] == "true";
-
-    Uri platformLocation = _computePlatformBinariesLocation(environment);
-    Uri outlineUri = platformLocation.resolve('vm_outline.dill');
-    List<int> outlineBytes = new File.fromUri(outlineUri).readAsBytesSync();
-
-    var options = new CompilerOptions()
-      ..packagesFileUri = Uri.base.resolve(".packages");
-    return new TreeShakerContext(outlineUri, new ProcessedOptions(options),
-        outlineBytes, updateExpectations);
-  }
-
-  /// Return the location of the platform binaries, such as `vm_outline.dill`
-  /// in the physical file system, using the given [environment] or the
-  /// default location in `xcodebuild`, `out`; or in the SDK distribution.
-  static Uri _computePlatformBinariesLocation(Map<String, String> environment) {
-    // Check if `--platformBinaries=/path/to/platform/` is given.
-    String platformBinaries = environment['platformBinaries'];
-    if (platformBinaries != null) {
-      if (!platformBinaries.endsWith('/')) {
-        platformBinaries = '$platformBinaries/';
-        return Uri.base.resolve(platformBinaries);
-      }
-    }
-    // Otherwise use the default mechanism.
-    return computePlatformBinariesLocation();
-  }
-}
-
-/// Step that extracts the test-specific options and builds the program without
-/// applying tree-shaking.
-class BuildProgram
-    extends Step<TestDescription, _IntermediateData, TreeShakerContext> {
-  const BuildProgram();
-  String get name => "build program";
-  Future<Result<_IntermediateData>> run(
-      TestDescription description, TreeShakerContext context) async {
-    return await CompilerContext.runWithOptions(context.options, (_) async {
-      try {
-        var platformOutline = context.loadPlatformOutline();
-        var uriTranslator = await context.options.getUriTranslator();
-        var dillTarget = new DillTarget(context.options.ticker, uriTranslator,
-            new VmTarget(new TargetFlags(strongMode: false)));
-        dillTarget.loader.appendLibraries(platformOutline);
-        var sourceTarget = new KernelTarget(
-            context.options.fileSystem, false, dillTarget, uriTranslator);
-        await dillTarget.buildOutlines();
-
-        var inputUri = description.uri;
-        sourceTarget.read(inputUri);
-        var contents = new File.fromUri(inputUri).readAsStringSync();
-        var showCoreLibraries = contents.contains("@@SHOW_CORE_LIBRARIES@@");
-
-        await sourceTarget.buildOutlines();
-        var component = await sourceTarget.buildComponent();
-
-        bool isIncluded(Uri uri) => uri == inputUri;
-
-        Component outline;
-        {
-          var bytesCollector = new BytesCollector();
-          serializeTrimmedOutline(bytesCollector, component, isIncluded);
-          var bytes = bytesCollector.collect();
-          outline = new Component();
-          new BinaryBuilder(bytes).readComponent(outline);
-        }
-
-        trimProgram(component, isIncluded);
-
-        return pass(new _IntermediateData(
-            inputUri, component, outline, showCoreLibraries));
-      } on deprecated_InputError catch (e, s) {
-        return fail(null, e.error, s);
-      }
-    });
-  }
-}
-
-/// Intermediate result from the testing chain.
-class _IntermediateData {
-  /// The input URI provided to the test.
-  final Uri uri;
-
-  /// Component built by [BuildProgram].
-  final Component component;
-
-  /// Shaken outline of [component].
-  final Component outline;
-
-  /// Whether the output should include tree-shaking information about the core
-  /// libraries. This is specified in a comment on individual test files where
-  /// we believe that information is relevant.
-  final bool showCoreLibraries;
-
-  _IntermediateData(
-      this.uri, this.component, this.outline, this.showCoreLibraries);
-}
-
-/// A step that runs the tree-shaker and checks against an expectation file for
-/// the list of members and classes that should be preserved by the tree-shaker.
-class CheckShaker
-    extends Step<_IntermediateData, _IntermediateData, ChainContext> {
-  final bool updateExpectations;
-  const CheckShaker({this.updateExpectations: false});
-
-  String get name => "match shaker expectation";
-
-  Future<Result<_IntermediateData>> run(
-      _IntermediateData data, ChainContext context) async {
-    String actualResult;
-    var entryUri = data.uri;
-    var component = data.component;
-
-    var errors = verifyComponent(component, isOutline: false);
-    if (!errors.isEmpty) {
-      return new Result<_IntermediateData>(
-          data, context.expectationSet["VerificationError"], errors, null);
-    }
-
-    // Build a text representation of what we expect to be retained.
-    var buffer = new StringBuffer();
-
-    buffer.writeln('''
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true''');
-
-    for (var library in component.libraries) {
-      var importUri = library.importUri;
-      if (importUri == entryUri) continue;
-      if (importUri.isScheme('dart') && !data.showCoreLibraries) continue;
-      String uri = relativizeUri(library.importUri);
-      buffer.writeln('\nlibrary $uri:');
-      for (var member in library.members) {
-        buffer.writeln('  - member ${member.name}');
-      }
-      for (var typedef_ in library.typedefs) {
-        buffer.writeln('  - typedef ${typedef_.name}');
-      }
-      for (var cls in library.classes) {
-        buffer.writeln('  - class ${cls.name}');
-        for (var member in cls.members) {
-          var name = '${member.name}';
-          if (name == "") {
-            buffer.writeln('    - (default constructor)');
-          } else {
-            buffer.writeln('    - $name');
-          }
-        }
-      }
-    }
-
-    actualResult = "$buffer";
-
-    // Compare against expectations using the text representation.
-    File expectedFile = new File("${entryUri.toFilePath()}.shaker.expect");
-    if (await expectedFile.exists()) {
-      String expected = await expectedFile.readAsString();
-      if (expected.trim() != actualResult.trim()) {
-        if (!updateExpectations) {
-          String diff = await runDiff(expectedFile.uri, actualResult);
-          return fail(
-              null, "$entryUri doesn't match ${expectedFile.uri}\n$diff");
-        }
-      } else {
-        return pass(data);
-      }
-    }
-    if (updateExpectations) {
-      expectedFile.writeAsStringSync(actualResult);
-      return pass(data);
-    } else {
-      return fail(data, """
-Please create file ${expectedFile.path} with this content:
-$buffer""");
-    }
-  }
-}
-
-/// A step that checks outline against an expectation file.
-class CheckOutline extends Step<_IntermediateData, String, ChainContext> {
-  final bool updateExpectations;
-
-  const CheckOutline({this.updateExpectations: false});
-
-  String get name => "match outline expectation";
-
-  Future<Result<String>> run(
-      _IntermediateData data, ChainContext context) async {
-    var entryUri = data.uri;
-    var outline = data.outline;
-
-    var errors = verifyComponent(outline, isOutline: true);
-    if (!errors.isEmpty) {
-      return new Result<String>(
-          null, context.expectationSet["VerificationError"], errors, null);
-    }
-
-    String actualResult;
-    {
-      StringBuffer buffer = new StringBuffer();
-
-      buffer.writeln('''
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true''');
-
-      for (var library in outline.libraries) {
-        if (library.importUri.isScheme('dart') && !data.showCoreLibraries) {
-          continue;
-        }
-        String uri = relativizeUri(library.importUri);
-
-        if (library.isExternal) {
-          if (library.dependencies.isNotEmpty) {
-            return fail(
-                null, 'External library $uri should not have dependencies');
-          }
-          if (library.parts.isNotEmpty) {
-            return fail(null, 'External library $uri should not have parts');
-          }
-        }
-
-        var printer = new Printer(buffer, syntheticNames: new NameSystem());
-        buffer.write('----- ');
-        if (library.isExternal) {
-          buffer.write('external ');
-        }
-        buffer.writeln(uri);
-        printer.writeLibraryFile(library);
-        buffer.writeln();
-      }
-      actualResult = buffer.toString();
-    }
-
-    // Compare against expectations using the text representation.
-    File expectedFile = new File("${entryUri.toFilePath()}.outline.expect");
-    if (await expectedFile.exists()) {
-      String expected = await expectedFile.readAsString();
-      if (expected.trim() != actualResult.trim()) {
-        if (!updateExpectations) {
-          String diff = await runDiff(expectedFile.uri, actualResult);
-          return fail(
-              null, "$entryUri doesn't match ${expectedFile.uri}\n$diff");
-        }
-      } else {
-        return pass(actualResult);
-      }
-    }
-    if (updateExpectations) {
-      expectedFile.writeAsStringSync(actualResult);
-      return pass(actualResult);
-    } else {
-      return fail(actualResult, """
-Please create file ${expectedFile.path} with this content:
-$actualResult""");
-    }
-  }
-}
diff --git a/pkg/front_end/test/fasta/strong_test.dart b/pkg/front_end/test/fasta/strong_test.dart
index d6ec3fe..9adc4aa 100644
--- a/pkg/front_end/test/fasta/strong_test.dart
+++ b/pkg/front_end/test/fasta/strong_test.dart
@@ -11,7 +11,6 @@
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) {
   environment[ENABLE_FULL_COMPILE] = "";
-  environment[AST_KIND_INDEX] = "${AstKind.Kernel.index}";
   environment[STRONG_MODE] = "";
   return FastaContext.create(suite, environment);
 }
diff --git a/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart b/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart
deleted file mode 100644
index 01ac3d2..0000000
--- a/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2017, 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 fasta.analyzer_diet_listener;
-
-import 'package:analyzer/dart/ast/ast.dart' as ast show ClassMember;
-
-import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory;
-
-import 'package:analyzer/dart/element/element.dart' as ast;
-
-import 'package:analyzer/src/dart/element/element.dart' as ast;
-
-import 'package:analyzer/src/dart/element/type.dart' as ast;
-
-import 'package:analyzer/src/fasta/ast_builder.dart' show AstBuilder;
-
-import 'package:front_end/src/fasta/kernel/body_builder.dart' show BodyBuilder;
-
-import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'
-    show TypeInferenceEngine;
-
-import 'package:kernel/ast.dart' show AsyncMarker;
-
-import 'package:front_end/src/fasta/source/stack_listener.dart'
-    show StackListener;
-
-import 'package:front_end/src/fasta/builder/builder.dart';
-
-import 'package:front_end/src/fasta/parser.dart' show MemberKind, Parser;
-
-import 'package:front_end/src/fasta/scanner/token.dart' show StringToken;
-
-import 'package:front_end/src/scanner/token.dart'
-    show Keyword, Token, TokenType;
-
-import 'package:front_end/src/fasta/source/source_library_builder.dart'
-    show SourceLibraryBuilder;
-
-import 'package:front_end/src/fasta/source/diet_listener.dart'
-    show DietListener;
-
-import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
-import 'package:kernel/core_types.dart' show CoreTypes;
-
-class AnalyzerDietListener extends DietListener {
-  /// The body builder for the method currently being compiled, or `null` if no
-  /// method is currently being compiled.
-  ///
-  /// Needed because it performs resolution and type inference.
-  BodyBuilder _bodyBuilder;
-
-  AnalyzerDietListener(SourceLibraryBuilder library, ClassHierarchy hierarchy,
-      CoreTypes coreTypes, TypeInferenceEngine typeInferenceEngine)
-      : super(library, hierarchy, coreTypes, typeInferenceEngine);
-
-  @override
-  void buildFields(int count, Token token, bool isTopLevel) {
-    List<String> names =
-        popList(count, new List<String>.filled(count, null, growable: true));
-    Builder builder = lookupBuilder(token, null, names.first);
-    Token metadata = pop();
-    AstBuilder listener =
-        createListener(builder, memberScope, builder.isInstanceMember);
-
-    if (!isTopLevel) {
-      listener.classDeclaration = astFactory.classDeclaration(
-        null,
-        null,
-        null,
-        new Token(Keyword.CLASS, 0),
-        astFactory.simpleIdentifier(
-            new StringToken.fromString(TokenType.IDENTIFIER, 'Cx', 6)),
-        null,
-        null,
-        null,
-        null,
-        null,
-        // leftBracket
-        <ast.ClassMember>[],
-        null, // rightBracket
-      );
-    }
-
-    _withBodyBuilder(builder, null, () {
-      parseFields(listener, token, metadata, isTopLevel);
-    });
-
-    listener.classDeclaration = null;
-  }
-
-  @override
-  void buildFunctionBody(
-      Token token, ProcedureBuilder builder, MemberKind kind, Token metadata) {
-    Scope typeParameterScope = builder.computeTypeParameterScope(memberScope);
-    Scope formalParameterScope =
-        builder.computeFormalParameterScope(typeParameterScope);
-    assert(typeParameterScope != null);
-    assert(formalParameterScope != null);
-    _withBodyBuilder(builder, formalParameterScope, () {
-      parseFunctionBody(
-          createListener(builder, typeParameterScope, builder.isInstanceMember,
-              formalParameterScope),
-          token,
-          metadata,
-          kind);
-    });
-  }
-
-  StackListener createListener(
-      ModifierBuilder builder, Scope memberScope, bool isInstanceMember,
-      [Scope formalParameterScope]) {
-    return new AstBuilder(
-        null, library.fileUri, builder, memberScope, false, uri);
-  }
-
-  @override
-  AsyncMarker getAsyncMarker(StackListener listener) => null;
-
-  @override
-  void listenerFinishFields(
-      StackListener listener, Token token, Token metadata, bool isTopLevel) {
-    // TODO(paulberry): this duplicates a lot of code from
-    // DietListener.parseFields.
-
-    // At this point the analyzer AST has been built, but it doesn't contain
-    // resolution data or inferred types.  Run the body builder and gather
-    // this information.
-    Parser parser = new Parser(_bodyBuilder);
-    if (isTopLevel) {
-      token = parser.parseTopLevelMember(metadata ?? token);
-    } else {
-      token = parser.parseClassMember(metadata ?? token).next;
-    }
-    _bodyBuilder.finishFields();
-    _bodyBuilder.checkEmpty(token.charOffset);
-  }
-
-  @override
-  void listenerFinishFunction(
-      StackListener listener,
-      Token token,
-      Token metadata,
-      MemberKind kind,
-      List metadataConstants,
-      dynamic formals,
-      AsyncMarker asyncModifier,
-      dynamic body) {
-    // TODO(paulberry): this duplicates a lot of code from
-    // DietListener.parseFunctionBody.
-
-    // At this point the analyzer AST has been built, but it doesn't contain
-    // resolution data or inferred types.  Run the body builder and gather
-    // this information.
-    Parser parser = new Parser(_bodyBuilder);
-    List bodyBuilderMetadataConstants;
-    if (metadata != null) {
-      parser.parseMetadataStar(parser.syntheticPreviousToken(metadata));
-      bodyBuilderMetadataConstants = _bodyBuilder.pop();
-    }
-    token = parser.parseFormalParametersOpt(
-        parser.syntheticPreviousToken(token), kind);
-    var bodyBuilderFormals = _bodyBuilder.pop();
-    _bodyBuilder.checkEmpty(token.next.charOffset);
-    token = parser.parseInitializersOpt(token);
-
-    // Parse the modifier so that the parser's `asyncState` will be set
-    // correctly, but remove the `AsyncModifier` from the listener's stack
-    // because the listener doesn't expect it to be there.
-    token = parser.parseAsyncModifierOpt(token);
-    _bodyBuilder.pop();
-
-    bool isExpression = false;
-    bool allowAbstract = asyncModifier == AsyncMarker.Sync;
-    parser.parseFunctionBody(token, isExpression, allowAbstract);
-    var bodyBuilderBody = _bodyBuilder.pop();
-    _bodyBuilder.checkEmpty(token.charOffset);
-    _bodyBuilder.finishFunction(bodyBuilderMetadataConstants,
-        bodyBuilderFormals, asyncModifier, bodyBuilderBody);
-
-    // Now apply the resolution data and inferred types to the analyzer AST.
-    listener.finishFunction(metadataConstants, formals, asyncModifier, body);
-  }
-
-  /// Calls the parser (via [parserCallback]) using a body builder initialized
-  /// to do type inference for the given [builder].
-  ///
-  /// When parsing methods, [formalParameterScope] should be set to the formal
-  /// parameter scope; otherwise it should be `null`.
-  void _withBodyBuilder(ModifierBuilder builder, Scope formalParameterScope,
-      void parserCallback()) {
-    // Create a body builder to do type inference, and a listener to record the
-    // types that are inferred.
-    _bodyBuilder = super.createListener(
-        builder, memberScope, builder.isInstanceMember, formalParameterScope);
-    // Run the parser callback; this will build the analyzer AST, run
-    // the body builder to do type inference, and then copy the inferred types
-    // over to the analyzer AST.
-    parserCallback();
-    _bodyBuilder = null;
-  }
-}
diff --git a/pkg/front_end/test/fasta/testing/analyzer_loader.dart b/pkg/front_end/test/fasta/testing/analyzer_loader.dart
deleted file mode 100644
index 745cee4..0000000
--- a/pkg/front_end/test/fasta/testing/analyzer_loader.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2017, 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 fasta.analyzer_loader;
-
-import 'package:front_end/src/api_prototype/standard_file_system.dart'
-    show StandardFileSystem;
-
-import 'package:front_end/src/fasta/builder/builder.dart' show LibraryBuilder;
-
-import 'package:front_end/src/fasta/source/source_class_builder.dart'
-    show SourceClassBuilder;
-
-import 'package:front_end/src/fasta/source/source_loader.dart'
-    show SourceLoader;
-
-import 'package:front_end/src/fasta/target_implementation.dart'
-    show TargetImplementation;
-
-import 'analyzer_diet_listener.dart' show AnalyzerDietListener;
-
-class AnalyzerLoader<L> extends SourceLoader<L> {
-  AnalyzerLoader(TargetImplementation target)
-      : super(StandardFileSystem.instance, false, target);
-
-  @override
-  AnalyzerDietListener createDietListener(LibraryBuilder library) {
-    return new AnalyzerDietListener(
-        library, hierarchy, coreTypes, typeInferenceEngine);
-  }
-
-  @override
-  void checkOverrides(List<SourceClassBuilder> sourceClasses) {
-    // Not implemented yet. Requires [hierarchy].
-  }
-}
diff --git a/pkg/front_end/test/fasta/testing/analyzer_target.dart b/pkg/front_end/test/fasta/testing/analyzer_target.dart
deleted file mode 100644
index 45bda44..0000000
--- a/pkg/front_end/test/fasta/testing/analyzer_target.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2017, 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 fasta.analyzer_target;
-
-import 'package:front_end/src/api_prototype/standard_file_system.dart';
-import 'package:kernel/ast.dart' show Library, Source;
-
-import 'package:front_end/src/fasta/kernel/kernel_target.dart'
-    show KernelTarget;
-
-import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
-
-import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
-
-import 'analyzer_loader.dart' show AnalyzerLoader;
-
-class AnalyzerTarget extends KernelTarget {
-  AnalyzerTarget(
-      DillTarget dillTarget, UriTranslator uriTranslator, bool strongMode,
-      [Map<Uri, Source> uriToSource])
-      : super(StandardFileSystem.instance, false, dillTarget, uriTranslator,
-            uriToSource: uriToSource);
-
-  @override
-  AnalyzerLoader<Library> createLoader() => new AnalyzerLoader<Library>(this);
-}
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 39f0bfc..b18da2a 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -72,14 +72,10 @@
 
 export 'package:testing/testing.dart' show Chain, runMe;
 
-import 'analyzer_target.dart' show AnalyzerTarget;
-
 const String STRONG_MODE = " strong mode ";
 
 const String ENABLE_FULL_COMPILE = " full compile ";
 
-const String AST_KIND_INDEX = " AST kind index ";
-
 const String EXPECTATIONS = '''
 [
   {
@@ -97,11 +93,6 @@
   return strongMode ? "strong" : "direct";
 }
 
-enum AstKind {
-  Analyzer,
-  Kernel,
-}
-
 class FastaContext extends ChainContext {
   final UriTranslatorImpl uriTranslator;
   final List<Step> steps;
@@ -128,38 +119,34 @@
       bool updateComments,
       bool skipVm,
       this.uriTranslator,
-      bool fullCompile,
-      AstKind astKind)
+      bool fullCompile)
       : steps = <Step>[
-          new Outline(fullCompile, astKind, strongMode,
-              updateComments: updateComments),
+          new Outline(fullCompile, strongMode, updateComments: updateComments),
           const Print(),
           new Verify(fullCompile)
         ] {
     verificationError = expectationSet["VerificationError"];
-    if (astKind != AstKind.Analyzer) {
+    if (!ignoreExpectations) {
+      steps.add(new MatchExpectation(
+          fullCompile
+              ? ".${generateExpectationName(strongMode)}.expect"
+              : ".outline.expect",
+          updateExpectations: updateExpectations));
+    }
+    if (strongMode) {
+      steps.add(const TypeCheck());
+    }
+    if (fullCompile && !skipVm) {
+      steps.add(const Transform());
       if (!ignoreExpectations) {
         steps.add(new MatchExpectation(
             fullCompile
-                ? ".${generateExpectationName(strongMode)}.expect"
-                : ".outline.expect",
+                ? ".${generateExpectationName(strongMode)}.transformed.expect"
+                : ".outline.transformed.expect",
             updateExpectations: updateExpectations));
       }
-      if (strongMode) {
-        steps.add(const TypeCheck());
-      }
-      if (fullCompile && !skipVm) {
-        steps.add(const Transform());
-        if (!ignoreExpectations) {
-          steps.add(new MatchExpectation(
-              fullCompile
-                  ? ".${generateExpectationName(strongMode)}.transformed.expect"
-                  : ".outline.transformed.expect",
-              updateExpectations: updateExpectations));
-        }
-        steps.add(const WriteDill());
-        steps.add(const Run());
-      }
+      steps.add(const WriteDill());
+      steps.add(const Run());
     }
   }
 
@@ -211,9 +198,6 @@
     if (platformBinaries != null && !platformBinaries.endsWith('/')) {
       platformBinaries = '$platformBinaries/';
     }
-    String astKindString = environment[AST_KIND_INDEX];
-    AstKind astKind =
-        astKindString == null ? null : AstKind.values[int.parse(astKindString)];
     return new FastaContext(
         vm,
         strongMode,
@@ -226,8 +210,7 @@
         updateComments,
         skipVm,
         uriTranslator,
-        environment.containsKey(ENABLE_FULL_COMPILE),
-        astKind);
+        environment.containsKey(ENABLE_FULL_COMPILE));
   }
 }
 
@@ -265,17 +248,15 @@
 class Outline extends Step<TestDescription, Component, FastaContext> {
   final bool fullCompile;
 
-  final AstKind astKind;
-
   final bool strongMode;
 
-  const Outline(this.fullCompile, this.astKind, this.strongMode,
+  const Outline(this.fullCompile, this.strongMode,
       {this.updateComments: false});
 
   final bool updateComments;
 
   String get name {
-    return fullCompile ? "${astKind} compile" : "outline";
+    return fullCompile ? "compile" : "outline";
   }
 
   bool get isCompiler => fullCompile;
@@ -297,10 +278,8 @@
       UriTranslatorImpl uriTranslator = new UriTranslatorImpl(
           const TargetLibrariesSpecification('vm'),
           context.uriTranslator.packages);
-      KernelTarget sourceTarget = astKind == AstKind.Analyzer
-          ? new AnalyzerTarget(dillTarget, uriTranslator, strongMode)
-          : new KernelTarget(
-              StandardFileSystem.instance, false, dillTarget, uriTranslator);
+      KernelTarget sourceTarget = new KernelTarget(
+          StandardFileSystem.instance, false, dillTarget, uriTranslator);
 
       Component p;
       try {
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
new file mode 100644
index 0000000..1f6c28f
--- /dev/null
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2018, 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' show Expect;
+
+import 'package:kernel/ast.dart' show Expression, ProcedureKind;
+
+import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show CompilerOptions, FormattedMessage, ProblemHandler;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
+
+import 'package:front_end/src/fasta/kernel/kernel_body_builder.dart'
+    show KernelBodyBuilder;
+
+import 'package:front_end/src/fasta/kernel/kernel_builder.dart'
+    show KernelLibraryBuilder, KernelProcedureBuilder;
+
+import 'package:front_end/src/fasta/kernel/kernel_target.dart'
+    show KernelTarget;
+
+import 'package:front_end/src/fasta/kernel/unlinked_scope.dart'
+    show UnlinkedScope;
+
+import 'package:front_end/src/fasta/parser.dart' show Parser;
+
+import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
+
+import 'package:front_end/src/fasta/scope.dart' show Scope;
+
+import 'package:front_end/src/fasta/severity.dart' show Severity;
+
+ProblemHandler handler;
+
+class MockLibraryBuilder extends KernelLibraryBuilder {
+  MockLibraryBuilder(Uri uri)
+      : super(
+            uri,
+            uri,
+            new KernelTarget(
+                    null,
+                    false,
+                    new DillTarget(
+                        null, null, new NoneTarget(new TargetFlags())),
+                    null)
+                .loader,
+            null,
+            null);
+
+  KernelProcedureBuilder mockProcedure(String name) {
+    return new KernelProcedureBuilder(null, 0, null, name, null, null,
+        ProcedureKind.Getter, this, -1, -1, -1);
+  }
+}
+
+class MockBodyBuilder extends KernelBodyBuilder {
+  MockBodyBuilder.internal(
+      MockLibraryBuilder libraryBuilder, String name, Scope scope)
+      : super(libraryBuilder, libraryBuilder.mockProcedure(name), scope, scope,
+            null, null, null, false, libraryBuilder.uri, null);
+
+  MockBodyBuilder(Uri uri, String name, Scope scope)
+      : this.internal(new MockLibraryBuilder(uri), name, scope);
+}
+
+Expression compileExpression(String source) {
+  KernelBodyBuilder listener = new MockBodyBuilder(
+      Uri.parse("org-dartlang-test:my_library.dart"),
+      "<test>",
+      new UnlinkedScope());
+
+  handler = (FormattedMessage problem, Severity severity,
+      List<FormattedMessage> context) {
+    throw problem.formatted;
+  };
+
+  Token token = scanString(source).tokens;
+  Parser parser = new Parser(listener);
+  parser.parseExpression(parser.syntheticPreviousToken(token));
+  Expression e = listener.popForValue();
+  listener.checkEmpty(-1);
+  return e;
+}
+
+void testExpression(String source, [String expected]) {
+  Expression e = compileExpression(source);
+  String actual =
+      "$e".replaceAll(new RegExp(r'invalid-expression "[^"]*"\.'), "");
+  Expect.stringEquals(expected ?? source, actual);
+  print(e);
+}
+
+main() {
+  CompilerContext context = new CompilerContext(new ProcessedOptions(
+      new CompilerOptions()
+        ..onProblem = (FormattedMessage problem, Severity severity,
+            List<FormattedMessage> context) {
+          handler(problem, severity, context);
+        }));
+  context.runInContext((_) {
+    testExpression("unresolved");
+    testExpression("a + b", "a.+(b)");
+    testExpression("a = b");
+  });
+}
diff --git a/pkg/front_end/testcases/README.md b/pkg/front_end/testcases/README.md
index 6e70b6d..a7d4fb1 100644
--- a/pkg/front_end/testcases/README.md
+++ b/pkg/front_end/testcases/README.md
@@ -11,16 +11,6 @@
 
 The source of truth for these configurations is the file [pkg/front_end/testing.json](../testing.json).
 
-## ast_builder
-
-* Status file: [ast_builder.status](ast_builder.status)
-* Standalone test: [pkg/front_end/test/fasta/ast_builder_test.dart](../test/fasta/ast_builder_test.dart)
-* Expectation prefix: N/A
-* How to update expectations: N/A
-
-This configuration doesn't have expectations as it doesn't produce Kernel AST nodes.
-
-
 ## Dart 1.0 Compilation
 
 * Status file: [compile.status](compile.status)
@@ -44,17 +34,6 @@
 ./pkg/front_end/tool/fasta testing -DupdateExpectations=true outline/test1 outline/test2 ...
 ```
 
-## Tree Shaking
-
-* Status file: [shaker.status](shaker.status)
-* Standalone test: [pkg/front_end/test/fasta/shaker_test.dart](../test/fasta/shaker_test.dart)
-* Expectation prefix: `.shaker.expect`
-* How to update expectations:
-
-```
-./pkg/front_end/tool/fasta testing -DupdateExpectations=true shaker/test1 shaker/test2 ...
-```
-
 ## Dart 2.0 (strong mode)
 
 * Status file: [strong.status](strong.status)
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
deleted file mode 100644
index 6e166ec..0000000
--- a/pkg/front_end/testcases/ast_builder.status
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2017, 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.md file.
-
-# Status file for the ast_builder_test.dart test suite. This is testing
-# generating analyzer ASTs and connecting up type inference information.
-annotation_on_enum_values: Crash
-annotation_top: Crash
-argument_mismatch: Fail
-bug32629: Fail
-dynamic_and_void: Fail
-inference/abstract_class_instantiation: Fail
-inference/constructors_too_many_positional_arguments: Fail
-inference/downwards_inference_annotations: Crash
-inference/downwards_inference_annotations_type_variable: Fail
-inference/downwards_inference_annotations_typedef: Crash
-inference/downwards_inference_on_function_of_t_using_the_t: Fail
-inference/downwards_inference_yield_yield_star: Fail
-inference/future_then_explicit_future: Fail
-inference/generic_functions_return_typedef: Fail
-inference/generic_methods_do_not_infer_invalid_override_of_generic_method: Fail
-inference/generic_methods_handle_override_of_non_generic_with_generic: Fail
-inference/generic_methods_infer_js_builtin: Fail
-inference/infer_method_missing_params: Fail
-inference/top_level_return_and_yield: Fail
-inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: Fail
-inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: Fail
-inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: Fail
-inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: Fail
-inference_new/dependency_only_if_generic_method: Fail
-invocations: VerificationError
-metadata_enum: Crash
-metadata_named_mixin_application: Crash
-minimum_int: Crash
-override_check_accessor_after_inference: Fail
-override_check_accessor_basic: Fail
-override_check_accessor_with_covariant_modifier: Fail
-override_check_after_inference: Fail
-override_check_basic: Fail
-override_check_two_substitutions: Fail
-override_check_with_covariant_modifier: Fail
-rasta/bad_default_constructor: VerificationError
-rasta/issue_000039: VerificationError
-rasta/mandatory_parameter_initializer: VerificationError
-rasta/parser_error: VerificationError
-rasta/unresolved_for_in: Crash
-regress/issue_29941: Crash
-regress/issue_29943: Crash
-regress/issue_29983: Crash # 'package:analyzer/src/fasta/ast_builder.dart': Failed assertion: line 478 pos 12: 'star == null': is not true.
-regress/issue_31157: Crash
-regress/issue_31180: Crash
-regress/issue_31186: Crash
-regress/issue_31187: Crash
-warn_unresolved_sends: Fail
diff --git a/pkg/front_end/testcases/bug32414a.dart b/pkg/front_end/testcases/bug32414a.dart
new file mode 100644
index 0000000..06a517c
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+/*@testedFeatures=inference*/
+
+void test() {
+  dynamic a = 5;
+  var /*@type=String*/ b = a. /*@target=Object::toString*/ toString();
+  b = 42;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/bug32414a.dart.direct.expect b/pkg/front_end/testcases/bug32414a.dart.direct.expect
new file mode 100644
index 0000000..95ea9bc
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart.direct.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+
+static method test() → void {
+  dynamic a = 5;
+  dynamic b = a.toString();
+  b = 42;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414a.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32414a.dart.direct.transformed.expect
new file mode 100644
index 0000000..95ea9bc
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart.direct.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+
+static method test() → void {
+  dynamic a = 5;
+  dynamic b = a.toString();
+  b = 42;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414a.dart.outline.expect b/pkg/front_end/testcases/bug32414a.dart.outline.expect
new file mode 100644
index 0000000..a440da0
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method test() → void
+  ;
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/bug32414a.dart.strong.expect b/pkg/front_end/testcases/bug32414a.dart.strong.expect
new file mode 100644
index 0000000..3e11c16
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart.strong.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  dynamic a = 5;
+  core::String b = a.{core::Object::toString}();
+  b = let final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/bug32414a.dart:10:7: Error: A value of type 'dart.core::int' can't be assigned to a variable of type 'dart.core::String'.
+Try changing the type of the left hand side, or casting the right hand side to 'dart.core::String'.
+  b = 42;
+      ^" in let final dynamic #t2 = 42 in null;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414a.dart.strong.transformed.expect b/pkg/front_end/testcases/bug32414a.dart.strong.transformed.expect
new file mode 100644
index 0000000..96b25c6
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  dynamic a = 5;
+  core::String b = a.{core::Object::toString}();
+  b = let final dynamic #t1 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/bug32414a.dart:10:7: Error: A value of type 'dart.core::int' can't be assigned to a variable of type 'dart.core::String'.
+Try changing the type of the left hand side, or casting the right hand side to 'dart.core::String'.
+  b = 42;
+      ^" in let final core::int #t2 = 42 in null;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414b.dart b/pkg/front_end/testcases/bug32414b.dart
new file mode 100644
index 0000000..a9a0a7e
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414b.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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.
+
+/*@testedFeatures=inference*/
+
+void test() {
+  List<dynamic> l = /*@typeArgs=dynamic*/ [1, "hello"];
+  List<String> l2 = l
+      . /*@target=Iterable::map*/ /*@typeArgs=String*/ map(
+          /*@returnType=String*/ (dynamic element) =>
+              element. /*@target=Object::toString*/ toString())
+      . /*@target=Iterable::toList*/ toList();
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/bug32414b.dart.direct.expect b/pkg/front_end/testcases/bug32414b.dart.direct.expect
new file mode 100644
index 0000000..1a8ece7
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414b.dart.direct.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  core::List<dynamic> l = <dynamic>[1, "hello"];
+  core::List<core::String> l2 = l.map((dynamic element) → dynamic => element.toString()).toList();
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414b.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32414b.dart.direct.transformed.expect
new file mode 100644
index 0000000..1a8ece7
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414b.dart.direct.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  core::List<dynamic> l = <dynamic>[1, "hello"];
+  core::List<core::String> l2 = l.map((dynamic element) → dynamic => element.toString()).toList();
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414b.dart.outline.expect b/pkg/front_end/testcases/bug32414b.dart.outline.expect
new file mode 100644
index 0000000..a440da0
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414b.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method test() → void
+  ;
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/bug32414b.dart.strong.expect b/pkg/front_end/testcases/bug32414b.dart.strong.expect
new file mode 100644
index 0000000..6a5fde9
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414b.dart.strong.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  core::List<dynamic> l = <dynamic>[1, "hello"];
+  core::List<core::String> l2 = l.{core::Iterable::map}<core::String>((dynamic element) → core::String => element.{core::Object::toString}()).{core::Iterable::toList}();
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug32414b.dart.strong.transformed.expect b/pkg/front_end/testcases/bug32414b.dart.strong.transformed.expect
new file mode 100644
index 0000000..6a5fde9
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414b.dart.strong.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  core::List<dynamic> l = <dynamic>[1, "hello"];
+  core::List<core::String> l2 = l.{core::Iterable::map}<core::String>((dynamic element) → core::String => element.{core::Object::toString}()).{core::Iterable::toList}();
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/bug33099.dart b/pkg/front_end/testcases/bug33099.dart
new file mode 100644
index 0000000..25fd24e
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:mirrors';
+
+const _FailingTest failingTest = const _FailingTest();
+
+class _FailingTest {
+  const _FailingTest();
+}
+
+class MyTest {
+  @failingTest
+  void foo() {}
+}
+
+class MyTest2 extends Object with MyTest {}
+
+main() {
+  ClassMirror classMirror = reflectClass(MyTest2);
+  classMirror.instanceMembers
+      .forEach((Symbol symbol, MethodMirror memberMirror) {
+    if (memberMirror.simpleName == #foo) {
+      print(memberMirror);
+      print(_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+
+bool _hasFailingTestAnnotation(MethodMirror method) {
+  var r = _hasAnnotationInstance(method, failingTest);
+  print('[_hasFailingTestAnnotation] $method $r');
+  return r;
+}
+
+bool _hasAnnotationInstance(DeclarationMirror declaration, instance) =>
+    declaration.metadata.any((InstanceMirror annotation) {
+      print('annotation: ${annotation.reflectee}');
+      return identical(annotation.reflectee, instance);
+    });
diff --git a/pkg/front_end/testcases/bug33099.dart.direct.expect b/pkg/front_end/testcases/bug33099.dart.direct.expect
new file mode 100644
index 0000000..ac82f35
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.direct.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.instanceMembers.forEach((core::Symbol symbol, mir::MethodMirror memberMirror) → dynamic {
+    if(memberMirror.simpleName.==(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  dynamic r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.metadata.any((mir::InstanceMirror annotation) → dynamic {
+    core::print("annotation: ${annotation.reflectee}");
+    return core::identical(annotation.reflectee, instance);
+  });
diff --git a/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect
new file mode 100644
index 0000000..d26b033
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.instanceMembers.forEach((core::Symbol symbol, mir::MethodMirror memberMirror) → dynamic {
+    if(memberMirror.simpleName.==(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  dynamic r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.metadata.any((mir::InstanceMirror annotation) → dynamic {
+    core::print("annotation: ${annotation.reflectee}");
+    return core::identical(annotation.reflectee, instance);
+  });
diff --git a/pkg/front_end/testcases/bug33099.dart.outline.expect b/pkg/front_end/testcases/bug33099.dart.outline.expect
new file mode 100644
index 0000000..9d360a0
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.outline.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method foo() → void
+    ;
+}
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    ;
+}
+static const field self::_FailingTest failingTest;
+static method main() → dynamic
+  ;
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool
+  ;
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  ;
diff --git a/pkg/front_end/testcases/bug33099.dart.strong.expect b/pkg/front_end/testcases/bug33099.dart.strong.expect
new file mode 100644
index 0000000..4119f1c
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.strong.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol symbol, mir::MethodMirror memberMirror) → core::Null {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  core::bool r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.{mir::DeclarationMirror::metadata}.{core::Iterable::any}((mir::InstanceMirror annotation) → core::bool {
+    core::print("annotation: ${annotation.{mir::InstanceMirror::reflectee}}");
+    return core::identical(annotation.{mir::InstanceMirror::reflectee}, instance);
+  });
diff --git a/pkg/front_end/testcases/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/bug33099.dart.strong.transformed.expect
new file mode 100644
index 0000000..072ae37
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.strong.transformed.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol symbol, mir::MethodMirror memberMirror) → core::Null {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  core::bool r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.{mir::DeclarationMirror::metadata}.{core::Iterable::any}((mir::InstanceMirror annotation) → core::bool {
+    core::print("annotation: ${annotation.{mir::InstanceMirror::reflectee}}");
+    return core::identical(annotation.{mir::InstanceMirror::reflectee}, instance);
+  });
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart b/pkg/front_end/testcases/inference/dynamic_methods.dart
index 76fc820..509a8f3 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart
@@ -11,21 +11,24 @@
 
 test() {
   dynamic d = new Foo();
-  var /*@type=dynamic*/ get_hashCode = d.hashCode;
-  var /*@type=dynamic*/ call_hashCode = d.hashCode();
-  var /*@type=dynamic*/ call_toString = d.toString();
+  var /*@type=int*/ get_hashCode = d. /*@target=Object::hashCode*/ hashCode;
+  var /*@type=dynamic*/ call_hashCode =
+      d. /*@target=Object::hashCode*/ hashCode();
+  var /*@type=String*/ call_toString =
+      d. /*@target=Object::toString*/ toString();
   var /*@type=dynamic*/ call_toStringArg = d.toString(color: "pink");
   var /*@type=dynamic*/ call_foo0 = d.foo();
   var /*@type=dynamic*/ call_foo1 = d.foo(1);
   var /*@type=dynamic*/ call_foo2 = d.foo(1, 2);
   var /*@type=dynamic*/ call_nsm0 = d.noSuchMethod();
-  var /*@type=dynamic*/ call_nsm1 = d.noSuchMethod(null);
+  var /*@type=dynamic*/ call_nsm1 =
+      d. /*@target=Object::noSuchMethod*/ noSuchMethod(null);
   var /*@type=dynamic*/ call_nsm2 = d.noSuchMethod(null, null);
-  var /*@type=bool*/ equals_self = d == d;
-  var /*@type=bool*/ equals_null = d == null;
+  var /*@type=bool*/ equals_self = d /*@target=Object::==*/ == d;
+  var /*@type=bool*/ equals_null = d /*@target=Object::==*/ == null;
   var /*@type=bool*/ null_equals = null /*@target=Object::==*/ == d;
-  var /*@type=bool*/ not_equals_self = d != d;
-  var /*@type=bool*/ not_equals_null = d != null;
+  var /*@type=bool*/ not_equals_self = d /*@target=Object::==*/ != d;
+  var /*@type=bool*/ not_equals_null = d /*@target=Object::==*/ != null;
   var /*@type=bool*/ null_not_equals = null /*@target=Object::==*/ != d;
 }
 
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
index 97bedda..452d130 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
@@ -11,21 +11,21 @@
 }
 static method test() → dynamic {
   dynamic d = new self::Foo::•();
-  dynamic get_hashCode = d.hashCode;
-  dynamic call_hashCode = d.hashCode();
-  dynamic call_toString = d.toString();
+  core::int get_hashCode = d.{core::Object::hashCode};
+  dynamic call_hashCode = d.{core::Object::hashCode}();
+  core::String call_toString = d.{core::Object::toString}();
   dynamic call_toStringArg = d.toString(color: "pink");
   dynamic call_foo0 = d.foo();
   dynamic call_foo1 = d.foo(1);
   dynamic call_foo2 = d.foo(1, 2);
   dynamic call_nsm0 = d.noSuchMethod();
-  dynamic call_nsm1 = d.noSuchMethod(null);
+  dynamic call_nsm1 = d.{core::Object::noSuchMethod}(null);
   dynamic call_nsm2 = d.noSuchMethod(null, null);
-  core::bool equals_self = d.==(d);
-  core::bool equals_null = d.==(null);
+  core::bool equals_self = d.{core::Object::==}(d);
+  core::bool equals_null = d.{core::Object::==}(null);
   core::bool null_equals = null.{core::Object::==}(d);
-  core::bool not_equals_self = !d.==(d);
-  core::bool not_equals_null = !d.==(null);
+  core::bool not_equals_self = !d.{core::Object::==}(d);
+  core::bool not_equals_null = !d.{core::Object::==}(null);
   core::bool null_not_equals = !null.{core::Object::==}(d);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
index 97bedda..452d130 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
@@ -11,21 +11,21 @@
 }
 static method test() → dynamic {
   dynamic d = new self::Foo::•();
-  dynamic get_hashCode = d.hashCode;
-  dynamic call_hashCode = d.hashCode();
-  dynamic call_toString = d.toString();
+  core::int get_hashCode = d.{core::Object::hashCode};
+  dynamic call_hashCode = d.{core::Object::hashCode}();
+  core::String call_toString = d.{core::Object::toString}();
   dynamic call_toStringArg = d.toString(color: "pink");
   dynamic call_foo0 = d.foo();
   dynamic call_foo1 = d.foo(1);
   dynamic call_foo2 = d.foo(1, 2);
   dynamic call_nsm0 = d.noSuchMethod();
-  dynamic call_nsm1 = d.noSuchMethod(null);
+  dynamic call_nsm1 = d.{core::Object::noSuchMethod}(null);
   dynamic call_nsm2 = d.noSuchMethod(null, null);
-  core::bool equals_self = d.==(d);
-  core::bool equals_null = d.==(null);
+  core::bool equals_self = d.{core::Object::==}(d);
+  core::bool equals_null = d.{core::Object::==}(null);
   core::bool null_equals = null.{core::Object::==}(d);
-  core::bool not_equals_self = !d.==(d);
-  core::bool not_equals_null = !d.==(null);
+  core::bool not_equals_self = !d.{core::Object::==}(d);
+  core::bool not_equals_null = !d.{core::Object::==}(null);
   core::bool null_not_equals = !null.{core::Object::==}(d);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/mixin_super_repeated.dart.strong.expect b/pkg/front_end/testcases/mixin_super_repeated.dart.strong.expect
index 4ece1f0..2050a52 100644
--- a/pkg/front_end/testcases/mixin_super_repeated.dart.strong.expect
+++ b/pkg/front_end/testcases/mixin_super_repeated.dart.strong.expect
@@ -36,10 +36,10 @@
   self::Named named = new self::Named::•();
   named.{self::M::m} = 42;
   named.{self::N::superM} = 87;
-  if(!named.{self::M::m}.==(42)) {
+  if(!named.{self::M::m}.{core::Object::==}(42)) {
     throw "Bad mixin translation of set:superM";
   }
-  if(!named.{self::N::superM}.==(87)) {
+  if(!named.{self::N::superM}.{core::Object::==}(87)) {
     throw "Bad mixin translation of get:superM";
   }
 }
diff --git a/pkg/front_end/testcases/mixin_super_repeated.dart.strong.transformed.expect b/pkg/front_end/testcases/mixin_super_repeated.dart.strong.transformed.expect
index 722cdb3..1bead45 100644
--- a/pkg/front_end/testcases/mixin_super_repeated.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/mixin_super_repeated.dart.strong.transformed.expect
@@ -49,10 +49,10 @@
   self::Named named = new self::Named::•();
   named.{self::M::m} = 42;
   named.{self::N::superM} = 87;
-  if(!named.{self::M::m}.==(42)) {
+  if(!named.{self::M::m}.{core::Object::==}(42)) {
     throw "Bad mixin translation of set:superM";
   }
-  if(!named.{self::N::superM}.==(87)) {
+  if(!named.{self::N::superM}.{core::Object::==}(87)) {
     throw "Bad mixin translation of get:superM";
   }
 }
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index ae45e4b..9cdafa9 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -247,7 +247,6 @@
 inference/unsafe_block_closure_inference_method_call_no_type_param: Fail
 inference/void_return_type_subtypes_dynamic: Fail
 
-rasta/issue_000032: Fail
 rasta/issue_000045: Fail
 rasta/issue_000046: Fail
 rasta/issue_000047: Fail
diff --git a/pkg/front_end/testcases/qualified.dart.strong.expect b/pkg/front_end/testcases/qualified.dart.strong.expect
index ead5697..9dceec4 100644
--- a/pkg/front_end/testcases/qualified.dart.strong.expect
+++ b/pkg/front_end/testcases/qualified.dart.strong.expect
@@ -29,7 +29,9 @@
   lib.Missing method() {}
   ^", "pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
 class Bad extends lib.Missing {
-                  ^", "pkg/front_end/testcases/qualified.dart: Error: Couldn't find constructor 'WrongName'."]/* from null */;
+                  ^", "pkg/front_end/testcases/qualified.dart:13:11: Error: Couldn't find constructor 'WrongName'.
+  factory WrongName() {}
+          ^"]/* from null */;
 static method main() → dynamic {
   new self::C::•<core::String>();
   new self::C::a<core::String>();
diff --git a/pkg/front_end/testcases/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
index 54bc304..2c96429 100644
--- a/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
@@ -35,7 +35,9 @@
   lib.Missing method() {}
   ^", "pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
 class Bad extends lib.Missing {
-                  ^", "pkg/front_end/testcases/qualified.dart: Error: Couldn't find constructor 'WrongName'."]/* from null */;
+                  ^", "pkg/front_end/testcases/qualified.dart:13:11: Error: Couldn't find constructor 'WrongName'.
+  factory WrongName() {}
+          ^"]/* from null */;
 static method main() → dynamic {
   new self::C::•<core::String>();
   new self::C::a<core::String>();
diff --git a/pkg/front_end/testcases/rasta/super.dart.strong.expect b/pkg/front_end/testcases/rasta/super.dart.strong.expect
index a3c04bd..05c0a32 100644
--- a/pkg/front_end/testcases/rasta/super.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.strong.expect
@@ -215,30 +215,30 @@
     self::use(super.m = 42);
     super.{self::A::n} = 42;
     self::use(super.{self::A::n} = 42);
-    super.{self::A::a}.==(null) ?{dynamic} super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t46 = super.{self::A::a} in #t46.==(null) ?{dynamic} super.{self::A::a} = 42 : #t46);
-    super.{self::B::b}.==(null) ?{dynamic} super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t47 = super.{self::B::b} in #t47.==(null) ?{dynamic} super.{self::A::b} = 42 : #t47);
-    super.{self::A::c}.==(null) ?{dynamic} super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t48 = super.{self::A::c} in #t48.==(null) ?{dynamic} super.{self::B::c} = 42 : #t48);
-    super.{self::B::d}.==(null) ?{dynamic} super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t49 = super.{self::B::d} in #t49.==(null) ?{dynamic} super.{self::A::d} = 42 : #t49);
-    super.{self::A::e}.==(null) ?{dynamic} super.e = 42 : null;
-    self::use(let final dynamic #t50 = super.{self::A::e} in #t50.==(null) ?{dynamic} super.e = 42 : #t50);
-    super.{self::A::f}.==(null) ?{dynamic} super.f = 42 : null;
-    self::use(let final dynamic #t51 = super.{self::A::f} in #t51.==(null) ?{dynamic} super.f = 42 : #t51);
-    super.g.==(null) ?{dynamic} super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t52 = super.g in #t52.==(null) ?{dynamic} super.{self::A::g} = 42 : #t52);
-    super.{self::A::h}.==(null) ?{dynamic} super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t53 = super.{self::A::h} in #t53.==(null) ?{dynamic} super.{self::A::h} = 42 : #t53);
-    super.{self::A::i}.==(null) ?{dynamic} super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t54 = super.{self::A::i} in #t54.==(null) ?{dynamic} super.{self::B::i} = 42 : #t54);
-    let final core::int #t55 = 87 in super.{self::A::[]}(#t55).==(null) ?{dynamic} let final core::int #t56 = 42 in let final void #t57 = super.{self::A::[]=}(#t55, #t56) in #t56 : null;
-    self::use(let final core::int #t58 = 87 in let final dynamic #t59 = super.{self::A::[]}(#t58) in #t59.==(null) ?{dynamic} let final core::int #t60 = 42 in let final void #t61 = super.{self::A::[]=}(#t58, #t60) in #t60 : #t59);
-    super.{self::A::m}.==(null) ?{core::Object} super.m = 42 : null;
-    self::use(let final () → void #t62 = super.{self::A::m} in #t62.==(null) ?{core::Object} super.m = 42 : #t62);
-    super.{self::A::n}.==(null) ?{core::Object} super.{self::A::n} = 42 : null;
-    self::use(let final () → void #t63 = super.{self::A::n} in #t63.==(null) ?{core::Object} super.{self::A::n} = 42 : #t63);
+    super.{self::A::a}.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : null;
+    self::use(let final dynamic #t46 = super.{self::A::a} in #t46.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t46);
+    super.{self::B::b}.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : null;
+    self::use(let final dynamic #t47 = super.{self::B::b} in #t47.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t47);
+    super.{self::A::c}.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : null;
+    self::use(let final dynamic #t48 = super.{self::A::c} in #t48.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t48);
+    super.{self::B::d}.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : null;
+    self::use(let final dynamic #t49 = super.{self::B::d} in #t49.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t49);
+    super.{self::A::e}.{core::Object::==}(null) ?{dynamic} super.e = 42 : null;
+    self::use(let final dynamic #t50 = super.{self::A::e} in #t50.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t50);
+    super.{self::A::f}.{core::Object::==}(null) ?{dynamic} super.f = 42 : null;
+    self::use(let final dynamic #t51 = super.{self::A::f} in #t51.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t51);
+    super.g.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : null;
+    self::use(let final dynamic #t52 = super.g in #t52.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t52);
+    super.{self::A::h}.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : null;
+    self::use(let final dynamic #t53 = super.{self::A::h} in #t53.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t53);
+    super.{self::A::i}.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : null;
+    self::use(let final dynamic #t54 = super.{self::A::i} in #t54.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t54);
+    let final core::int #t55 = 87 in super.{self::A::[]}(#t55).{core::Object::==}(null) ?{dynamic} let final core::int #t56 = 42 in let final void #t57 = super.{self::A::[]=}(#t55, #t56) in #t56 : null;
+    self::use(let final core::int #t58 = 87 in let final dynamic #t59 = super.{self::A::[]}(#t58) in #t59.{core::Object::==}(null) ?{dynamic} let final core::int #t60 = 42 in let final void #t61 = super.{self::A::[]=}(#t58, #t60) in #t60 : #t59);
+    super.{self::A::m}.{core::Object::==}(null) ?{core::Object} super.m = 42 : null;
+    self::use(let final () → void #t62 = super.{self::A::m} in #t62.{core::Object::==}(null) ?{core::Object} super.m = 42 : #t62);
+    super.{self::A::n}.{core::Object::==}(null) ?{core::Object} super.{self::A::n} = 42 : null;
+    self::use(let final () → void #t63 = super.{self::A::n} in #t63.{core::Object::==}(null) ?{core::Object} super.{self::A::n} = 42 : #t63);
     super.{self::A::a} = super.{self::A::a}.+(42);
     self::use(super.{self::A::a} = super.{self::A::a}.+(42));
     super.{self::A::b} = super.{self::B::b}.+(42);
@@ -433,7 +433,7 @@
     use(super.n(87));
               ^"]/* from null */;
 static method use(dynamic x) → dynamic {
-  if(x.==(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
+  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
     throw "Shouldn't happen";
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/regress/issue_29986.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29986.dart.direct.expect
index fc0df85..e017490a 100644
--- a/pkg/front_end/testcases/regress/issue_29986.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_29986.dart.direct.expect
@@ -4,8 +4,9 @@
 static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29986.dart:8:13: Error: Expected a function body or '=>'.
 Try adding {}.
 C(this.name);
-            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: 'this' parameters can only be used on constructors.
+            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: Field formal parameters can only be used in a constructor.
+Try removing 'this.'.
 C(this.name);
-  ^"]/* from null */;
+  ^^^^"]/* from null */;
 static method main() → dynamic {}
 static abstract method C(dynamic name) → dynamic;
diff --git a/pkg/front_end/testcases/regress/issue_29986.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29986.dart.direct.transformed.expect
index fc0df85..e017490a 100644
--- a/pkg/front_end/testcases/regress/issue_29986.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29986.dart.direct.transformed.expect
@@ -4,8 +4,9 @@
 static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29986.dart:8:13: Error: Expected a function body or '=>'.
 Try adding {}.
 C(this.name);
-            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: 'this' parameters can only be used on constructors.
+            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: Field formal parameters can only be used in a constructor.
+Try removing 'this.'.
 C(this.name);
-  ^"]/* from null */;
+  ^^^^"]/* from null */;
 static method main() → dynamic {}
 static abstract method C(dynamic name) → dynamic;
diff --git a/pkg/front_end/testcases/regress/issue_29986.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29986.dart.strong.expect
index fc0df85..e017490a 100644
--- a/pkg/front_end/testcases/regress/issue_29986.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29986.dart.strong.expect
@@ -4,8 +4,9 @@
 static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29986.dart:8:13: Error: Expected a function body or '=>'.
 Try adding {}.
 C(this.name);
-            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: 'this' parameters can only be used on constructors.
+            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: Field formal parameters can only be used in a constructor.
+Try removing 'this.'.
 C(this.name);
-  ^"]/* from null */;
+  ^^^^"]/* from null */;
 static method main() → dynamic {}
 static abstract method C(dynamic name) → dynamic;
diff --git a/pkg/front_end/testcases/regress/issue_29986.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29986.dart.strong.transformed.expect
index fc0df85..e017490a 100644
--- a/pkg/front_end/testcases/regress/issue_29986.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29986.dart.strong.transformed.expect
@@ -4,8 +4,9 @@
 static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/regress/issue_29986.dart:8:13: Error: Expected a function body or '=>'.
 Try adding {}.
 C(this.name);
-            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: 'this' parameters can only be used on constructors.
+            ^", "pkg/front_end/testcases/regress/issue_29986.dart:8:3: Error: Field formal parameters can only be used in a constructor.
+Try removing 'this.'.
 C(this.name);
-  ^"]/* from null */;
+  ^^^^"]/* from null */;
 static method main() → dynamic {}
 static abstract method C(dynamic name) → dynamic;
diff --git a/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.expect b/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.expect
index 31007c6..47fe398 100644
--- a/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.expect
+++ b/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.expect
@@ -5,6 +5,6 @@
 static method f(core::List<dynamic> x) → core::bool {
   return x.{core::Iterable::expand}<dynamic>((dynamic y) → core::Iterable<dynamic> {
     return y.split(",") as{TypeError} core::Iterable<dynamic>;
-  }).{core::Iterable::any}((dynamic y) → core::bool => y.==("z"));
+  }).{core::Iterable::any}((dynamic y) → core::bool => y.{core::Object::==}("z"));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.transformed.expect b/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.transformed.expect
index 31007c6..47fe398 100644
--- a/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.strong.transformed.expect
@@ -5,6 +5,6 @@
 static method f(core::List<dynamic> x) → core::bool {
   return x.{core::Iterable::expand}<dynamic>((dynamic y) → core::Iterable<dynamic> {
     return y.split(",") as{TypeError} core::Iterable<dynamic>;
-  }).{core::Iterable::any}((dynamic y) → core::bool => y.==("z"));
+  }).{core::Iterable::any}((dynamic y) → core::bool => y.{core::Object::==}("z"));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/shaker.status b/pkg/front_end/testcases/shaker.status
deleted file mode 100644
index f02e723..0000000
--- a/pkg/front_end/testcases/shaker.status
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, 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.md file.
-
-# Status file for the shaker_test.dart test suite. This is only testing the
-# tree-shaking piece of the modular compilation in fasta.
-
-include_field_type: Fail # Fasta does not create interfaceTarget on accessors.
diff --git a/pkg/front_end/testcases/shaker/empty_program.dart b/pkg/front_end/testcases/shaker/empty_program.dart
deleted file mode 100644
index c4169cb..0000000
--- a/pkg/front_end/testcases/shaker/empty_program.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-// An empty program will include some minimal pieces of dart:core and dart:async
-// that today are required by fasta and by the kernel transformers.
-
-// @@SHOW_CORE_LIBRARIES@@ (special comment for the test framework).
-main() {}
diff --git a/pkg/front_end/testcases/shaker/empty_program.dart.outline.expect b/pkg/front_end/testcases/shaker/empty_program.dart.outline.expect
deleted file mode 100644
index 99fafe3..0000000
--- a/pkg/front_end/testcases/shaker/empty_program.dart.outline.expect
+++ /dev/null
@@ -1,596 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/empty_program.dart
-library;
-import self as self;
-
-static method main() → dynamic;
-
------ external dart:async
-library dart.async;
-import self as self;
-import "dart:core" as core;
-
-typedef ControllerCallback = () → void;
-typedef ControllerCancelCallback = () → dynamic;
-class _AsyncStarStreamController<T extends core::Object> extends core::Object {
-  field self::StreamController<self::_AsyncStarStreamController::T> controller;
-  field core::Function asyncStarBody;
-  field core::bool isAdding;
-  field core::bool onListenReceived;
-  field core::bool isScheduled;
-  field core::bool isSuspendedAtYield;
-  field self::Completer<dynamic> cancellationCompleter;
-  constructor •(core::Function asyncStarBody) → void;
-  get stream() → self::Stream<self::_AsyncStarStreamController::T>;
-  method runBody() → void;
-  method scheduleGenerator() → void;
-  method add(self::_AsyncStarStreamController::T event) → core::bool;
-  method addStream(self::Stream<self::_AsyncStarStreamController::T> stream) → core::bool;
-  method addError(core::Object error, core::StackTrace stackTrace) → void;
-  method close() → dynamic;
-  method onListen() → dynamic;
-  method onResume() → dynamic;
-  method onCancel() → dynamic;
-}
-abstract class FutureOr<T extends core::Object> extends core::Object {
-}
-abstract class Future<T extends core::Object> extends core::Object {
-  static factory microtask<T extends core::Object>(() → self::FutureOr<self::Future::microtask::T> computation) → self::Future<self::Future::microtask::T>;
-  abstract method then<S extends core::Object>((self::Future::T) → self::FutureOr<self::Future::then::S> onValue, {core::Function onError}) → self::Future<self::Future::then::S>;
-  abstract method catchError(core::Function onError, {(core::Object) → core::bool test}) → self::Future<self::Future::T>;
-  abstract method whenComplete(() → self::FutureOr<dynamic> action) → self::Future<self::Future::T>;
-  abstract method asStream() → self::Stream<self::Future::T>;
-  abstract method timeout(core::Duration timeLimit, {() → self::FutureOr<self::Future::T> onTimeout}) → self::Future<self::Future::T>;
-}
-abstract class Completer<T extends core::Object> extends core::Object {
-  static factory sync<T extends core::Object>() → self::Completer<self::Completer::sync::T>;
-  abstract get future() → self::Future<self::Completer::T>;
-  abstract method complete([self::FutureOr<self::Completer::T> value]) → void;
-  abstract method completeError(core::Object error, [core::StackTrace stackTrace]) → void;
-  abstract get isCompleted() → core::bool;
-}
-abstract class Stream<T extends core::Object> extends core::Object {
-  get isBroadcast() → core::bool;
-  method asBroadcastStream({(self::StreamSubscription<self::Stream::T>) → void onListen, (self::StreamSubscription<self::Stream::T>) → void onCancel}) → self::Stream<self::Stream::T>;
-  abstract method listen((self::Stream::T) → void onData, {core::Function onError, () → void onDone, core::bool cancelOnError}) → self::StreamSubscription<self::Stream::T>;
-  method where((self::Stream::T) → core::bool test) → self::Stream<self::Stream::T>;
-  method map<S extends core::Object>((self::Stream::T) → self::Stream::map::S convert) → self::Stream<self::Stream::map::S>;
-  method asyncMap<E extends core::Object>((self::Stream::T) → self::FutureOr<self::Stream::asyncMap::E> convert) → self::Stream<self::Stream::asyncMap::E>;
-  method asyncExpand<E extends core::Object>((self::Stream::T) → self::Stream<self::Stream::asyncExpand::E> convert) → self::Stream<self::Stream::asyncExpand::E>;
-  method handleError(core::Function onError, {(dynamic) → core::bool test}) → self::Stream<self::Stream::T>;
-  method expand<S extends core::Object>((self::Stream::T) → core::Iterable<self::Stream::expand::S> convert) → self::Stream<self::Stream::expand::S>;
-  method pipe(self::StreamConsumer<self::Stream::T> streamConsumer) → self::Future<dynamic>;
-  method transform<S extends core::Object>(self::StreamTransformer<self::Stream::T, self::Stream::transform::S> streamTransformer) → self::Stream<self::Stream::transform::S>;
-  method reduce((self::Stream::T, self::Stream::T) → self::Stream::T combine) → self::Future<self::Stream::T>;
-  method fold<S extends core::Object>(self::Stream::fold::S initialValue, (self::Stream::fold::S, self::Stream::T) → self::Stream::fold::S combine) → self::Future<self::Stream::fold::S>;
-  method join([core::String separator]) → self::Future<core::String>;
-  method contains(core::Object needle) → self::Future<core::bool>;
-  method forEach((self::Stream::T) → void action) → self::Future<dynamic>;
-  method every((self::Stream::T) → core::bool test) → self::Future<core::bool>;
-  method any((self::Stream::T) → core::bool test) → self::Future<core::bool>;
-  get length() → self::Future<core::int>;
-  get isEmpty() → self::Future<core::bool>;
-  method cast<R extends core::Object>() → self::Stream<self::Stream::cast::R>;
-  method retype<R extends core::Object>() → self::Stream<self::Stream::retype::R>;
-  method toList() → self::Future<core::List<self::Stream::T>>;
-  method toSet() → self::Future<core::Set<self::Stream::T>>;
-  method drain<E extends core::Object>([self::Stream::drain::E futureValue]) → self::Future<self::Stream::drain::E>;
-  method take(core::int count) → self::Stream<self::Stream::T>;
-  method takeWhile((self::Stream::T) → core::bool test) → self::Stream<self::Stream::T>;
-  method skip(core::int count) → self::Stream<self::Stream::T>;
-  method skipWhile((self::Stream::T) → core::bool test) → self::Stream<self::Stream::T>;
-  method distinct([(self::Stream::T, self::Stream::T) → core::bool equals]) → self::Stream<self::Stream::T>;
-  get first() → self::Future<self::Stream::T>;
-  get last() → self::Future<self::Stream::T>;
-  get single() → self::Future<self::Stream::T>;
-  method firstWhere((self::Stream::T) → core::bool test, {() → self::Stream::T orElse}) → self::Future<self::Stream::T>;
-  method lastWhere((self::Stream::T) → core::bool test, {() → self::Stream::T orElse}) → self::Future<self::Stream::T>;
-  method singleWhere((self::Stream::T) → core::bool test, {() → self::Stream::T orElse}) → self::Future<self::Stream::T>;
-  method elementAt(core::int index) → self::Future<self::Stream::T>;
-  method timeout(core::Duration timeLimit, {(self::EventSink<self::Stream::T>) → void onTimeout}) → self::Stream<self::Stream::T>;
-}
-abstract class StreamSubscription<T extends core::Object> extends core::Object {
-  abstract method cancel() → self::Future<dynamic>;
-  abstract method onData((self::StreamSubscription::T) → void handleData) → void;
-  abstract method onError(core::Function handleError) → void;
-  abstract method onDone(() → void handleDone) → void;
-  abstract method pause([self::Future<dynamic> resumeSignal]) → void;
-  abstract method resume() → void;
-  abstract get isPaused() → core::bool;
-  abstract method asFuture<E extends core::Object>([self::StreamSubscription::asFuture::E futureValue]) → self::Future<self::StreamSubscription::asFuture::E>;
-}
-abstract class EventSink<T extends core::Object> extends core::Object implements core::Sink<self::EventSink::T> {
-  abstract method add(self::EventSink::T event) → void;
-  abstract method addError(core::Object error, [core::StackTrace stackTrace]) → void;
-  abstract method close() → void;
-}
-abstract class StreamConsumer<S extends core::Object> extends core::Object {
-  abstract method addStream(self::Stream<self::StreamConsumer::S> stream) → self::Future<dynamic>;
-  abstract method close() → self::Future<dynamic>;
-}
-abstract class StreamSink<S extends core::Object> extends core::Object implements self::EventSink<self::StreamSink::S>, self::StreamConsumer<self::StreamSink::S> {
-  abstract method close() → self::Future<dynamic>;
-  abstract get done() → self::Future<dynamic>;
-}
-abstract class StreamTransformer<S extends core::Object, T extends core::Object> extends core::Object {
-  abstract method bind(self::Stream<self::StreamTransformer::S> stream) → self::Stream<self::StreamTransformer::T>;
-  abstract method cast<RS extends core::Object, RT extends core::Object>() → self::StreamTransformer<self::StreamTransformer::cast::RS, self::StreamTransformer::cast::RT>;
-  abstract method retype<RS extends core::Object, RT extends core::Object>() → self::StreamTransformer<self::StreamTransformer::retype::RS, self::StreamTransformer::retype::RT>;
-}
-abstract class StreamIterator<T extends core::Object> extends core::Object {
-  abstract method moveNext() → self::Future<core::bool>;
-  abstract get current() → self::StreamIterator::T;
-  abstract method cancel() → self::Future<dynamic>;
-}
-abstract class StreamController<T extends core::Object> extends core::Object implements self::StreamSink<self::StreamController::T> {
-  abstract get stream() → self::Stream<self::StreamController::T>;
-  abstract get onListen() → () → void;
-  abstract set onListen(() → void onListenHandler) → void;
-  abstract get onPause() → () → void;
-  abstract set onPause(() → void onPauseHandler) → void;
-  abstract get onResume() → () → void;
-  abstract set onResume(() → void onResumeHandler) → void;
-  abstract get onCancel() → () → dynamic;
-  abstract set onCancel(() → dynamic onCancelHandler) → void;
-  abstract get sink() → self::StreamSink<self::StreamController::T>;
-  abstract get isClosed() → core::bool;
-  abstract get isPaused() → core::bool;
-  abstract get hasListener() → core::bool;
-  abstract method add(self::StreamController::T event) → void;
-  abstract method addError(core::Object error, [core::StackTrace stackTrace]) → void;
-  abstract method close() → self::Future<dynamic>;
-  abstract method addStream(self::Stream<self::StreamController::T> source, {core::bool cancelOnError}) → self::Future<dynamic>;
-}
-class _StreamIterator<T extends core::Object> extends core::Object implements self::StreamIterator<self::_StreamIterator::T> {
-  constructor •(final self::Stream<self::_StreamIterator::T> stream) → void;
-  get current() → self::_StreamIterator::T;
-  method moveNext() → self::Future<core::bool>;
-  method cancel() → self::Future<dynamic>;
-}
-static method _asyncThenWrapperHelper(dynamic continuation) → core::Function;
-static method _asyncErrorWrapperHelper(dynamic continuation) → core::Function;
-static method _awaitHelper(dynamic object, core::Function thenCallback, core::Function errorCallback, dynamic awaiter) → self::Future<dynamic>;
-
------ external dart:collection
-library dart.collection;
-import self as self;
-import "dart:core" as core;
-
-abstract class IterableBase<E extends core::Object> extends core::Iterable<self::IterableBase::E> {
-}
-
------ external dart:_internal
-library dart._internal;
-import self as self;
-import "dart:core" as core;
-
-class ExternalName extends core::Object {
-  final field core::String name;
-  const constructor •(core::String name) → void;
-}
-abstract class EfficientLengthIterable<T extends core::Object> extends core::Iterable<self::EfficientLengthIterable::T> {
-  abstract get length() → core::int;
-}
-class Symbol extends core::Object implements core::Symbol {
-  operator ==(dynamic other) → core::bool;
-  external get hashCode() → core::int;
-  external method toString() → dynamic;
-}
-
------ external dart:math
-library dart.math;
-import self as self;
-import "dart:core" as core;
-
-abstract class Random extends core::Object {
-  abstract method nextInt(core::int max) → core::int;
-  abstract method nextDouble() → core::double;
-  abstract method nextBool() → core::bool;
-}
-
------ external dart:core
-library dart.core;
-import self as self;
-import "dart:collection" as col;
-import "dart:_internal" as _in;
-import "dart:math" as math;
-
-typedef _SyncGeneratorCallback<T extends self::Object> = (self::_SyncIterator<T>) → self::bool;
-class _SyncIterable<T extends self::Object> extends col::IterableBase<self::_SyncIterable::T> {
-  const constructor •((self::_SyncIterator<self::_SyncIterable::T>) → self::bool _moveNextFn) → void;
-  get iterator() → self::Iterator<self::_SyncIterable::T>;
-}
-class _SyncIterator<T extends self::Object> extends self::Object implements self::Iterator<self::_SyncIterator::T> {
-  get current() → self::_SyncIterator::T;
-  method moveNext() → self::bool;
-}
-class _CompileTimeError extends self::Error {
-  constructor •(self::String _errorMsg) → void;
-  method toString() → self::String;
-}
-class _DuplicatedFieldInitializerError extends self::Error {
-  constructor •(self::String _name) → void;
-  method toString() → dynamic;
-}
-class _InvocationMirror extends self::Object implements self::Invocation {
-  constructor _withoutType(self::String _functionName, self::List<self::Type> _typeArguments, self::List<dynamic> _positionalArguments, self::Map<self::Symbol, dynamic> _namedArguments, self::bool _isSuperInvocation) → void;
-  get memberName() → self::Symbol;
-  get typeArguments() → self::List<self::Type>;
-  get positionalArguments() → self::List<dynamic>;
-  get namedArguments() → self::Map<self::Symbol, dynamic>;
-  get isMethod() → self::bool;
-  get isAccessor() → self::bool;
-  get isGetter() → self::bool;
-  get isSetter() → self::bool;
-}
-class bool extends self::Object {
-  external get hashCode() → self::int;
-  method toString() → self::String;
-}
-abstract class Comparable<T extends self::Object> extends self::Object {
-  abstract method compareTo(self::Comparable::T other) → self::int;
-}
-abstract class double extends self::num {
-  abstract method remainder(self::num other) → self::double;
-  abstract operator +(self::num other) → self::double;
-  abstract operator -(self::num other) → self::double;
-  abstract operator *(self::num other) → self::double;
-  abstract operator %(self::num other) → self::double;
-  abstract operator /(self::num other) → self::double;
-  abstract operator ~/(self::num other) → self::int;
-  abstract operator unary-() → self::double;
-  abstract method abs() → self::double;
-  abstract get sign() → self::double;
-  abstract method round() → self::int;
-  abstract method floor() → self::int;
-  abstract method ceil() → self::int;
-  abstract method truncate() → self::int;
-  abstract method roundToDouble() → self::double;
-  abstract method floorToDouble() → self::double;
-  abstract method ceilToDouble() → self::double;
-  abstract method truncateToDouble() → self::double;
-  abstract method toString() → self::String;
-}
-class Duration extends self::Object implements self::Comparable<self::Duration> {
-  operator +(self::Duration other) → self::Duration;
-  operator -(self::Duration other) → self::Duration;
-  operator *(self::num factor) → self::Duration;
-  operator ~/(self::int quotient) → self::Duration;
-  operator <(self::Duration other) → self::bool;
-  operator >(self::Duration other) → self::bool;
-  operator <=(self::Duration other) → self::bool;
-  operator >=(self::Duration other) → self::bool;
-  get inDays() → self::int;
-  get inHours() → self::int;
-  get inMinutes() → self::int;
-  get inSeconds() → self::int;
-  get inMilliseconds() → self::int;
-  get inMicroseconds() → self::int;
-  operator ==(dynamic other) → self::bool;
-  get hashCode() → self::int;
-  method compareTo(self::Duration other) → self::int;
-  method toString() → self::String;
-  get isNegative() → self::bool;
-  method abs() → self::Duration;
-  operator unary-() → self::Duration;
-}
-class Error extends self::Object {
-  external get stackTrace() → self::StackTrace;
-}
-class FallThroughError extends self::Error {
-  external constructor _create(self::String url, self::int line) → void;
-  external method toString() → self::String;
-}
-class _ConstantExpressionError extends self::Object {
-  const constructor •() → void;
-}
-abstract class Function extends self::Object {
-  abstract get hashCode() → self::int;
-  abstract operator ==(self::Object other) → self::bool;
-}
-abstract class int extends self::num {
-  abstract operator &(self::int other) → self::int;
-  abstract operator |(self::int other) → self::int;
-  abstract operator ^(self::int other) → self::int;
-  abstract operator ~() → self::int;
-  abstract operator <<(self::int shiftAmount) → self::int;
-  abstract operator >>(self::int shiftAmount) → self::int;
-  abstract method modPow(self::int exponent, self::int modulus) → self::int;
-  abstract method modInverse(self::int modulus) → self::int;
-  abstract method gcd(self::int other) → self::int;
-  abstract get isEven() → self::bool;
-  abstract get isOdd() → self::bool;
-  abstract get bitLength() → self::int;
-  abstract method toUnsigned(self::int width) → self::int;
-  abstract method toSigned(self::int width) → self::int;
-  abstract operator unary-() → self::int;
-  abstract method abs() → self::int;
-  abstract get sign() → self::int;
-  abstract method round() → self::int;
-  abstract method floor() → self::int;
-  abstract method ceil() → self::int;
-  abstract method truncate() → self::int;
-  abstract method roundToDouble() → self::double;
-  abstract method floorToDouble() → self::double;
-  abstract method ceilToDouble() → self::double;
-  abstract method truncateToDouble() → self::double;
-  abstract method toString() → self::String;
-  abstract method toRadixString(self::int radix) → self::String;
-}
-abstract class Invocation extends self::Object {
-  abstract get memberName() → self::Symbol;
-  get typeArguments() → self::List<self::Type>;
-  abstract get positionalArguments() → self::List<dynamic>;
-  abstract get namedArguments() → self::Map<self::Symbol, dynamic>;
-  abstract get isMethod() → self::bool;
-  abstract get isGetter() → self::bool;
-  abstract get isSetter() → self::bool;
-  get isAccessor() → self::bool;
-}
-abstract class Iterable<E extends self::Object> extends self::Object {
-  abstract get iterator() → self::Iterator<self::Iterable::E>;
-  method cast<R extends self::Object>() → self::Iterable<self::Iterable::cast::R>;
-  method retype<R extends self::Object>() → self::Iterable<self::Iterable::retype::R>;
-  method followedBy(self::Iterable<self::Iterable::E> other) → self::Iterable<self::Iterable::E>;
-  method map<T extends self::Object>((self::Iterable::E) → self::Iterable::map::T f) → self::Iterable<self::Iterable::map::T>;
-  method where((self::Iterable::E) → self::bool test) → self::Iterable<self::Iterable::E>;
-  method whereType<T extends self::Object>() → self::Iterable<self::Iterable::whereType::T>;
-  method expand<T extends self::Object>((self::Iterable::E) → self::Iterable<self::Iterable::expand::T> f) → self::Iterable<self::Iterable::expand::T>;
-  method contains(self::Object element) → self::bool;
-  method forEach((self::Iterable::E) → void f) → void;
-  method reduce((self::Iterable::E, self::Iterable::E) → self::Iterable::E combine) → self::Iterable::E;
-  method fold<T extends self::Object>(self::Iterable::fold::T initialValue, (self::Iterable::fold::T, self::Iterable::E) → self::Iterable::fold::T combine) → self::Iterable::fold::T;
-  method every((self::Iterable::E) → self::bool test) → self::bool;
-  method join([self::String separator]) → self::String;
-  method any((self::Iterable::E) → self::bool test) → self::bool;
-  method toList({self::bool growable}) → self::List<self::Iterable::E>;
-  method toSet() → self::Set<self::Iterable::E>;
-  get length() → self::int;
-  get isEmpty() → self::bool;
-  get isNotEmpty() → self::bool;
-  method take(self::int count) → self::Iterable<self::Iterable::E>;
-  method takeWhile((self::Iterable::E) → self::bool test) → self::Iterable<self::Iterable::E>;
-  method skip(self::int count) → self::Iterable<self::Iterable::E>;
-  method skipWhile((self::Iterable::E) → self::bool test) → self::Iterable<self::Iterable::E>;
-  get first() → self::Iterable::E;
-  get last() → self::Iterable::E;
-  get single() → self::Iterable::E;
-  method firstWhere((self::Iterable::E) → self::bool test, {() → self::Iterable::E orElse}) → self::Iterable::E;
-  method lastWhere((self::Iterable::E) → self::bool test, {() → self::Iterable::E orElse}) → self::Iterable::E;
-  method singleWhere((self::Iterable::E) → self::bool test, {() → self::Iterable::E orElse}) → self::Iterable::E;
-  method elementAt(self::int index) → self::Iterable::E;
-  method toString() → self::String;
-}
-abstract class BidirectionalIterator<E extends self::Object> extends self::Object implements self::Iterator<self::BidirectionalIterator::E> {
-  abstract method movePrevious() → self::bool;
-}
-abstract class Iterator<E extends self::Object> extends self::Object {
-  abstract method moveNext() → self::bool;
-  abstract get current() → self::Iterator::E;
-}
-abstract class List<E extends self::Object> extends self::Object implements _in::EfficientLengthIterable<self::List::E> {
-  external static factory from<E extends self::Object>(self::Iterable<dynamic> elements, {self::bool growable}) → self::List<self::List::from::E>;
-  abstract method cast<R extends self::Object>() → self::List<self::List::cast::R>;
-  abstract method retype<R extends self::Object>() → self::List<self::List::retype::R>;
-  abstract operator [](self::int index) → self::List::E;
-  abstract operator []=(self::int index, self::List::E value) → void;
-  abstract set first(self::List::E value) → void;
-  abstract set last(self::List::E value) → void;
-  abstract get length() → self::int;
-  abstract set length(self::int newLength) → dynamic;
-  abstract method add(self::List::E value) → void;
-  abstract method addAll(self::Iterable<self::List::E> iterable) → void;
-  abstract get reversed() → self::Iterable<self::List::E>;
-  abstract method sort([(self::List::E, self::List::E) → self::int compare]) → void;
-  abstract method shuffle([math::Random random]) → void;
-  abstract method indexOf(self::List::E element, [self::int start]) → self::int;
-  abstract method indexWhere((self::List::E) → self::bool test, [self::int start]) → self::int;
-  abstract method lastIndexWhere((self::List::E) → self::bool test, [self::int start]) → self::int;
-  abstract method lastIndexOf(self::List::E element, [self::int start]) → self::int;
-  abstract method clear() → void;
-  abstract method insert(self::int index, self::List::E element) → void;
-  abstract method insertAll(self::int index, self::Iterable<self::List::E> iterable) → void;
-  abstract method setAll(self::int index, self::Iterable<self::List::E> iterable) → void;
-  abstract method remove(self::Object value) → self::bool;
-  abstract method removeAt(self::int index) → self::List::E;
-  abstract method removeLast() → self::List::E;
-  abstract method removeWhere((self::List::E) → self::bool test) → void;
-  abstract method retainWhere((self::List::E) → self::bool test) → void;
-  abstract operator +(self::List<self::List::E> other) → self::List<self::List::E>;
-  abstract method sublist(self::int start, [self::int end]) → self::List<self::List::E>;
-  abstract method getRange(self::int start, self::int end) → self::Iterable<self::List::E>;
-  abstract method setRange(self::int start, self::int end, self::Iterable<self::List::E> iterable, [self::int skipCount]) → void;
-  abstract method removeRange(self::int start, self::int end) → void;
-  abstract method fillRange(self::int start, self::int end, [self::List::E fillValue]) → void;
-  abstract method replaceRange(self::int start, self::int end, self::Iterable<self::List::E> replacement) → void;
-  abstract method asMap() → self::Map<self::int, self::List::E>;
-}
-abstract class Map<K extends self::Object, V extends self::Object> extends self::Object {
-  abstract method cast<RK extends self::Object, RV extends self::Object>() → self::Map<self::Map::cast::RK, self::Map::cast::RV>;
-  abstract method retype<RK extends self::Object, RV extends self::Object>() → self::Map<self::Map::retype::RK, self::Map::retype::RV>;
-  abstract method containsValue(self::Object value) → self::bool;
-  abstract method containsKey(self::Object key) → self::bool;
-  abstract operator [](self::Object key) → self::Map::V;
-  abstract operator []=(self::Map::K key, self::Map::V value) → void;
-  abstract get entries() → self::Iterable<self::MapEntry<self::Map::K, self::Map::V>>;
-  abstract method map<K2 extends self::Object, V2 extends self::Object>((self::Map::K, self::Map::V) → self::MapEntry<self::Map::map::K2, self::Map::map::V2> f) → self::Map<self::Map::map::K2, self::Map::map::V2>;
-  abstract method addEntries(self::Iterable<self::MapEntry<self::Map::K, self::Map::V>> newEntries) → void;
-  abstract method update(self::Map::K key, (self::Map::V) → self::Map::V update, {() → self::Map::V ifAbsent}) → self::Map::V;
-  abstract method updateAll((self::Map::K, self::Map::V) → self::Map::V update) → void;
-  abstract method removeWhere((self::Map::K, self::Map::V) → self::bool predicate) → void;
-  abstract method putIfAbsent(self::Map::K key, () → self::Map::V ifAbsent) → self::Map::V;
-  abstract method addAll(self::Map<self::Map::K, self::Map::V> other) → void;
-  abstract method remove(self::Object key) → self::Map::V;
-  abstract method clear() → void;
-  abstract method forEach((self::Map::K, self::Map::V) → void f) → void;
-  abstract get keys() → self::Iterable<self::Map::K>;
-  abstract get values() → self::Iterable<self::Map::V>;
-  abstract get length() → self::int;
-  abstract get isEmpty() → self::bool;
-  abstract get isNotEmpty() → self::bool;
-}
-class MapEntry<K extends self::Object, V extends self::Object> extends self::Object {
-  final field self::MapEntry::K key;
-  final field self::MapEntry::V value;
-  method toString() → self::String;
-}
-class Null extends self::Object {
-  external get hashCode() → self::int;
-  method toString() → self::String;
-}
-abstract class num extends self::Object implements self::Comparable<self::num> {
-  abstract operator ==(self::Object other) → self::bool;
-  abstract get hashCode() → self::int;
-  abstract method compareTo(self::num other) → self::int;
-  abstract operator +(self::num other) → self::num;
-  abstract operator -(self::num other) → self::num;
-  abstract operator *(self::num other) → self::num;
-  abstract operator %(self::num other) → self::num;
-  abstract operator /(self::num other) → self::double;
-  abstract operator ~/(self::num other) → self::int;
-  abstract operator unary-() → self::num;
-  abstract method remainder(self::num other) → self::num;
-  abstract operator <(self::num other) → self::bool;
-  abstract operator <=(self::num other) → self::bool;
-  abstract operator >(self::num other) → self::bool;
-  abstract operator >=(self::num other) → self::bool;
-  abstract get isNaN() → self::bool;
-  abstract get isNegative() → self::bool;
-  abstract get isInfinite() → self::bool;
-  abstract get isFinite() → self::bool;
-  abstract method abs() → self::num;
-  abstract get sign() → self::num;
-  abstract method round() → self::int;
-  abstract method floor() → self::int;
-  abstract method ceil() → self::int;
-  abstract method truncate() → self::int;
-  abstract method roundToDouble() → self::double;
-  abstract method floorToDouble() → self::double;
-  abstract method ceilToDouble() → self::double;
-  abstract method truncateToDouble() → self::double;
-  abstract method clamp(self::num lowerLimit, self::num upperLimit) → self::num;
-  abstract method toInt() → self::int;
-  abstract method toDouble() → self::double;
-  abstract method toStringAsFixed(self::int fractionDigits) → self::String;
-  abstract method toStringAsExponential([self::int fractionDigits]) → self::String;
-  abstract method toStringAsPrecision(self::int precision) → self::String;
-  abstract method toString() → self::String;
-}
-class Object {
-  static final field dynamic _hashCodeRnd;
-  const constructor •() → void;
-  static method _objectHashCode(dynamic obj) → self::int;
-  get _identityHashCode() → self::int;
-  static method _toString(dynamic obj) → self::String;
-  static method _haveSameRuntimeType(dynamic a, dynamic b) → self::bool;
-  method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → self::bool;
-  method _simpleInstanceOf(dynamic type) → self::bool;
-  method _simpleInstanceOfTrue(dynamic type) → self::bool;
-  method _simpleInstanceOfFalse(dynamic type) → self::bool;
-  method _as(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dynamic;
-  external operator ==(dynamic other) → self::bool;
-  external get hashCode() → self::int;
-  external method toString() → self::String;
-  external method noSuchMethod(self::Invocation invocation) → dynamic;
-  external get runtimeType() → self::Type;
-}
-abstract class Pattern extends self::Object {
-  abstract method allMatches(self::String string, [self::int start]) → self::Iterable<self::Match>;
-  abstract method matchAsPrefix(self::String string, [self::int start]) → self::Match;
-}
-abstract class Match extends self::Object {
-  abstract get start() → self::int;
-  abstract get end() → self::int;
-  abstract method group(self::int group) → self::String;
-  abstract operator [](self::int group) → self::String;
-  abstract method groups(self::List<self::int> groupIndices) → self::List<self::String>;
-  abstract get groupCount() → self::int;
-  abstract get input() → self::String;
-  abstract get pattern() → self::Pattern;
-}
-abstract class Set<E extends self::Object> extends _in::EfficientLengthIterable<self::Set::E> {
-  abstract method cast<R extends self::Object>() → self::Set<self::Set::cast::R>;
-  abstract method retype<R extends self::Object>() → self::Set<self::Set::retype::R>;
-  abstract get iterator() → self::Iterator<self::Set::E>;
-  abstract method contains(self::Object value) → self::bool;
-  abstract method add(self::Set::E value) → self::bool;
-  abstract method addAll(self::Iterable<self::Set::E> elements) → void;
-  abstract method remove(self::Object value) → self::bool;
-  abstract method lookup(self::Object object) → self::Set::E;
-  abstract method removeAll(self::Iterable<self::Object> elements) → void;
-  abstract method retainAll(self::Iterable<self::Object> elements) → void;
-  abstract method removeWhere((self::Set::E) → self::bool test) → void;
-  abstract method retainWhere((self::Set::E) → self::bool test) → void;
-  abstract method containsAll(self::Iterable<self::Object> other) → self::bool;
-  abstract method intersection(self::Set<self::Object> other) → self::Set<self::Set::E>;
-  abstract method union(self::Set<self::Set::E> other) → self::Set<self::Set::E>;
-  abstract method difference(self::Set<self::Object> other) → self::Set<self::Set::E>;
-  abstract method clear() → void;
-  abstract method toSet() → self::Set<self::Set::E>;
-}
-abstract class Sink<T extends self::Object> extends self::Object {
-  abstract method add(self::Sink::T data) → void;
-  abstract method close() → void;
-}
-abstract class StackTrace extends self::Object {
-  abstract method toString() → self::String;
-}
-abstract class String extends self::Object implements self::Comparable<self::String>, self::Pattern {
-  abstract operator [](self::int index) → self::String;
-  abstract method codeUnitAt(self::int index) → self::int;
-  abstract get length() → self::int;
-  abstract get hashCode() → self::int;
-  abstract operator ==(self::Object other) → self::bool;
-  abstract method endsWith(self::String other) → self::bool;
-  abstract method startsWith(self::Pattern pattern, [self::int index]) → self::bool;
-  abstract method indexOf(self::Pattern pattern, [self::int start]) → self::int;
-  abstract method lastIndexOf(self::Pattern pattern, [self::int start]) → self::int;
-  abstract get isEmpty() → self::bool;
-  abstract get isNotEmpty() → self::bool;
-  abstract operator +(self::String other) → self::String;
-  abstract method substring(self::int startIndex, [self::int endIndex]) → self::String;
-  abstract method trim() → self::String;
-  abstract method trimLeft() → self::String;
-  abstract method trimRight() → self::String;
-  abstract operator *(self::int times) → self::String;
-  abstract method padLeft(self::int width, [self::String padding]) → self::String;
-  abstract method padRight(self::int width, [self::String padding]) → self::String;
-  abstract method contains(self::Pattern other, [self::int startIndex]) → self::bool;
-  abstract method replaceFirst(self::Pattern from, self::String to, [self::int startIndex]) → self::String;
-  abstract method replaceFirstMapped(self::Pattern from, (self::Match) → self::String replace, [self::int startIndex]) → self::String;
-  abstract method replaceAll(self::Pattern from, self::String replace) → self::String;
-  abstract method replaceAllMapped(self::Pattern from, (self::Match) → self::String replace) → self::String;
-  abstract method replaceRange(self::int start, self::int end, self::String replacement) → self::String;
-  abstract method split(self::Pattern pattern) → self::List<self::String>;
-  abstract method splitMapJoin(self::Pattern pattern, {(self::Match) → self::String onMatch, (self::String) → self::String onNonMatch}) → self::String;
-  abstract get codeUnits() → self::List<self::int>;
-  abstract get runes() → self::Runes;
-  abstract method toLowerCase() → self::String;
-  abstract method toUpperCase() → self::String;
-}
-class Runes extends self::Iterable<self::int> {
-  final field self::String string;
-  get iterator() → self::RuneIterator;
-  get last() → self::int;
-}
-class RuneIterator extends self::Object implements self::BidirectionalIterator<self::int> {
-  final field self::String string;
-  get rawIndex() → self::int;
-  set rawIndex(self::int rawIndex) → void;
-  method reset([self::int rawIndex]) → void;
-  get current() → self::int;
-  get currentSize() → self::int;
-  get currentAsString() → self::String;
-  method moveNext() → self::bool;
-  method movePrevious() → self::bool;
-}
-abstract class Symbol extends self::Object {
-  abstract get hashCode() → self::int;
-  abstract operator ==(dynamic other) → self::bool;
-}
-abstract class Type extends self::Object {
-}
-static method print(self::Object object) → void;
-
diff --git a/pkg/front_end/testcases/shaker/empty_program.dart.shaker.expect b/pkg/front_end/testcases/shaker/empty_program.dart.shaker.expect
deleted file mode 100644
index ebd2c9b..0000000
--- a/pkg/front_end/testcases/shaker/empty_program.dart.shaker.expect
+++ /dev/null
@@ -1,516 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library dart:async:
-  - member dart.async::_asyncThenWrapperHelper
-  - member dart.async::_asyncErrorWrapperHelper
-  - member dart.async::_awaitHelper
-  - typedef ControllerCallback
-  - typedef ControllerCancelCallback
-  - class _AsyncStarStreamController
-    - controller
-    - asyncStarBody
-    - isAdding
-    - onListenReceived
-    - isScheduled
-    - isSuspendedAtYield
-    - cancellationCompleter
-    - (default constructor)
-    - stream
-    - runBody
-    - scheduleGenerator
-    - add
-    - addStream
-    - addError
-    - close
-    - onListen
-    - onResume
-    - onCancel
-  - class FutureOr
-  - class Future
-    - microtask
-    - then
-    - catchError
-    - whenComplete
-    - asStream
-    - timeout
-  - class Completer
-    - sync
-    - future
-    - complete
-    - completeError
-    - isCompleted
-  - class Stream
-    - isBroadcast
-    - asBroadcastStream
-    - listen
-    - where
-    - map
-    - asyncMap
-    - asyncExpand
-    - handleError
-    - expand
-    - pipe
-    - transform
-    - reduce
-    - fold
-    - join
-    - contains
-    - forEach
-    - every
-    - any
-    - length
-    - isEmpty
-    - cast
-    - retype
-    - toList
-    - toSet
-    - drain
-    - take
-    - takeWhile
-    - skip
-    - skipWhile
-    - distinct
-    - first
-    - last
-    - single
-    - firstWhere
-    - lastWhere
-    - singleWhere
-    - elementAt
-    - timeout
-  - class StreamSubscription
-    - cancel
-    - onData
-    - onError
-    - onDone
-    - pause
-    - resume
-    - isPaused
-    - asFuture
-  - class EventSink
-    - add
-    - addError
-    - close
-  - class StreamConsumer
-    - addStream
-    - close
-  - class StreamSink
-    - close
-    - done
-  - class StreamTransformer
-    - bind
-    - cast
-    - retype
-  - class StreamIterator
-    - moveNext
-    - current
-    - cancel
-  - class StreamController
-    - stream
-    - onListen
-    - onListen
-    - onPause
-    - onPause
-    - onResume
-    - onResume
-    - onCancel
-    - onCancel
-    - sink
-    - isClosed
-    - isPaused
-    - hasListener
-    - add
-    - addError
-    - close
-    - addStream
-  - class _StreamIterator
-    - (default constructor)
-    - current
-    - moveNext
-    - cancel
-
-library dart:collection:
-  - class IterableBase
-
-library dart:_internal:
-  - class ExternalName
-    - name
-    - (default constructor)
-  - class EfficientLengthIterable
-    - length
-  - class Symbol
-    - ==
-    - hashCode
-    - toString
-
-library dart:math:
-  - class Random
-    - nextInt
-    - nextDouble
-    - nextBool
-
-library dart:core:
-  - member print
-  - typedef _SyncGeneratorCallback
-  - class _SyncIterable
-    - (default constructor)
-    - iterator
-  - class _SyncIterator
-    - current
-    - moveNext
-  - class _CompileTimeError
-    - (default constructor)
-    - toString
-  - class _DuplicatedFieldInitializerError
-    - (default constructor)
-    - toString
-  - class _InvocationMirror
-    - dart.core::_withoutType
-    - memberName
-    - typeArguments
-    - positionalArguments
-    - namedArguments
-    - isMethod
-    - isAccessor
-    - isGetter
-    - isSetter
-  - class bool
-    - hashCode
-    - toString
-  - class Comparable
-    - compareTo
-  - class double
-    - remainder
-    - +
-    - -
-    - *
-    - %
-    - /
-    - ~/
-    - unary-
-    - abs
-    - sign
-    - round
-    - floor
-    - ceil
-    - truncate
-    - roundToDouble
-    - floorToDouble
-    - ceilToDouble
-    - truncateToDouble
-    - toString
-  - class Duration
-    - +
-    - -
-    - *
-    - ~/
-    - <
-    - >
-    - <=
-    - >=
-    - inDays
-    - inHours
-    - inMinutes
-    - inSeconds
-    - inMilliseconds
-    - inMicroseconds
-    - ==
-    - hashCode
-    - compareTo
-    - toString
-    - isNegative
-    - abs
-    - unary-
-  - class Error
-    - stackTrace
-  - class FallThroughError
-    - dart.core::_create
-    - toString
-  - class _ConstantExpressionError
-    - (default constructor)
-  - class Function
-    - hashCode
-    - ==
-  - class int
-    - &
-    - |
-    - ^
-    - ~
-    - <<
-    - >>
-    - modPow
-    - modInverse
-    - gcd
-    - isEven
-    - isOdd
-    - bitLength
-    - toUnsigned
-    - toSigned
-    - unary-
-    - abs
-    - sign
-    - round
-    - floor
-    - ceil
-    - truncate
-    - roundToDouble
-    - floorToDouble
-    - ceilToDouble
-    - truncateToDouble
-    - toString
-    - toRadixString
-  - class Invocation
-    - memberName
-    - typeArguments
-    - positionalArguments
-    - namedArguments
-    - isMethod
-    - isGetter
-    - isSetter
-    - isAccessor
-  - class Iterable
-    - iterator
-    - cast
-    - retype
-    - followedBy
-    - map
-    - where
-    - whereType
-    - expand
-    - contains
-    - forEach
-    - reduce
-    - fold
-    - every
-    - join
-    - any
-    - toList
-    - toSet
-    - length
-    - isEmpty
-    - isNotEmpty
-    - take
-    - takeWhile
-    - skip
-    - skipWhile
-    - first
-    - last
-    - single
-    - firstWhere
-    - lastWhere
-    - singleWhere
-    - elementAt
-    - toString
-  - class BidirectionalIterator
-    - movePrevious
-  - class Iterator
-    - moveNext
-    - current
-  - class List
-    - from
-    - cast
-    - retype
-    - []
-    - []=
-    - first
-    - last
-    - length
-    - length
-    - add
-    - addAll
-    - reversed
-    - sort
-    - shuffle
-    - indexOf
-    - indexWhere
-    - lastIndexWhere
-    - lastIndexOf
-    - clear
-    - insert
-    - insertAll
-    - setAll
-    - remove
-    - removeAt
-    - removeLast
-    - removeWhere
-    - retainWhere
-    - +
-    - sublist
-    - getRange
-    - setRange
-    - removeRange
-    - fillRange
-    - replaceRange
-    - asMap
-  - class Map
-    - cast
-    - retype
-    - containsValue
-    - containsKey
-    - []
-    - []=
-    - entries
-    - map
-    - addEntries
-    - update
-    - updateAll
-    - removeWhere
-    - putIfAbsent
-    - addAll
-    - remove
-    - clear
-    - forEach
-    - keys
-    - values
-    - length
-    - isEmpty
-    - isNotEmpty
-  - class MapEntry
-    - key
-    - value
-    - toString
-  - class Null
-    - hashCode
-    - toString
-  - class num
-    - ==
-    - hashCode
-    - compareTo
-    - +
-    - -
-    - *
-    - %
-    - /
-    - ~/
-    - unary-
-    - remainder
-    - <
-    - <=
-    - >
-    - >=
-    - isNaN
-    - isNegative
-    - isInfinite
-    - isFinite
-    - abs
-    - sign
-    - round
-    - floor
-    - ceil
-    - truncate
-    - roundToDouble
-    - floorToDouble
-    - ceilToDouble
-    - truncateToDouble
-    - clamp
-    - toInt
-    - toDouble
-    - toStringAsFixed
-    - toStringAsExponential
-    - toStringAsPrecision
-    - toString
-  - class Object
-    - dart.core::_hashCodeRnd
-    - (default constructor)
-    - dart.core::_objectHashCode
-    - dart.core::_identityHashCode
-    - dart.core::_toString
-    - dart.core::_haveSameRuntimeType
-    - dart.core::_instanceOf
-    - dart.core::_simpleInstanceOf
-    - dart.core::_simpleInstanceOfTrue
-    - dart.core::_simpleInstanceOfFalse
-    - dart.core::_as
-    - ==
-    - hashCode
-    - toString
-    - noSuchMethod
-    - runtimeType
-  - class Pattern
-    - allMatches
-    - matchAsPrefix
-  - class Match
-    - start
-    - end
-    - group
-    - []
-    - groups
-    - groupCount
-    - input
-    - pattern
-  - class Set
-    - cast
-    - retype
-    - iterator
-    - contains
-    - add
-    - addAll
-    - remove
-    - lookup
-    - removeAll
-    - retainAll
-    - removeWhere
-    - retainWhere
-    - containsAll
-    - intersection
-    - union
-    - difference
-    - clear
-    - toSet
-  - class Sink
-    - add
-    - close
-  - class StackTrace
-    - toString
-  - class String
-    - []
-    - codeUnitAt
-    - length
-    - hashCode
-    - ==
-    - endsWith
-    - startsWith
-    - indexOf
-    - lastIndexOf
-    - isEmpty
-    - isNotEmpty
-    - +
-    - substring
-    - trim
-    - trimLeft
-    - trimRight
-    - *
-    - padLeft
-    - padRight
-    - contains
-    - replaceFirst
-    - replaceFirstMapped
-    - replaceAll
-    - replaceAllMapped
-    - replaceRange
-    - split
-    - splitMapJoin
-    - codeUnits
-    - runes
-    - toLowerCase
-    - toUpperCase
-  - class Runes
-    - string
-    - iterator
-    - last
-  - class RuneIterator
-    - string
-    - rawIndex
-    - rawIndex
-    - reset
-    - current
-    - currentSize
-    - currentAsString
-    - moveNext
-    - movePrevious
-  - class Symbol
-    - hashCode
-    - ==
-  - class Type
diff --git a/pkg/front_end/testcases/shaker/error_typedef_not_function.dart b/pkg/front_end/testcases/shaker/error_typedef_not_function.dart
deleted file mode 100644
index c862f36..0000000
--- a/pkg/front_end/testcases/shaker/error_typedef_not_function.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-typedef F = int;
diff --git a/pkg/front_end/testcases/shaker/error_typedef_not_function.dart.outline.expect b/pkg/front_end/testcases/shaker/error_typedef_not_function.dart.outline.expect
deleted file mode 100644
index 445c29e..0000000
--- a/pkg/front_end/testcases/shaker/error_typedef_not_function.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/error_typedef_not_function.dart
-library;
-import self as self;
-
-typedef F = dynamic;
-static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/shaker/error_typedef_not_function.dart:5:11: Error: Can't create typedef from non-function type.\ntypedef F = int;\n          ^"]/* from  */;
diff --git a/pkg/front_end/testcases/shaker/error_typedef_not_function.dart.shaker.expect b/pkg/front_end/testcases/shaker/error_typedef_not_function.dart.shaker.expect
deleted file mode 100644
index 0df054c..0000000
--- a/pkg/front_end/testcases/shaker/error_typedef_not_function.dart.shaker.expect
+++ /dev/null
@@ -1,3 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
diff --git a/pkg/front_end/testcases/shaker/export_class.dart b/pkg/front_end/testcases/shaker/export_class.dart
deleted file mode 100644
index b6bcaea..0000000
--- a/pkg/front_end/testcases/shaker/export_class.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-export 'export_class_lib.dart' show A;
diff --git a/pkg/front_end/testcases/shaker/export_class.dart.outline.expect b/pkg/front_end/testcases/shaker/export_class.dart.outline.expect
deleted file mode 100644
index 0caa543..0000000
--- a/pkg/front_end/testcases/shaker/export_class.dart.outline.expect
+++ /dev/null
@@ -1,27 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/export_class.dart
-library;
-import self as self;
-import "./export_class_lib.dart" as exp;
-additionalExports = (exp::A)
-
-
------ external pkg/front_end/testcases/shaker/export_class_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  static field core::int publicStaticField;
-  field core::int publicInstanceField;
-  constructor •() → void
-    : super core::Object::•();
-  constructor publicConstructor() → void
-    : super core::Object::•();
-  static factory publicFactory() → self::A;
-  static method publicStaticMethod() → void;
-  method publicInstanceMethod() → void;
-}
-
diff --git a/pkg/front_end/testcases/shaker/export_class.dart.shaker.expect b/pkg/front_end/testcases/shaker/export_class.dart.shaker.expect
deleted file mode 100644
index d744aa7..0000000
--- a/pkg/front_end/testcases/shaker/export_class.dart.shaker.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/export_class_lib.dart:
-  - class A
-    - publicStaticField
-    - publicInstanceField
-    - (default constructor)
-    - publicConstructor
-    - publicFactory
-    - publicStaticMethod
-    - publicInstanceMethod
diff --git a/pkg/front_end/testcases/shaker/export_class_lib.dart b/pkg/front_end/testcases/shaker/export_class_lib.dart
deleted file mode 100644
index 9cac086..0000000
--- a/pkg/front_end/testcases/shaker/export_class_lib.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {
-  static int publicStaticField;
-  static int _privateStaticField;
-
-  int publicInstanceField;
-  int _privateInstanceField;
-
-  A();
-
-  A.publicConstructor();
-  A._privateConstructor();
-
-  factory A.publicFactory() => null;
-  factory A._privateFactory() => null;
-
-  static void publicStaticMethod() {}
-  static void _privateStaticMethod() {}
-
-  void publicInstanceMethod() {}
-  void _privateInstanceMethod() {}
-}
-
-class B {
-  int field;
-}
diff --git a/pkg/front_end/testcases/shaker/export_combinators.dart b/pkg/front_end/testcases/shaker/export_combinators.dart
deleted file mode 100644
index aeeeb24..0000000
--- a/pkg/front_end/testcases/shaker/export_combinators.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-export 'export_combinators_lib1.dart' show A2;
-export 'export_combinators_lib2.dart' hide A5;
diff --git a/pkg/front_end/testcases/shaker/export_combinators.dart.outline.expect b/pkg/front_end/testcases/shaker/export_combinators.dart.outline.expect
deleted file mode 100644
index cb203dd..0000000
--- a/pkg/front_end/testcases/shaker/export_combinators.dart.outline.expect
+++ /dev/null
@@ -1,35 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/export_combinators.dart
-library;
-import self as self;
-import "./export_combinators_lib1.dart" as exp;
-import "./export_combinators_lib2.dart" as exp2;
-additionalExports = (exp::A2, exp2::A4, exp2::A6)
-
-
------ external pkg/front_end/testcases/shaker/export_combinators_lib1.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A2 extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-
------ external pkg/front_end/testcases/shaker/export_combinators_lib2.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A4 extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-class A6 extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-
diff --git a/pkg/front_end/testcases/shaker/export_combinators.dart.shaker.expect b/pkg/front_end/testcases/shaker/export_combinators.dart.shaker.expect
deleted file mode 100644
index cfe383d..0000000
--- a/pkg/front_end/testcases/shaker/export_combinators.dart.shaker.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/export_combinators_lib1.dart:
-  - class A2
-    - (default constructor)
-
-library pkg/front_end/testcases/shaker/export_combinators_lib2.dart:
-  - class A4
-    - (default constructor)
-  - class A6
-    - (default constructor)
diff --git a/pkg/front_end/testcases/shaker/export_combinators_lib1.dart b/pkg/front_end/testcases/shaker/export_combinators_lib1.dart
deleted file mode 100644
index 689903c..0000000
--- a/pkg/front_end/testcases/shaker/export_combinators_lib1.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A1 {}
-
-class A2 {}
-
-class A3 {}
diff --git a/pkg/front_end/testcases/shaker/export_combinators_lib2.dart b/pkg/front_end/testcases/shaker/export_combinators_lib2.dart
deleted file mode 100644
index 349830b..0000000
--- a/pkg/front_end/testcases/shaker/export_combinators_lib2.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A4 {}
-
-class A5 {}
-
-class A6 {}
diff --git a/pkg/front_end/testcases/shaker/export_references.dart b/pkg/front_end/testcases/shaker/export_references.dart
deleted file mode 100644
index 80545a5..0000000
--- a/pkg/front_end/testcases/shaker/export_references.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-export 'export_references_lib.dart';
diff --git a/pkg/front_end/testcases/shaker/export_references.dart.outline.expect b/pkg/front_end/testcases/shaker/export_references.dart.outline.expect
deleted file mode 100644
index 3f65083..0000000
--- a/pkg/front_end/testcases/shaker/export_references.dart.outline.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/export_references.dart
-library;
-import self as self;
-import "./export_references_lib.dart" as exp;
-import "./export_references_lib2.dart" as exp2;
-additionalExports = (exp::B, exp2::A)
-
-
------ external pkg/front_end/testcases/shaker/export_references_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class B extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-
------ external pkg/front_end/testcases/shaker/export_references_lib2.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
diff --git a/pkg/front_end/testcases/shaker/export_references.dart.shaker.expect b/pkg/front_end/testcases/shaker/export_references.dart.shaker.expect
deleted file mode 100644
index 3481b49..0000000
--- a/pkg/front_end/testcases/shaker/export_references.dart.shaker.expect
+++ /dev/null
@@ -1,11 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/export_references_lib.dart:
-  - class B
-    - (default constructor)
-
-library pkg/front_end/testcases/shaker/export_references_lib2.dart:
-  - class A
-    - (default constructor)
diff --git a/pkg/front_end/testcases/shaker/export_references_lib.dart b/pkg/front_end/testcases/shaker/export_references_lib.dart
deleted file mode 100644
index 2764df5..0000000
--- a/pkg/front_end/testcases/shaker/export_references_lib.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-export 'export_references_lib2.dart' show A;
-
-class B {}
diff --git a/pkg/front_end/testcases/shaker/export_references_lib2.dart b/pkg/front_end/testcases/shaker/export_references_lib2.dart
deleted file mode 100644
index 4d95543..0000000
--- a/pkg/front_end/testcases/shaker/export_references_lib2.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {}
diff --git a/pkg/front_end/testcases/shaker/export_targets.dart b/pkg/front_end/testcases/shaker/export_targets.dart
deleted file mode 100644
index 261dd78..0000000
--- a/pkg/front_end/testcases/shaker/export_targets.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-export 'lib/targets_top.dart';
diff --git a/pkg/front_end/testcases/shaker/export_targets.dart.outline.expect b/pkg/front_end/testcases/shaker/export_targets.dart.outline.expect
deleted file mode 100644
index 3139b70..0000000
--- a/pkg/front_end/testcases/shaker/export_targets.dart.outline.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/export_targets.dart
-library;
-import self as self;
-import "lib/targets_top.dart" as tar;
-additionalExports = (tar::MyClass, tar::MyFunctionTypeAlias, tar::myTopLevelVariable, tar::myTopLevelFunction)
-
-
------ external pkg/front_end/testcases/shaker/lib/targets_top.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-typedef MyFunctionTypeAlias = () → void;
-class MyClass extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-static field core::int myTopLevelVariable;
-static method myTopLevelFunction() → core::int;
-
diff --git a/pkg/front_end/testcases/shaker/export_targets.dart.shaker.expect b/pkg/front_end/testcases/shaker/export_targets.dart.shaker.expect
deleted file mode 100644
index 372e643..0000000
--- a/pkg/front_end/testcases/shaker/export_targets.dart.shaker.expect
+++ /dev/null
@@ -1,10 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/targets_top.dart:
-  - member myTopLevelVariable
-  - member myTopLevelFunction
-  - typedef MyFunctionTypeAlias
-  - class MyClass
-    - (default constructor)
diff --git a/pkg/front_end/testcases/shaker/lib/sources.dart b/pkg/front_end/testcases/shaker/lib/sources.dart
deleted file mode 100644
index 6c1603d..0000000
--- a/pkg/front_end/testcases/shaker/lib/sources.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-class A1 {}
-
-class A2 {}
-
-class A3 {}
-
-class A4 {}
-
-class A5 {}
-
-class A6 {}
-
-class A7 {}
-
-class A8 {}
-
-class A9 {}
-
-class A10 {}
-
-class A11 {}
-
-class A12 {}
-
-class A13 {}
-
-class A14 {}
-
-class A15 {}
diff --git a/pkg/front_end/testcases/shaker/lib/targets_top.dart b/pkg/front_end/testcases/shaker/lib/targets_top.dart
deleted file mode 100644
index 0c4c70e..0000000
--- a/pkg/front_end/testcases/shaker/lib/targets_top.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-class MyClass {}
-
-typedef void MyFunctionTypeAlias();
-
-int myTopLevelVariable = 0;
-
-int myTopLevelFunction() => 0;
diff --git a/pkg/front_end/testcases/shaker/private_nodes.dart b/pkg/front_end/testcases/shaker/private_nodes.dart
deleted file mode 100644
index 4ba4a42..0000000
--- a/pkg/front_end/testcases/shaker/private_nodes.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'private_nodes_lib.dart';
-
-class _PrivateClass1 {
-  A1 publicField1;
-}
-
-class _PrivateClass2 {
-  A2 publicField2;
-  A3 _privateField2;
-
-  _PrivateClass2();
-  _PrivateClass2._privateConstructor();
-
-  void publicMethod2() {}
-  void _privateMethod2() {}
-}
-
-class _PrivateClass21 extends _PrivateClass2 {
-  A4 publicField21;
-  A5 _privateField21;
-
-  _PrivateClass21();
-  _PrivateClass21.publicConstructor();
-  _PrivateClass21._privateConstructor();
-
-  void publicMethod21() {
-    _privateMethod2();
-    _privateMethod21();
-  }
-
-  void _privateMethod21() {}
-}
-
-class _PrivateClass22 extends _PrivateClass2 {}
-
-class PublicClass extends _PrivateClass21 {
-  A6 publicField;
-  A7 _privateField;
-
-  PublicClass() : super.publicConstructor();
-  PublicClass._privateConstructor() : super._privateConstructor();
-
-  void publicMethod() {}
-  void _privateMethod() {}
-}
-
-A8 publicField;
-
-A9 _privateField;
-
-A10 publicFunction() => null;
-
-A11 _privateFunction() => null;
diff --git a/pkg/front_end/testcases/shaker/private_nodes.dart.outline.expect b/pkg/front_end/testcases/shaker/private_nodes.dart.outline.expect
deleted file mode 100644
index d989526..0000000
--- a/pkg/front_end/testcases/shaker/private_nodes.dart.outline.expect
+++ /dev/null
@@ -1,46 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/private_nodes.dart
-library;
-import self as self;
-import "dart:core" as core;
-import "./private_nodes_lib.dart" as pri;
-
-class _PrivateClass2 extends core::Object {
-  field pri::A2 publicField2;
-  constructor •() → void
-    : super core::Object::•();
-  method publicMethod2() → void;
-}
-class _PrivateClass21 extends self::_PrivateClass2 {
-  field pri::A4 publicField21;
-  constructor publicConstructor() → void
-    : super self::_PrivateClass2::•();
-  method publicMethod21() → void;
-}
-class PublicClass extends self::_PrivateClass21 {
-  field pri::A6 publicField;
-  constructor •() → void
-    : super self::_PrivateClass21::publicConstructor();
-  method publicMethod() → void;
-}
-static field pri::A8 publicField;
-static method publicFunction() → pri::A10;
-
------ external pkg/front_end/testcases/shaker/private_nodes_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A2 extends core::Object {
-}
-class A4 extends core::Object {
-}
-class A6 extends core::Object {
-}
-class A8 extends core::Object {
-}
-class A10 extends core::Object {
-}
-
diff --git a/pkg/front_end/testcases/shaker/private_nodes.dart.shaker.expect b/pkg/front_end/testcases/shaker/private_nodes.dart.shaker.expect
deleted file mode 100644
index 1181e86..0000000
--- a/pkg/front_end/testcases/shaker/private_nodes.dart.shaker.expect
+++ /dev/null
@@ -1,16 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/private_nodes_lib.dart:
-  - class A1
-  - class A2
-  - class A3
-  - class A4
-  - class A5
-  - class A6
-  - class A7
-  - class A8
-  - class A9
-  - class A10
-  - class A11
diff --git a/pkg/front_end/testcases/shaker/private_nodes_lib.dart b/pkg/front_end/testcases/shaker/private_nodes_lib.dart
deleted file mode 100644
index e06929c..0000000
--- a/pkg/front_end/testcases/shaker/private_nodes_lib.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A1 {}
-
-class A2 {}
-
-class A3 {}
-
-class A4 {}
-
-class A5 {}
-
-class A6 {}
-
-class A7 {}
-
-class A8 {}
-
-class A9 {}
-
-class A10 {}
-
-class A11 {}
-
-class A12 {}
diff --git a/pkg/front_end/testcases/shaker/source_class.dart b/pkg/front_end/testcases/shaker/source_class.dart
deleted file mode 100644
index 1ea42b8..0000000
--- a/pkg/front_end/testcases/shaker/source_class.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/sources.dart';
-
-class C {
-  A1 f1;
-  var f2 = A2;
-
-  A3 m1(A4 a, [A5 b]) => null;
-  A3 m2(A4 a, {A6 b}) => null;
-
-  A7 get getter => null;
-  void set setter(A8 v) {}
-}
diff --git a/pkg/front_end/testcases/shaker/source_class.dart.outline.expect b/pkg/front_end/testcases/shaker/source_class.dart.outline.expect
deleted file mode 100644
index 105e644..0000000
--- a/pkg/front_end/testcases/shaker/source_class.dart.outline.expect
+++ /dev/null
@@ -1,40 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/source_class.dart
-library;
-import self as self;
-import "dart:core" as core;
-import "lib/sources.dart" as sou;
-
-class C extends core::Object {
-  field sou::A1 f1;
-  field dynamic f2;
-  synthetic constructor •() → void
-    : super core::Object::•();
-  method m1(sou::A4 a, [sou::A5 b]) → sou::A3;
-  method m2(sou::A4 a, {sou::A6 b}) → sou::A3;
-  get getter() → sou::A7;
-  set setter(sou::A8 v) → void;
-}
-
------ external pkg/front_end/testcases/shaker/lib/sources.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A1 extends core::Object {
-}
-class A3 extends core::Object {
-}
-class A4 extends core::Object {
-}
-class A5 extends core::Object {
-}
-class A6 extends core::Object {
-}
-class A7 extends core::Object {
-}
-class A8 extends core::Object {
-}
-
diff --git a/pkg/front_end/testcases/shaker/source_class.dart.shaker.expect b/pkg/front_end/testcases/shaker/source_class.dart.shaker.expect
deleted file mode 100644
index 6e98ce8..0000000
--- a/pkg/front_end/testcases/shaker/source_class.dart.shaker.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/sources.dart:
-  - class A1
-  - class A2
-  - class A3
-  - class A4
-  - class A5
-  - class A6
-  - class A7
-  - class A8
diff --git a/pkg/front_end/testcases/shaker/source_class_static.dart b/pkg/front_end/testcases/shaker/source_class_static.dart
deleted file mode 100644
index 8b46092..0000000
--- a/pkg/front_end/testcases/shaker/source_class_static.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/sources.dart';
-
-class C {
-  static A1 _privateField;
-  static A2 publicField;
-
-  static A3 _privateMethod() => null;
-  static A4 publicMethod() => null;
-
-  static A5 get _privateGetter => null;
-  static A6 get publicGetter => null;
-
-  static void set _privateSetter(A7 _) {}
-  static void set publicSetter(A8 _) {}
-}
diff --git a/pkg/front_end/testcases/shaker/source_class_static.dart.outline.expect b/pkg/front_end/testcases/shaker/source_class_static.dart.outline.expect
deleted file mode 100644
index de7cbca..0000000
--- a/pkg/front_end/testcases/shaker/source_class_static.dart.outline.expect
+++ /dev/null
@@ -1,31 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/source_class_static.dart
-library;
-import self as self;
-import "dart:core" as core;
-import "lib/sources.dart" as sou;
-
-class C extends core::Object {
-  static field sou::A2 publicField;
-  synthetic constructor •() → void
-    : super core::Object::•();
-  static method publicMethod() → sou::A4;
-  static get publicGetter() → sou::A6;
-  static set publicSetter(sou::A8 _) → void;
-}
-
------ external pkg/front_end/testcases/shaker/lib/sources.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A2 extends core::Object {
-}
-class A4 extends core::Object {
-}
-class A6 extends core::Object {
-}
-class A8 extends core::Object {
-}
diff --git a/pkg/front_end/testcases/shaker/source_class_static.dart.shaker.expect b/pkg/front_end/testcases/shaker/source_class_static.dart.shaker.expect
deleted file mode 100644
index 6e98ce8..0000000
--- a/pkg/front_end/testcases/shaker/source_class_static.dart.shaker.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/sources.dart:
-  - class A1
-  - class A2
-  - class A3
-  - class A4
-  - class A5
-  - class A6
-  - class A7
-  - class A8
diff --git a/pkg/front_end/testcases/shaker/source_constant.dart b/pkg/front_end/testcases/shaker/source_constant.dart
deleted file mode 100644
index 12d2012..0000000
--- a/pkg/front_end/testcases/shaker/source_constant.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'source_constant_lib.dart';
-
-class ClassWithoutConstConstructor {
-  static const int staticConstField = 42;
-  static final int staticFinalField = 42;
-  static int staticField = 42;
-  final int instanceFinalField = 42;
-  int instanceField = 42;
-
-  ClassWithoutConstConstructor([int p = 42]);
-}
-
-class ClassWithConstConstructor {
-  static const int staticConstField = 42;
-  static final int staticFinalField = 42;
-  static int staticField = 42;
-  final int instanceFinalField = 42;
-
-  const ClassWithConstConstructor([int a = 42, b = libConst1]);
-}
-
-const int constField = 42;
-final int finalField = 42;
-int regularField = 42;
diff --git a/pkg/front_end/testcases/shaker/source_constant.dart.outline.expect b/pkg/front_end/testcases/shaker/source_constant.dart.outline.expect
deleted file mode 100644
index 1928816..0000000
--- a/pkg/front_end/testcases/shaker/source_constant.dart.outline.expect
+++ /dev/null
@@ -1,37 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/source_constant.dart
-library;
-import self as self;
-import "dart:core" as core;
-import "./source_constant_lib.dart" as sou;
-
-class ClassWithoutConstConstructor extends core::Object {
-  static const field core::int staticConstField = 42;
-  static final field core::int staticFinalField;
-  static field core::int staticField;
-  final field core::int instanceFinalField;
-  field core::int instanceField;
-  constructor •([core::int p]) → void
-    : super core::Object::•();
-}
-class ClassWithConstConstructor extends core::Object {
-  static const field core::int staticConstField = 42;
-  static final field core::int staticFinalField;
-  static field core::int staticField;
-  final field core::int instanceFinalField = 42;
-  const constructor •([core::int a = 42, dynamic b = sou::libConst1]) → void
-    : super core::Object::•();
-}
-static const field core::int constField = 42;
-static final field core::int finalField;
-static field core::int regularField;
-
------ external pkg/front_end/testcases/shaker/source_constant_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-static const field core::int libConst1 = 1;
-
diff --git a/pkg/front_end/testcases/shaker/source_constant.dart.shaker.expect b/pkg/front_end/testcases/shaker/source_constant.dart.shaker.expect
deleted file mode 100644
index f55a94e..0000000
--- a/pkg/front_end/testcases/shaker/source_constant.dart.shaker.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/source_constant_lib.dart:
-  - member libConst1
diff --git a/pkg/front_end/testcases/shaker/source_constant_lib.dart b/pkg/front_end/testcases/shaker/source_constant_lib.dart
deleted file mode 100644
index e6e8cd4..0000000
--- a/pkg/front_end/testcases/shaker/source_constant_lib.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-const int libConst1 = 1;
-const int libConst2 = 1;
diff --git a/pkg/front_end/testcases/shaker/source_local.dart b/pkg/front_end/testcases/shaker/source_local.dart
deleted file mode 100644
index 2537acf..0000000
--- a/pkg/front_end/testcases/shaker/source_local.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/sources.dart';
-
-void topLevelFunction() {
-  A1 v1;
-  var v2 = A2;
-  print(v1);
-  print(v2);
-}
diff --git a/pkg/front_end/testcases/shaker/source_local.dart.outline.expect b/pkg/front_end/testcases/shaker/source_local.dart.outline.expect
deleted file mode 100644
index cdf9d9a..0000000
--- a/pkg/front_end/testcases/shaker/source_local.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/source_local.dart
-library;
-import self as self;
-
-static method topLevelFunction() → void;
-
diff --git a/pkg/front_end/testcases/shaker/source_local.dart.shaker.expect b/pkg/front_end/testcases/shaker/source_local.dart.shaker.expect
deleted file mode 100644
index 486de3b..0000000
--- a/pkg/front_end/testcases/shaker/source_local.dart.shaker.expect
+++ /dev/null
@@ -1,7 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/sources.dart:
-  - class A1
-  - class A2
diff --git a/pkg/front_end/testcases/shaker/source_top.dart b/pkg/front_end/testcases/shaker/source_top.dart
deleted file mode 100644
index 2e7cefb9..0000000
--- a/pkg/front_end/testcases/shaker/source_top.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/sources.dart';
-
-class C1 extends A1 {}
-
-class C2 implements A2 {}
-
-class C3 extends Object with A3 {}
-
-typedef A4 F1(A5 a, [A6 b]);
-typedef A4 F2(A5 a, {A7 b});
-
-A8 topLevelVariable1;
-var topLevelVariable2 = A9;
-
-A10 topLevelFunction1(A11 a, [A12 b]) => null;
-A10 topLevelFunction2(A11 a, {A13 b}) => null;
-
-@Meta(A14)
-class X {}
-
-class Meta {
-  final f;
-  const Meta(this.f);
-}
diff --git a/pkg/front_end/testcases/shaker/source_top.dart.outline.expect b/pkg/front_end/testcases/shaker/source_top.dart.outline.expect
deleted file mode 100644
index 019bb8a..0000000
--- a/pkg/front_end/testcases/shaker/source_top.dart.outline.expect
+++ /dev/null
@@ -1,74 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/source_top.dart
-library;
-import self as self;
-import "lib/sources.dart" as sou;
-import "dart:core" as core;
-
-typedef F1 = (sou::A5, [sou::A6]) → sou::A4;
-typedef F2 = (sou::A5, {b: sou::A7}) → sou::A4;
-class C1 extends sou::A1 {
-  synthetic constructor •() → void
-    : super sou::A1::•();
-}
-class C2 extends core::Object implements sou::A2 {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-abstract class _C3&Object&A3 extends core::Object implements sou::A3 {
-}
-class C3 extends self::_C3&Object&A3 {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-@self::Meta::•(sou::A14)
-class X extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-class Meta extends core::Object {
-  final field dynamic f;
-  const constructor •(dynamic f) → void
-    : self::Meta::f = f, super core::Object::•();
-}
-static field sou::A8 topLevelVariable1;
-static field dynamic topLevelVariable2;
-static method topLevelFunction1(sou::A11 a, [sou::A12 b]) → sou::A10;
-static method topLevelFunction2(sou::A11 a, {sou::A13 b}) → sou::A10;
-
------ external pkg/front_end/testcases/shaker/lib/sources.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A1 extends core::Object {
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-class A2 extends core::Object {
-}
-class A3 extends core::Object {
-}
-class A4 extends core::Object {
-}
-class A5 extends core::Object {
-}
-class A6 extends core::Object {
-}
-class A7 extends core::Object {
-}
-class A8 extends core::Object {
-}
-class A10 extends core::Object {
-}
-class A11 extends core::Object {
-}
-class A12 extends core::Object {
-}
-class A13 extends core::Object {
-}
-class A14 extends core::Object {
-}
-
diff --git a/pkg/front_end/testcases/shaker/source_top.dart.shaker.expect b/pkg/front_end/testcases/shaker/source_top.dart.shaker.expect
deleted file mode 100644
index 176cc92..0000000
--- a/pkg/front_end/testcases/shaker/source_top.dart.shaker.expect
+++ /dev/null
@@ -1,20 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/sources.dart:
-  - class A1
-    - (default constructor)
-  - class A2
-  - class A3
-  - class A4
-  - class A5
-  - class A6
-  - class A7
-  - class A8
-  - class A9
-  - class A10
-  - class A11
-  - class A12
-  - class A13
-  - class A14
diff --git a/pkg/front_end/testcases/shaker/target_class_constructor.dart b/pkg/front_end/testcases/shaker/target_class_constructor.dart
deleted file mode 100644
index 1f0d891..0000000
--- a/pkg/front_end/testcases/shaker/target_class_constructor.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'target_class_constructor_lib.dart';
-
-main() {
-  new B.namedConstructor();
-}
diff --git a/pkg/front_end/testcases/shaker/target_class_constructor.dart.outline.expect b/pkg/front_end/testcases/shaker/target_class_constructor.dart.outline.expect
deleted file mode 100644
index 8b10b8a..0000000
--- a/pkg/front_end/testcases/shaker/target_class_constructor.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_class_constructor.dart
-library;
-import self as self;
-
-static method main() → dynamic;
-
diff --git a/pkg/front_end/testcases/shaker/target_class_constructor.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_class_constructor.dart.shaker.expect
deleted file mode 100644
index 9c94294..0000000
--- a/pkg/front_end/testcases/shaker/target_class_constructor.dart.shaker.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/target_class_constructor_lib.dart:
-  - class A
-    - field
-    - (default constructor)
-    - method
-  - class B
-    - field
-    - namedConstructor
-    - method
diff --git a/pkg/front_end/testcases/shaker/target_class_constructor_lib.dart b/pkg/front_end/testcases/shaker/target_class_constructor_lib.dart
deleted file mode 100644
index f74d689..0000000
--- a/pkg/front_end/testcases/shaker/target_class_constructor_lib.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {
-  int field;
-
-  A();
-  A.namedConstructor();
-
-  void method() {}
-}
-
-class B extends A {
-  int field;
-
-  B();
-  B.namedConstructor() : field = 0;
-
-  void method() {}
-}
diff --git a/pkg/front_end/testcases/shaker/target_class_static.dart b/pkg/front_end/testcases/shaker/target_class_static.dart
deleted file mode 100644
index 61944a8..0000000
--- a/pkg/front_end/testcases/shaker/target_class_static.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'target_class_static_lib.dart';
-
-main() {
-  A.field1;
-  A.getter1;
-  A.setter1 = 0;
-  A.method1();
-}
diff --git a/pkg/front_end/testcases/shaker/target_class_static.dart.outline.expect b/pkg/front_end/testcases/shaker/target_class_static.dart.outline.expect
deleted file mode 100644
index 3301965..0000000
--- a/pkg/front_end/testcases/shaker/target_class_static.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_class_static.dart
-library;
-import self as self;
-
-static method main() → dynamic;
-
diff --git a/pkg/front_end/testcases/shaker/target_class_static.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_class_static.dart.shaker.expect
deleted file mode 100644
index 84e12b0..0000000
--- a/pkg/front_end/testcases/shaker/target_class_static.dart.shaker.expect
+++ /dev/null
@@ -1,10 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/target_class_static_lib.dart:
-  - class A
-    - field1
-    - getter1
-    - setter1
-    - method1
diff --git a/pkg/front_end/testcases/shaker/target_class_static_lib.dart b/pkg/front_end/testcases/shaker/target_class_static_lib.dart
deleted file mode 100644
index 52fdef0..0000000
--- a/pkg/front_end/testcases/shaker/target_class_static_lib.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {
-  static int field1;
-  static int field2;
-
-  static int get getter1 => 0;
-  static int get getter2 => 0;
-
-  static void set setter1(int x) {}
-  static void set setter2(int x) {}
-
-  static void method1() {}
-  static void method2() {}
-}
diff --git a/pkg/front_end/testcases/shaker/target_constant.dart b/pkg/front_end/testcases/shaker/target_constant.dart
deleted file mode 100644
index 561e644..0000000
--- a/pkg/front_end/testcases/shaker/target_constant.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'target_constant_lib.dart';
-
-class RefStaticConstFields {
-  static const int staticConstField_from_staticConst = A1.staticConstField1;
-  static int staticConstField_from_static = A1.staticConstField2;
-  static final int staticConstField_from_staticFinal = A1.staticConstField3;
-  final int staticConstField_from_final = A1.staticConstField4;
-  int staticConstField_from_regular = A1.staticConstField5;
-}
-
-class RefNotConstStaticFields {
-  static int ref_staticFinalField = A2.staticFinalField1;
-  static int ref_staticField = A2.staticField1;
-}
-
-class RefNotConstInstanceFields {
-  static int ref_instanceFinalField = new A3().instanceFinalField1;
-  static int ref_instanceField = new A3().instanceField1;
-}
-
-const b = const B();
diff --git a/pkg/front_end/testcases/shaker/target_constant.dart.outline.expect b/pkg/front_end/testcases/shaker/target_constant.dart.outline.expect
deleted file mode 100644
index ed84690..0000000
--- a/pkg/front_end/testcases/shaker/target_constant.dart.outline.expect
+++ /dev/null
@@ -1,54 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_constant.dart
-library;
-import self as self;
-import "dart:core" as core;
-import "./target_constant_lib.dart" as tar;
-
-class RefStaticConstFields extends core::Object {
-  static const field core::int staticConstField_from_staticConst = tar::A1::staticConstField1;
-  static field core::int staticConstField_from_static;
-  static final field core::int staticConstField_from_staticFinal;
-  final field core::int staticConstField_from_final;
-  field core::int staticConstField_from_regular;
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-class RefNotConstStaticFields extends core::Object {
-  static field core::int ref_staticFinalField;
-  static field core::int ref_staticField;
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-class RefNotConstInstanceFields extends core::Object {
-  static field core::int ref_instanceFinalField;
-  static field core::int ref_instanceField;
-  synthetic constructor •() → void
-    : super core::Object::•();
-}
-static const field dynamic b = const tar::B::•();
-
------ external pkg/front_end/testcases/shaker/target_constant_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A1 extends core::Object {
-  static const field core::int staticConstField1 = self::_A12::staticConstField21;
-}
-class _A12 extends core::Object {
-  static const field core::int staticConstField21 = 42;
-}
-class B extends core::Object {
-  final field core::int instanceFinalField1 = self::B2::field21;
-  final field core::int instanceFinalField2 = self::B2::field22;
-  const constructor •() → void
-    : super core::Object::•();
-}
-class B2 extends core::Object {
-  static const field core::int field21 = 42;
-  static const field core::int field22 = 42;
-}
-
diff --git a/pkg/front_end/testcases/shaker/target_constant.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_constant.dart.shaker.expect
deleted file mode 100644
index 6249118..0000000
--- a/pkg/front_end/testcases/shaker/target_constant.dart.shaker.expect
+++ /dev/null
@@ -1,33 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/target_constant_lib.dart:
-  - class A1
-    - staticConstField1
-    - staticConstField2
-    - staticConstField3
-    - staticConstField4
-    - staticConstField5
-  - class _A12
-    - staticConstField21
-    - staticConstField22
-    - staticConstField23
-    - staticConstField24
-    - staticConstField25
-  - class A2
-    - staticFinalField1
-    - staticField1
-  - class A3
-    - instanceFinalField1
-    - instanceFinalField2
-    - instanceField1
-    - instanceField2
-    - (default constructor)
-  - class B
-    - instanceFinalField1
-    - instanceFinalField2
-    - (default constructor)
-  - class B2
-    - field21
-    - field22
diff --git a/pkg/front_end/testcases/shaker/target_constant_lib.dart b/pkg/front_end/testcases/shaker/target_constant_lib.dart
deleted file mode 100644
index d8a27d7..0000000
--- a/pkg/front_end/testcases/shaker/target_constant_lib.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A1 {
-  static const int staticConstField1 = _A12.staticConstField21;
-  static const int staticConstField2 = _A12.staticConstField22;
-  static const int staticConstField3 = _A12.staticConstField23;
-  static const int staticConstField4 = _A12.staticConstField24;
-  static const int staticConstField5 = _A12.staticConstField25;
-  static const int staticConstField6 = _A12.staticConstField26;
-}
-
-class _A12 {
-  static const int staticConstField21 = 42;
-  static const int staticConstField22 = 42;
-  static const int staticConstField23 = 42;
-  static const int staticConstField24 = 42;
-  static const int staticConstField25 = 42;
-  static const int staticConstField26 = 42;
-}
-
-class A2 {
-  static final int staticFinalField1 = 42;
-  static final int staticFinalField2 = 42;
-
-  static int staticField1 = 42;
-  static int staticField2 = 42;
-}
-
-class A3 {
-  final int instanceFinalField1 = 42;
-  final int instanceFinalField2 = 42;
-
-  int instanceField1 = 42;
-  int instanceField2 = 42;
-}
-
-class B {
-  final int instanceFinalField1 = B2.field21;
-  final int instanceFinalField2 = B2.field22;
-
-  const B();
-}
-
-class B2 {
-  static const int field21 = 42;
-  static const int field22 = 42;
-}
diff --git a/pkg/front_end/testcases/shaker/target_top_class.dart b/pkg/front_end/testcases/shaker/target_top_class.dart
deleted file mode 100644
index 893d9ef..0000000
--- a/pkg/front_end/testcases/shaker/target_top_class.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/targets_top.dart';
-
-MyClass c;
diff --git a/pkg/front_end/testcases/shaker/target_top_class.dart.outline.expect b/pkg/front_end/testcases/shaker/target_top_class.dart.outline.expect
deleted file mode 100644
index a7ac881..0000000
--- a/pkg/front_end/testcases/shaker/target_top_class.dart.outline.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_top_class.dart
-library;
-import self as self;
-import "lib/targets_top.dart" as tar;
-
-static field tar::MyClass c;
-
------ external pkg/front_end/testcases/shaker/lib/targets_top.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class MyClass extends core::Object {
-}
-
diff --git a/pkg/front_end/testcases/shaker/target_top_class.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_top_class.dart.shaker.expect
deleted file mode 100644
index 47efc0e..0000000
--- a/pkg/front_end/testcases/shaker/target_top_class.dart.shaker.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/targets_top.dart:
-  - class MyClass
diff --git a/pkg/front_end/testcases/shaker/target_top_function.dart b/pkg/front_end/testcases/shaker/target_top_function.dart
deleted file mode 100644
index 8c366c0..0000000
--- a/pkg/front_end/testcases/shaker/target_top_function.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/targets_top.dart';
-
-var v = myTopLevelFunction();
diff --git a/pkg/front_end/testcases/shaker/target_top_function.dart.outline.expect b/pkg/front_end/testcases/shaker/target_top_function.dart.outline.expect
deleted file mode 100644
index 0686114..0000000
--- a/pkg/front_end/testcases/shaker/target_top_function.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_top_function.dart
-library;
-import self as self;
-
-static field dynamic v;
-
diff --git a/pkg/front_end/testcases/shaker/target_top_function.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_top_function.dart.shaker.expect
deleted file mode 100644
index 19ee457..0000000
--- a/pkg/front_end/testcases/shaker/target_top_function.dart.shaker.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/targets_top.dart:
-  - member myTopLevelFunction
diff --git a/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart b/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart
deleted file mode 100644
index 327060c..0000000
--- a/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/targets_top.dart';
-
-MyFunctionTypeAlias c;
diff --git a/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart.outline.expect b/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart.outline.expect
deleted file mode 100644
index 775f669..0000000
--- a/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart.outline.expect
+++ /dev/null
@@ -1,15 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_top_function_type_alias.dart
-library;
-import self as self;
-
-static field () → void c;
-
------ external pkg/front_end/testcases/shaker/lib/targets_top.dart
-library;
-import self as self;
-
-typedef MyFunctionTypeAlias = () → void;
-
diff --git a/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart.shaker.expect
deleted file mode 100644
index 502a9cd..0000000
--- a/pkg/front_end/testcases/shaker/target_top_function_type_alias.dart.shaker.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/targets_top.dart:
-  - typedef MyFunctionTypeAlias
diff --git a/pkg/front_end/testcases/shaker/target_top_variable.dart b/pkg/front_end/testcases/shaker/target_top_variable.dart
deleted file mode 100644
index 0818f4c..0000000
--- a/pkg/front_end/testcases/shaker/target_top_variable.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'lib/targets_top.dart';
-
-var v = myTopLevelVariable;
diff --git a/pkg/front_end/testcases/shaker/target_top_variable.dart.outline.expect b/pkg/front_end/testcases/shaker/target_top_variable.dart.outline.expect
deleted file mode 100644
index 81b2340..0000000
--- a/pkg/front_end/testcases/shaker/target_top_variable.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/target_top_variable.dart
-library;
-import self as self;
-
-static field dynamic v;
-
diff --git a/pkg/front_end/testcases/shaker/target_top_variable.dart.shaker.expect b/pkg/front_end/testcases/shaker/target_top_variable.dart.shaker.expect
deleted file mode 100644
index 43f5613..0000000
--- a/pkg/front_end/testcases/shaker/target_top_variable.dart.shaker.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/lib/targets_top.dart:
-  - member myTopLevelVariable
diff --git a/pkg/front_end/testcases/shaker/transitive_annotations.dart b/pkg/front_end/testcases/shaker/transitive_annotations.dart
deleted file mode 100644
index 2ca6223..0000000
--- a/pkg/front_end/testcases/shaker/transitive_annotations.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_annotations_lib.dart';
-
-class X1 extends C1 {
-  @forMethod2
-  void publicMethodX1() {}
-
-  @B2(forSubexpression2)
-  void publicMethodX2() {}
-
-  @excludedOutline
-  void _privateMethodX2() {}
-}
-
-C2<int> y1;
-
-F1 y2;
-
-int y3 = publicFunction1(0);
diff --git a/pkg/front_end/testcases/shaker/transitive_annotations.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_annotations.dart.outline.expect
deleted file mode 100644
index 3e56148..0000000
--- a/pkg/front_end/testcases/shaker/transitive_annotations.dart.outline.expect
+++ /dev/null
@@ -1,56 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_annotations.dart
-library;
-import self as self;
-import "./transitive_annotations_lib.dart" as tra;
-import "dart:core" as core;
-
-class X1 extends tra::C1 {
-  synthetic constructor •() → void
-    : super tra::C1::•();
-  @tra::forMethod2
-  method publicMethodX1() → void;
-  @tra::B2::•(tra::forSubexpression2)
-  method publicMethodX2() → void;
-}
-static field tra::C2<core::int> y1;
-static field () → void y2;
-static field core::int y3;
-
------ external pkg/front_end/testcases/shaker/transitive_annotations_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-@self::forTypedef
-typedef F1 = () → void;
-class B1 extends core::Object {
-  const constructor •(dynamic _) → void
-    : super core::Object::•();
-}
-class B2 extends core::Object {
-  const constructor •(dynamic _) → void
-    : super core::Object::•();
-}
-class C1 extends core::Object {
-  @self::forClassField
-  field core::int publicField;
-  synthetic constructor •() → void
-    : super core::Object::•();
-  @self::forMethod1
-  method publicMethod1() → void;
-  @self::B1::•(self::forSubexpression1)
-  method publicMethod2() → void;
-}
-class C2<T extends core::Object> extends core::Object {
-  field self::C2::T field;
-}
-static const field dynamic forClassField = const core::Object::•();
-static const field dynamic forMethod1 = const core::Object::•();
-static const field dynamic forMethod2 = const core::Object::•();
-static const field dynamic forSubexpression1 = const core::Object::•();
-static const field dynamic forSubexpression2 = const core::Object::•();
-static const field dynamic forTypedef = const core::Object::•();
-
diff --git a/pkg/front_end/testcases/shaker/transitive_annotations.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_annotations.dart.shaker.expect
deleted file mode 100644
index 5a64fcd..0000000
--- a/pkg/front_end/testcases/shaker/transitive_annotations.dart.shaker.expect
+++ /dev/null
@@ -1,26 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_annotations_lib.dart:
-  - member excludedOutline
-  - member forClassField
-  - member forMethod1
-  - member forMethod2
-  - member forSubexpression1
-  - member forSubexpression2
-  - member forTopLevelFunction
-  - member forTypedef
-  - member publicFunction1
-  - typedef F1
-  - class B1
-    - (default constructor)
-  - class B2
-    - (default constructor)
-  - class C1
-    - publicField
-    - (default constructor)
-    - publicMethod1
-    - publicMethod2
-  - class C2
-    - field
diff --git a/pkg/front_end/testcases/shaker/transitive_annotations_lib.dart b/pkg/front_end/testcases/shaker/transitive_annotations_lib.dart
deleted file mode 100644
index b86e96f..0000000
--- a/pkg/front_end/testcases/shaker/transitive_annotations_lib.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-const excludedAlways = const Object();
-const excludedOutline = const Object();
-
-const forClassField = const Object();
-const forFormalParameter = const Object();
-const forMethod1 = const Object();
-const forMethod2 = const Object();
-const forSubexpression1 = const Object();
-const forSubexpression2 = const Object();
-const forTopLevelFunction = const Object();
-const forTypedef = const Object();
-const forTypeParameter = const Object();
-
-@forTopLevelFunction
-int publicFunction1(@forFormalParameter int p) => 0;
-
-@excludedAlways
-int publicFunction2(@excludedAlways int p) => 0;
-
-@excludedAlways
-int _privateFunction(@excludedAlways int p) => 0;
-
-@forTypedef
-typedef void F1();
-
-@excludedAlways
-typedef void F2();
-
-class B1 {
-  const B1(_);
-}
-
-class B2 {
-  const B2(_);
-}
-
-class B3 {
-  const B3(_);
-}
-
-class C1 {
-  @forClassField
-  int publicField;
-
-  @excludedAlways
-  int _privateField;
-
-  @forMethod1
-  void publicMethod1() {}
-
-  @B1(forSubexpression1)
-  void publicMethod2() {}
-
-  @excludedAlways
-  void _privateMethod() {}
-}
-
-class C2<@forTypeParameter T> {
-  T field;
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_class.dart b/pkg/front_end/testcases/shaker/transitive_class.dart
deleted file mode 100644
index bb54544..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_class_lib.dart';
-
-C c;
diff --git a/pkg/front_end/testcases/shaker/transitive_class.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_class.dart.outline.expect
deleted file mode 100644
index 436404e..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class.dart.outline.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_class.dart
-library;
-import self as self;
-import "./transitive_class_lib.dart" as tra;
-
-static field tra::C c;
-
------ external pkg/front_end/testcases/shaker/transitive_class_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A1 extends core::Object {
-}
-class A3 extends core::Object {
-}
-class A5 extends core::Object {
-}
-class B extends core::Object {
-  field self::A1 publicField;
-}
-class C extends core::Object {
-  field self::A3 publicField;
-  field self::B b;
-  method publicMethod(self::A5 a) → void;
-}
-
diff --git a/pkg/front_end/testcases/shaker/transitive_class.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_class.dart.shaker.expect
deleted file mode 100644
index b40d03a..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class.dart.shaker.expect
+++ /dev/null
@@ -1,14 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_class_lib.dart:
-  - class A1
-  - class A3
-  - class A5
-  - class B
-    - publicField
-  - class C
-    - publicField
-    - b
-    - publicMethod
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor.dart b/pkg/front_end/testcases/shaker/transitive_class_constructor.dart
deleted file mode 100644
index 0175873..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_class_constructor_lib.dart';
-
-class C extends B {
-  C();
-  C.named() : super.publicConstructor(null);
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_class_constructor.dart.outline.expect
deleted file mode 100644
index 64b89ee..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor.dart.outline.expect
+++ /dev/null
@@ -1,46 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_class_constructor.dart
-library;
-import self as self;
-import "./transitive_class_constructor_lib.dart" as tra;
-
-class C extends tra::B {
-  constructor •() → void
-    : super tra::B::•();
-  constructor named() → void
-    : super tra::B::publicConstructor(null);
-}
-
------ external pkg/front_end/testcases/shaker/transitive_class_constructor_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A1 extends core::Object {
-}
-class A3 extends core::Object {
-}
-class A4 extends core::Object {
-}
-class S1 extends core::Object {
-  constructor •() → void
-    : super core::Object::•();
-  constructor namedConstructor1() → void
-    : super core::Object::•();
-}
-class S2 extends self::S1 {
-  constructor •() → void
-    : super self::S1::•();
-  constructor namedConstructor1() → void
-    : super self::S1::namedConstructor1();
-}
-class B extends self::S2 {
-  field self::A1 publicField;
-  constructor •() → void
-    : super self::S2::•();
-  constructor publicConstructor(self::A3 a, [self::A4 b]) → void
-    : super self::S2::namedConstructor1();
-}
-
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_class_constructor.dart.shaker.expect
deleted file mode 100644
index ff151d8..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor.dart.shaker.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_class_constructor_lib.dart:
-  - class A1
-  - class A3
-  - class A4
-  - class S1
-    - (default constructor)
-    - namedConstructor1
-  - class S2
-    - (default constructor)
-    - namedConstructor1
-  - class B
-    - publicField
-    - (default constructor)
-    - publicConstructor
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor_lib.dart b/pkg/front_end/testcases/shaker/transitive_class_constructor_lib.dart
deleted file mode 100644
index 646a9e7..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor_lib.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A1 {}
-
-class A2 {}
-
-class A3 {}
-
-class A4 {}
-
-class A5 {}
-
-class A6 {}
-
-class S1 {
-  S1();
-  S1.namedConstructor1();
-  S1.namedConstructor2();
-}
-
-class S2 extends S1 {
-  S2();
-  S2.namedConstructor1() : super.namedConstructor1();
-  S2.namedConstructor2() : super.namedConstructor2();
-}
-
-class B extends S2 {
-  A1 publicField;
-  A2 _privateField;
-
-  B();
-  B.publicConstructor(A3 a, [A4 b]) : super.namedConstructor1();
-  B._privateConstructor(A5 a);
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart b/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart
deleted file mode 100644
index 677e7b6f..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_class_constructor_redirect_lib.dart';
-
-main() {
-  new A();
-  new A.aaa1();
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart.outline.expect
deleted file mode 100644
index 4c550e0..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart
-library;
-import self as self;
-
-static method main() → dynamic;
-
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart.shaker.expect
deleted file mode 100644
index 500fbaa..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect.dart.shaker.expect
+++ /dev/null
@@ -1,10 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_class_constructor_redirect_lib.dart:
-  - class A
-  - class B
-  - class C
-    - (default constructor)
-    - ccc1
diff --git a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect_lib.dart b/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect_lib.dart
deleted file mode 100644
index fda2552..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_constructor_redirect_lib.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {
-  factory A() = B;
-  factory A.aaa1() = B.bbb1;
-  factory A.aaa2() = B.bbb2;
-}
-
-class B implements A {
-  factory B() = C;
-  factory B.bbb1() = C.ccc1;
-  factory B.bbb2() = C.ccc2;
-}
-
-class C implements B {
-  C();
-  C.ccc1();
-  C.ccc2();
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_class_lib.dart b/pkg/front_end/testcases/shaker/transitive_class_lib.dart
deleted file mode 100644
index 496b4cd..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_lib.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A1 {}
-
-class A2 {}
-
-class A3 {}
-
-class A4 {}
-
-class A5 {}
-
-class A6 {}
-
-class A7 {}
-
-class A8 {}
-
-class A9 {}
-
-class B {
-  A1 publicField;
-  A2 _privateField;
-}
-
-class C {
-  A3 publicField;
-  A4 _privateField;
-  B b;
-
-  C();
-  C.namedConstructor();
-
-  void publicMethod(A5 a) {}
-  void _privateMethod(A6 a) {}
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart b/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart
deleted file mode 100644
index f0a0fe7..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_class_type_parameter_bound_lib.dart';
-
-B b;
diff --git a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart.outline.expect
deleted file mode 100644
index 00e4313..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart
-library;
-import self as self;
-import "./transitive_class_type_parameter_bound_lib.dart" as tra;
-
-static field tra::B<dynamic> b;
-
------ external pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field core::int field;
-}
-class B<T extends self::A> extends core::Object {
-  field core::int field;
-}
-
diff --git a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart.shaker.expect
deleted file mode 100644
index c72fdfb..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound.dart.shaker.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound_lib.dart:
-  - class A
-    - field
-  - class B
-    - field
diff --git a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound_lib.dart b/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound_lib.dart
deleted file mode 100644
index 9438956..0000000
--- a/pkg/front_end/testcases/shaker/transitive_class_type_parameter_bound_lib.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {
-  int field;
-}
-
-class B<T extends A> {
-  int field;
-}
-
-class C {
-  int field;
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_mixins.dart b/pkg/front_end/testcases/shaker/transitive_mixins.dart
deleted file mode 100644
index 43ee444..0000000
--- a/pkg/front_end/testcases/shaker/transitive_mixins.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_mixins_lib.dart';
-
-C v = null;
diff --git a/pkg/front_end/testcases/shaker/transitive_mixins.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_mixins.dart.outline.expect
deleted file mode 100644
index b823ddf..0000000
--- a/pkg/front_end/testcases/shaker/transitive_mixins.dart.outline.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_mixins.dart
-library;
-import self as self;
-import "./transitive_mixins_lib.dart" as tra;
-
-static field tra::C v;
-
------ external pkg/front_end/testcases/shaker/transitive_mixins_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-}
-class B extends core::Object {
-}
-abstract class _C&Object&A extends core::Object implements self::A {
-}
-class C extends self::_C&Object&A implements self::B {
-}
-
diff --git a/pkg/front_end/testcases/shaker/transitive_mixins.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_mixins.dart.shaker.expect
deleted file mode 100644
index b083426..0000000
--- a/pkg/front_end/testcases/shaker/transitive_mixins.dart.shaker.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_mixins_lib.dart:
-  - class A
-  - class B
-  - class _C&Object&A
-  - class C
diff --git a/pkg/front_end/testcases/shaker/transitive_mixins_lib.dart b/pkg/front_end/testcases/shaker/transitive_mixins_lib.dart
deleted file mode 100644
index d4c0191..0000000
--- a/pkg/front_end/testcases/shaker/transitive_mixins_lib.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A {}
-
-class B {}
-
-class C extends Object with A implements B {}
-
-class D {}
diff --git a/pkg/front_end/testcases/shaker/transitive_parameter_default.dart b/pkg/front_end/testcases/shaker/transitive_parameter_default.dart
deleted file mode 100644
index 21ecd17..0000000
--- a/pkg/front_end/testcases/shaker/transitive_parameter_default.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_parameter_default_lib.dart';
-
-main() {
-  new C1();
-  new C2();
-  topLevelFunction1(null);
-  topLevelFunction2(null);
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_parameter_default.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_parameter_default.dart.outline.expect
deleted file mode 100644
index 5d69368..0000000
--- a/pkg/front_end/testcases/shaker/transitive_parameter_default.dart.outline.expect
+++ /dev/null
@@ -1,9 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_parameter_default.dart
-library;
-import self as self;
-
-static method main() → dynamic;
-
diff --git a/pkg/front_end/testcases/shaker/transitive_parameter_default.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_parameter_default.dart.shaker.expect
deleted file mode 100644
index fb63e32..0000000
--- a/pkg/front_end/testcases/shaker/transitive_parameter_default.dart.shaker.expect
+++ /dev/null
@@ -1,11 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_parameter_default_lib.dart:
-  - member topLevelFunction1
-  - member topLevelFunction2
-  - class C1
-    - (default constructor)
-  - class C2
-    - (default constructor)
diff --git a/pkg/front_end/testcases/shaker/transitive_parameter_default_lib.dart b/pkg/front_end/testcases/shaker/transitive_parameter_default_lib.dart
deleted file mode 100644
index 3f303c1..0000000
--- a/pkg/front_end/testcases/shaker/transitive_parameter_default_lib.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_parameter_default_lib2.dart';
-
-topLevelFunction1(p1, [p2, p3 = const A1()]) {}
-
-topLevelFunction2(p1, {p2, p3: const A2()}) {}
-
-topLevelFunction3(p1, {p2, p3: const A3()}) {}
-
-class C1 {
-  C1([p = const A4()]);
-}
-
-class C2 {
-  C2({p: const A5()});
-}
-
-class C3 {
-  C3({p: const A6()});
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_parameter_default_lib2.dart b/pkg/front_end/testcases/shaker/transitive_parameter_default_lib2.dart
deleted file mode 100644
index 1453fe9..0000000
--- a/pkg/front_end/testcases/shaker/transitive_parameter_default_lib2.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class A1 {
-  const A1();
-}
-
-class A2 {
-  const A2();
-}
-
-class A3 {
-  const A3();
-}
-
-class A4 {
-  const A4();
-}
-
-class A5 {
-  const A5();
-}
-
-class A6 {
-  const A6();
-}
-
-class A7 {
-  const A7();
-}
diff --git a/pkg/front_end/testcases/shaker/transitive_superclass.dart b/pkg/front_end/testcases/shaker/transitive_superclass.dart
deleted file mode 100644
index c2e5d5d..0000000
--- a/pkg/front_end/testcases/shaker/transitive_superclass.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-import 'transitive_superclass_lib.dart';
-
-C c;
diff --git a/pkg/front_end/testcases/shaker/transitive_superclass.dart.outline.expect b/pkg/front_end/testcases/shaker/transitive_superclass.dart.outline.expect
deleted file mode 100644
index 7472eed..0000000
--- a/pkg/front_end/testcases/shaker/transitive_superclass.dart.outline.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
------ pkg/front_end/testcases/shaker/transitive_superclass.dart
-library;
-import self as self;
-import "./transitive_superclass_lib.dart" as tra;
-
-static field tra::C c;
-
------ external pkg/front_end/testcases/shaker/transitive_superclass_lib.dart
-library;
-import self as self;
-import "dart:core" as core;
-
-class _A extends core::Object {
-  field core::int field;
-}
-class B extends self::_A {
-  field core::int field;
-}
-class C extends self::B {
-  field core::int field;
-}
-
diff --git a/pkg/front_end/testcases/shaker/transitive_superclass.dart.shaker.expect b/pkg/front_end/testcases/shaker/transitive_superclass.dart.shaker.expect
deleted file mode 100644
index 10a4f5d..0000000
--- a/pkg/front_end/testcases/shaker/transitive_superclass.dart.shaker.expect
+++ /dev/null
@@ -1,11 +0,0 @@
-This file was autogenerated from running the shaker test suite.
-To update this file, either copy the output from a failing test or run
-pkg/front_end/tool/fasta testing shaker -DupdateExpectations=true
-
-library pkg/front_end/testcases/shaker/transitive_superclass_lib.dart:
-  - class _A
-    - field
-  - class B
-    - field
-  - class C
-    - field
diff --git a/pkg/front_end/testcases/shaker/transitive_superclass_lib.dart b/pkg/front_end/testcases/shaker/transitive_superclass_lib.dart
deleted file mode 100644
index 6b301b6..0000000
--- a/pkg/front_end/testcases/shaker/transitive_superclass_lib.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2017, 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.md file.
-
-class _A {
-  int field;
-}
-
-class B extends _A {
-  int field;
-}
-
-class C extends B {
-  int field;
-}
diff --git a/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect b/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect
index f5230259..cc2cd34 100644
--- a/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect
+++ b/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect
@@ -177,28 +177,28 @@
     self::use(let final core::int #t35 = 87 in let final core::int #t36 = 42 in let final void #t37 = super.{self::A::[]=}(#t35, #t36) in #t36);
     super.m = 42;
     self::use(super.m = 42);
-    super.{self::A::a}.==(null) ?{dynamic} super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t38 = super.{self::A::a} in #t38.==(null) ?{dynamic} super.{self::A::a} = 42 : #t38);
-    super.{self::B::b}.==(null) ?{dynamic} super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t39 = super.{self::B::b} in #t39.==(null) ?{dynamic} super.{self::A::b} = 42 : #t39);
-    super.{self::A::c}.==(null) ?{dynamic} super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t40 = super.{self::A::c} in #t40.==(null) ?{dynamic} super.{self::B::c} = 42 : #t40);
-    super.{self::B::d}.==(null) ?{dynamic} super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t41 = super.{self::B::d} in #t41.==(null) ?{dynamic} super.{self::A::d} = 42 : #t41);
-    super.{self::A::e}.==(null) ?{dynamic} super.e = 42 : null;
-    self::use(let final dynamic #t42 = super.{self::A::e} in #t42.==(null) ?{dynamic} super.e = 42 : #t42);
-    super.{self::A::f}.==(null) ?{dynamic} super.f = 42 : null;
-    self::use(let final dynamic #t43 = super.{self::A::f} in #t43.==(null) ?{dynamic} super.f = 42 : #t43);
-    super.g.==(null) ?{dynamic} super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t44 = super.g in #t44.==(null) ?{dynamic} super.{self::A::g} = 42 : #t44);
-    super.{self::A::h}.==(null) ?{dynamic} super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t45 = super.{self::A::h} in #t45.==(null) ?{dynamic} super.{self::A::h} = 42 : #t45);
-    super.{self::A::i}.==(null) ?{dynamic} super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t46 = super.{self::A::i} in #t46.==(null) ?{dynamic} super.{self::B::i} = 42 : #t46);
-    let final core::int #t47 = 87 in super.{self::A::[]}(#t47).==(null) ?{dynamic} let final core::int #t48 = 42 in let final void #t49 = super.{self::A::[]=}(#t47, #t48) in #t48 : null;
-    self::use(let final core::int #t50 = 87 in let final dynamic #t51 = super.{self::A::[]}(#t50) in #t51.==(null) ?{dynamic} let final core::int #t52 = 42 in let final void #t53 = super.{self::A::[]=}(#t50, #t52) in #t52 : #t51);
-    super.{self::A::m}.==(null) ?{core::Object} super.m = 42 : null;
-    self::use(let final () → void #t54 = super.{self::A::m} in #t54.==(null) ?{core::Object} super.m = 42 : #t54);
+    super.{self::A::a}.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : null;
+    self::use(let final dynamic #t38 = super.{self::A::a} in #t38.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t38);
+    super.{self::B::b}.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : null;
+    self::use(let final dynamic #t39 = super.{self::B::b} in #t39.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t39);
+    super.{self::A::c}.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : null;
+    self::use(let final dynamic #t40 = super.{self::A::c} in #t40.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t40);
+    super.{self::B::d}.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : null;
+    self::use(let final dynamic #t41 = super.{self::B::d} in #t41.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t41);
+    super.{self::A::e}.{core::Object::==}(null) ?{dynamic} super.e = 42 : null;
+    self::use(let final dynamic #t42 = super.{self::A::e} in #t42.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t42);
+    super.{self::A::f}.{core::Object::==}(null) ?{dynamic} super.f = 42 : null;
+    self::use(let final dynamic #t43 = super.{self::A::f} in #t43.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t43);
+    super.g.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : null;
+    self::use(let final dynamic #t44 = super.g in #t44.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t44);
+    super.{self::A::h}.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : null;
+    self::use(let final dynamic #t45 = super.{self::A::h} in #t45.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t45);
+    super.{self::A::i}.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : null;
+    self::use(let final dynamic #t46 = super.{self::A::i} in #t46.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t46);
+    let final core::int #t47 = 87 in super.{self::A::[]}(#t47).{core::Object::==}(null) ?{dynamic} let final core::int #t48 = 42 in let final void #t49 = super.{self::A::[]=}(#t47, #t48) in #t48 : null;
+    self::use(let final core::int #t50 = 87 in let final dynamic #t51 = super.{self::A::[]}(#t50) in #t51.{core::Object::==}(null) ?{dynamic} let final core::int #t52 = 42 in let final void #t53 = super.{self::A::[]=}(#t50, #t52) in #t52 : #t51);
+    super.{self::A::m}.{core::Object::==}(null) ?{core::Object} super.m = 42 : null;
+    self::use(let final () → void #t54 = super.{self::A::m} in #t54.{core::Object::==}(null) ?{core::Object} super.m = 42 : #t54);
     super.{self::A::a} = super.{self::A::a}.+(42);
     self::use(super.{self::A::a} = super.{self::A::a}.+(42));
     super.{self::A::b} = super.{self::B::b}.+(42);
@@ -363,7 +363,7 @@
     use(super.m(87));
               ^"]/* from null */;
 static method use(dynamic x) → dynamic {
-  if(x.==(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
+  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
     throw "Shouldn't happen";
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect
index 052b332..661a043 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.expect
@@ -17,6 +17,6 @@
   let final self::C #t3 = c in (let final dynamic #t4 = #t3 in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart:14:33: Error: The getter 'x' isn't defined for the class '#lib1::C'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'x'.
   c. /*@error=UndefinedGetter*/ x ??= 1;
-                                ^").==(null) ?{dynamic} #t3.{self::C::x} = 1 : null;
+                                ^").{core::Object::==}(null) ?{dynamic} #t3.{self::C::x} = 1 : null;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect
index bb3271b..956e97e 100644
--- a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.strong.transformed.expect
@@ -17,6 +17,6 @@
   let final self::C #t3 = c in (let final self::C #t4 = #t3 in let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart:14:33: Error: The getter 'x' isn't defined for the class '#lib1::C'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'x'.
   c. /*@error=UndefinedGetter*/ x ??= 1;
-                                ^").==(null) ?{dynamic} #t3.{self::C::x} = 1 : null;
+                                ^").{core::Object::==}(null) ?{dynamic} #t3.{self::C::x} = 1 : null;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index c283616..6c3add6 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -105,39 +105,6 @@
     },
 
     {
-      "name": "ast_builder",
-      "kind": "Chain",
-      "source": "test/fasta/ast_builder_test.dart",
-      "path": "testcases/",
-      "status": "testcases/ast_builder.status",
-      "pattern": [
-        "\\.dart$"
-      ],
-      "exclude": [
-        "/testcases/.*_part[0-9]*\\.dart$",
-        "/testcases/.*_lib[0-9]*\\.dart$",
-        "/testcases/dartino/",
-        "/testcases/shaker/"
-      ]
-    },
-
-    {
-      "name": "shaker",
-      "kind": "Chain",
-      "source": "test/fasta/shaker_test.dart",
-      "path": "testcases/shaker/",
-      "status": "testcases/shaker.status",
-      "pattern": [
-        "\\.dart$"
-      ],
-      "exclude": [
-        "/testcases/dartino/",
-        "/shaker/lib/.*\\.dart$",
-        "/shaker/.*_lib[0-9]*\\.dart$"
-      ]
-    },
-
-    {
       "name": "incremental",
       "kind": "Chain",
       "source": "test/fasta/incremental_test.dart",
@@ -330,6 +297,7 @@
 
     "uris": [
       "lib/",
+      "../analyzer/lib/src/generated/parser_fasta.dart",
       "tool/",
       "test/",
       "../kernel/lib/",
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index 52afecd..1b47a33 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.dart
@@ -114,7 +114,8 @@
     //
     // It's broken if it says something like this:
     //
-    //     ninja explain: expected depfile 'vm_platform.dill.d' to mention 'vm_platform.dill', got '/.../xcodebuild/ReleaseX64/vm_platform.dill'
+    //     ninja explain: expected depfile 'vm_platform.dill.d' to mention \
+    //     'vm_platform.dill', got '/.../xcodebuild/ReleaseX64/vm_platform.dill'
     return Uri.parse(relativizeUri(uri, base: Uri.base)).toFilePath();
   }
 
diff --git a/pkg/front_end/tool/_fasta/dump_partial.dart b/pkg/front_end/tool/_fasta/dump_partial.dart
index 610fdb7..9f8bef0 100644
--- a/pkg/front_end/tool/_fasta/dump_partial.dart
+++ b/pkg/front_end/tool/_fasta/dump_partial.dart
@@ -20,8 +20,9 @@
   writeComponentToText(component);
 }
 
-/// Creates a component that contains all of the context code marked as external,
-/// and all libraries defined in partial.dill as they are written in that file.
+/// Creates a component that contains all of the context code marked as
+/// external, and all libraries defined in partial.dill as they are written in
+/// that file.
 Component _loadComponent(List<String> args) {
   List<int> partialInput = new File(args[0]).readAsBytesSync();
 
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index 75a58f7..39cb453 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -212,7 +212,7 @@
 // Note: AstBuilder doesn't build compilation-units or classes, only method
 // bodies. So this listener is not feature complete.
 class _PartialAstBuilder extends AstBuilder {
-  _PartialAstBuilder(Uri uri) : super(null, null, null, null, true, uri);
+  _PartialAstBuilder(Uri uri) : super(null, null, true, uri);
 
   // Note: this method converts the body to kernel, so we skip that here.
   @override
diff --git a/pkg/js_ast/lib/src/template.dart b/pkg/js_ast/lib/src/template.dart
index 9c055db..c6a732a 100644
--- a/pkg/js_ast/lib/src/template.dart
+++ b/pkg/js_ast/lib/src/template.dart
@@ -486,7 +486,7 @@
       return new Switch(
           makeKey(arguments),
           makeCases
-              .map((Instantiator makeCase) => makeCase(arguments))
+              .map<SwitchClause>((Instantiator makeCase) => makeCase(arguments))
               .toList());
     };
   }
@@ -692,7 +692,8 @@
         node.elements.map(visit).toList(growable: false);
     return (arguments) {
       List<Expression> elements = elementMakers
-          .map((Instantiator instantiator) => instantiator(arguments))
+          .map<Expression>(
+              (Instantiator instantiator) => instantiator(arguments))
           .toList(growable: false);
       return new ArrayInitializer(elements);
     };
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index d94fb18..3159a05 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -903,6 +903,7 @@
 
 type InstanceConstant extends Constant {
   Byte tag = 7;
+  CanonicalNameReference class;
   List<DartType> typeArguments;
   List<[FieldReference, ConstantReference]> values;
 }
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index f7367b9..f55c28f 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -5620,6 +5620,7 @@
 
   void writeCanonicalNameReference(CanonicalName name);
   void writeStringReference(String str);
+  void writeName(Name node);
   void writeDartType(DartType type);
   void writeNode(Node node);
 
@@ -5646,6 +5647,7 @@
 
   CanonicalName readCanonicalNameReference();
   String readStringReference();
+  Name readName();
   DartType readDartType();
   FunctionNode readFunctionNode();
 
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 3a461aa1..91f5fd6 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -20,8 +20,16 @@
       <LabeledStatement, LabeledStatement>{};
   final Map<SwitchCase, SwitchCase> switchCases = <SwitchCase, SwitchCase>{};
   final Map<TypeParameter, DartType> typeSubstitution;
+  bool cloneAnnotations;
 
-  CloneVisitor({Map<TypeParameter, DartType> typeSubstitution})
+  /// Creates an instance of the cloning visitor for Kernel ASTs.
+  ///
+  /// The boolean value of [cloneAnnotations] tells if the annotations on the
+  /// outline elements in the source AST should be cloned to the target AST. The
+  /// annotations in procedure bodies are cloned unconditionally.
+  CloneVisitor(
+      {Map<TypeParameter, DartType> typeSubstitution,
+      this.cloneAnnotations = true})
       : this.typeSubstitution = ensureMutable(typeSubstitution);
 
   static Map<TypeParameter, DartType> ensureMutable(
@@ -395,6 +403,9 @@
     return variables[node] = new VariableDeclaration(node.name,
         initializer: cloneOptional(node.initializer),
         type: visitType(node.type))
+      ..annotations = cloneAnnotations && !node.annotations.isEmpty
+          ? node.annotations.map(clone).toList()
+          : const <Expression>[]
       ..flags = node.flags;
   }
 
@@ -413,6 +424,9 @@
         initializers: node.initializers.map(clone).toList(),
         transformerFlags: node.transformerFlags,
         fileUri: _activeFileUri)
+      ..annotations = cloneAnnotations && !node.annotations.isEmpty
+          ? node.annotations.map(clone).toList()
+          : const <Expression>[]
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset);
   }
@@ -423,6 +437,9 @@
         fileUri: _activeFileUri,
         forwardingStubSuperTarget: node.forwardingStubSuperTarget,
         forwardingStubInterfaceTarget: node.forwardingStubInterfaceTarget)
+      ..annotations = cloneAnnotations && !node.annotations.isEmpty
+          ? node.annotations.map(clone).toList()
+          : const <Expression>[]
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
       ..flags = node.flags;
@@ -440,6 +457,9 @@
         hasImplicitSetter: node.hasImplicitSetter,
         transformerFlags: node.transformerFlags,
         fileUri: _activeFileUri)
+      ..annotations = cloneAnnotations && !node.annotations.isEmpty
+          ? node.annotations.map(clone).toList()
+          : const <Expression>[]
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
       ..flags = node.flags;
@@ -456,7 +476,10 @@
         positionalParameters: node.positionalParameters.map(clone).toList(),
         namedParameters: node.namedParameters.map(clone).toList(),
         requiredParameterCount: node.requiredParameterCount,
-        fileUri: _activeFileUri);
+        fileUri: _activeFileUri)
+      ..annotations = cloneAnnotations && !node.annotations.isEmpty
+          ? node.annotations.map(clone).toList()
+          : const <Expression>[];
   }
 
   visitTypeParameter(TypeParameter node) {
@@ -466,10 +489,22 @@
     if (node.defaultType != null) {
       newNode.defaultType = visitType(node.defaultType);
     }
-    return newNode..flags = node.flags;
+    return newNode
+      ..annotations = cloneAnnotations && !node.annotations.isEmpty
+          ? node.annotations.map(clone).toList()
+          : const <Expression>[]
+      ..flags = node.flags;
   }
 
-  TreeNode cloneFunctionNodeBody(FunctionNode node) => cloneOptional(node.body);
+  TreeNode cloneFunctionNodeBody(FunctionNode node) {
+    bool savedCloneAnnotations = this.cloneAnnotations;
+    try {
+      this.cloneAnnotations = true;
+      return cloneOptional(node.body);
+    } finally {
+      this.cloneAnnotations = savedCloneAnnotations;
+    }
+  }
 
   visitFunctionNode(FunctionNode node) {
     var typeParameters = node.typeParameters.map(clone).toList();
@@ -584,8 +619,12 @@
 }
 
 class CloneWithoutBody extends CloneVisitor {
-  CloneWithoutBody({Map<TypeParameter, DartType> typeSubstitution})
-      : super(typeSubstitution: typeSubstitution);
+  CloneWithoutBody(
+      {Map<TypeParameter, DartType> typeSubstitution,
+      bool cloneAnnotations = true})
+      : super(
+            typeSubstitution: typeSubstitution,
+            cloneAnnotations: cloneAnnotations);
 
   @override
   TreeNode cloneFunctionNodeBody(FunctionNode node) => null;
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index e0fe377..de05b25 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -98,6 +98,10 @@
   /// The `dart:mirrors` library, or `null` if the component does not use it.
   Library _mirrorsLibrary;
 
+  Class _pragmaClass;
+  Field _pragmaName;
+  Field _pragmaOptions;
+
   CoreTypes(Component component)
       : index = new LibraryIndex.coreLibraries(component);
 
@@ -318,6 +322,18 @@
     return _objectEquals ??= index.getMember('dart:core', 'Object', '==');
   }
 
+  Class get pragmaClass {
+    return _pragmaClass ??= index.getClass('dart:core', 'pragma');
+  }
+
+  Field get pragmaName {
+    return _pragmaName ??= index.getMember('dart:core', 'pragma', 'name');
+  }
+
+  Field get pragmaOptions {
+    return _pragmaOptions ??= index.getMember('dart:core', 'pragma', 'options');
+  }
+
   Procedure get printProcedure {
     return _printProcedure ??= index.getTopLevelMember('dart:core', 'print');
   }
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index 05b814d..d3d2c0c 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -12,6 +12,17 @@
 
 import 'async.dart';
 
+class ContinuationVariables {
+  static const awaitJumpVar = ':await_jump_var';
+  static const awaitContextVar = ':await_ctx_var';
+  static const exceptionParam = ':exception';
+  static const stackTraceParam = ':stack_trace';
+
+  static String savedTryContextVar(int depth) => ':saved_try_context_var$depth';
+  static String exceptionVar(int depth) => ':exception$depth';
+  static String stackTraceVar(int depth) => ':stack_trace$depth';
+}
+
 void transformLibraries(
     CoreTypes coreTypes, List<Library> libraries, bool syncAsync) {
   var helper = new HelperNodes.fromCoreTypes(coreTypes);
@@ -42,10 +53,10 @@
   final bool syncAsync;
 
   final VariableDeclaration asyncJumpVariable = new VariableDeclaration(
-      ":await_jump_var",
+      ContinuationVariables.awaitJumpVar,
       initializer: new IntLiteral(0));
   final VariableDeclaration asyncContextVariable =
-      new VariableDeclaration(":await_ctx_var");
+      new VariableDeclaration(ContinuationVariables.awaitContextVar);
 
   RecursiveContinuationRewriter(this.helper, this.syncAsync);
 
@@ -154,13 +165,15 @@
   }
 
   Iterable<VariableDeclaration> createCapturedTryVariables() =>
-      new Iterable.generate(capturedTryDepth,
-          (depth) => new VariableDeclaration(":saved_try_context_var${depth}"));
+      new Iterable.generate(
+          capturedTryDepth,
+          (depth) => new VariableDeclaration(
+              ContinuationVariables.savedTryContextVar(depth)));
 
   Iterable<VariableDeclaration> createCapturedCatchVariables() =>
       new Iterable.generate(capturedCatchDepth).expand((depth) => [
-            new VariableDeclaration(":exception${depth}"),
-            new VariableDeclaration(":stack_trace${depth}"),
+            new VariableDeclaration(ContinuationVariables.exceptionVar(depth)),
+            new VariableDeclaration(ContinuationVariables.stackTraceVar(depth)),
           ]);
 
   List<VariableDeclaration> variableDeclarations() =>
@@ -293,8 +306,8 @@
     // }
     final parameters = <VariableDeclaration>[
       expressionRewriter.asyncResult,
-      new VariableDeclaration(':exception'),
-      new VariableDeclaration(':stack_trace'),
+      new VariableDeclaration(ContinuationVariables.exceptionParam),
+      new VariableDeclaration(ContinuationVariables.stackTraceParam),
     ];
 
     // Note: SyncYielding functions have no Dart equivalent. Since they are
diff --git a/pkg/kernel/lib/transformations/treeshaker.dart b/pkg/kernel/lib/transformations/treeshaker.dart
index d615439..f708bd9 100644
--- a/pkg/kernel/lib/transformations/treeshaker.dart
+++ b/pkg/kernel/lib/transformations/treeshaker.dart
@@ -1265,6 +1265,16 @@
           assert(annotation.arguments.positional.length == 1);
           return (annotation.arguments.positional[0] as StringLiteral).value;
         }
+      } else if (annotation is ConstantExpression) {
+        final constant = annotation.constant;
+        if (constant is InstanceConstant) {
+          final Class klass = constant.klass;
+          if (klass.name == 'ExternalName' &&
+              klass.enclosingLibrary.importUri.toString() == 'dart:_internal') {
+            assert(constant.fieldValues.length == 1);
+            return (constant.fieldValues.values.single as StringConstant).value;
+          }
+        }
       }
     }
   }
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index db043a8..db64098 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@
 name: kernel
 # Currently, kernel API is not stable and users should
 # not depend on semver semantics when depending on this package.
-version: 0.3.1-alpha.0
+version: 0.3.1
 author: Dart Team <misc@dartlang.org>
 description: Dart IR (Intermediate Representation)
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
@@ -14,7 +14,7 @@
   package_config: ^1.0.0
 dev_dependencies:
   analyzer: '>=0.31.0 <0.33.0'
-  front_end: 0.1.1-alpha.0
+  front_end: 0.1.1
   test: ^0.12.15+6
   stack_trace: ^1.6.6
   ansicolor: ^0.0.9
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 70fb077..ded000c 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -196,11 +196,6 @@
 [ $compiler == dart2js && $csp ]
 mutation_observer: Skip # This test cannot run under CSP because it is injecting a JavaScript polyfill
 
-[ $compiler == dart2js && $fasta && $host_checked ]
-analysis_server_client/test/analysis_server_client_test: Crash
-js_ast/test/printer_callback_test: Crash
-js_ast/test/string_escape_test: Crash
-
 [ $compiler == dart2js && ($runtime == chrome || $runtime == ff) ]
 async/test/stream_zip_test: SkipSlow # Times out. Issue 22050
 collection/test/unmodifiable_collection_test: SkipSlow # Times out. Issue 22050
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index 287ed0a..a6fdf12 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -57,18 +57,19 @@
   List<StringReference> names;
 }
 
-type ConstantICData extends ConstantPoolEntry {
-  Byte tag = 7;
-  StringReference targetName;
-  ConstantIndex argDesc;
-}
-
 enum InvocationKind {
   method, // x.foo(...) or foo(...)
   getter, // x.foo
   setter  // x.foo = ...
 }
 
+type ConstantICData extends ConstantPoolEntry {
+  Byte tag = 7;
+  Byte invocationKind; // Index in InvocationKind enum.
+  Name targetName;
+  ConstantIndex argDesc;
+}
+
 type ConstantStaticICData extends ConstantPoolEntry {
   Byte tag = 8;
   Byte invocationKind; // Index in InvocationKind enum.
@@ -442,28 +443,46 @@
       listEquals(this.argNames, other.argNames);
 }
 
+enum InvocationKind { method, getter, setter }
+
+String _invocationKindToString(InvocationKind kind) {
+  switch (kind) {
+    case InvocationKind.method:
+      return '';
+    case InvocationKind.getter:
+      return 'get ';
+    case InvocationKind.setter:
+      return 'set ';
+  }
+  throw 'Unexpected InvocationKind $kind';
+}
+
 class ConstantICData extends ConstantPoolEntry {
-  final String targetName;
+  final InvocationKind invocationKind;
+  final Name targetName;
   final int argDescConstantIndex;
 
-  ConstantICData(this.targetName, this.argDescConstantIndex);
+  ConstantICData(
+      this.invocationKind, this.targetName, this.argDescConstantIndex);
 
   @override
   ConstantTag get tag => ConstantTag.kICData;
 
   @override
   void writeValueToBinary(BinarySink sink) {
-    sink.writeStringReference(targetName);
+    sink.writeByte(invocationKind.index);
+    sink.writeName(targetName);
     sink.writeUInt30(argDescConstantIndex);
   }
 
   ConstantICData.readFromBinary(BinarySource source)
-      : targetName = source.readStringReference(),
+      : invocationKind = InvocationKind.values[source.readByte()],
+        targetName = source.readName(),
         argDescConstantIndex = source.readUInt();
 
   @override
-  String toString() =>
-      'ICData target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
+  String toString() => 'ICData ${_invocationKindToString(invocationKind)}'
+      'target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
 
   // ConstantICData entries are created per call site and should not be merged,
   // so ConstantICData class uses identity [hashCode] and [operator ==].
@@ -475,8 +494,6 @@
   bool operator ==(other) => identical(this, other);
 }
 
-enum InvocationKind { method, getter, setter }
-
 class ConstantStaticICData extends ConstantPoolEntry {
   final InvocationKind invocationKind;
   final Reference _reference;
@@ -508,11 +525,7 @@
         argDescConstantIndex = source.readUInt();
 
   @override
-  String toString() =>
-      'StaticICData ' +
-      (invocationKind == InvocationKind.getter
-          ? 'get '
-          : (invocationKind == InvocationKind.setter ? 'set ' : '')) +
+  String toString() => 'StaticICData ${_invocationKindToString(invocationKind)}'
       'target \'$target\', arg-desc CP#$argDescConstantIndex';
 
   // ConstantStaticICData entries are created per call site and should not be
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 6f48e18..53a6975 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -644,14 +644,6 @@
 // Should match constant in runtime/vm/stack_frame_dbc.h.
 const int kParamEndSlotFromFp = 4;
 
-// Prefix used to distinguish getters in ICData target names.
-// Should match constant in runtime/vm/object.cc.
-const String kGetterPrefix = 'get:';
-
-// Prefix used to distinguish setters in ICData target names.
-// Should match constant in runtime/vm/object.cc.
-const String kSetterPrefix = 'set:';
-
 enum SpecialIndex {
   exception,
   stackTrace,
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 0bfd866..51f5fdc 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -63,6 +63,7 @@
   Map<SwitchCase, Label> switchCases;
   Map<TryCatch, TryBlock> tryCatches;
   Map<TryFinally, List<FinallyBlock>> finallyBlocks;
+  List<Label> yieldPoints;
   Map<TreeNode, int> contextLevels;
   List<ClosureBytecode> closures;
   ConstantPool cp;
@@ -97,7 +98,7 @@
 
   @override
   defaultMember(Member node) {
-    if (node.isAbstract) {
+    if (node.isAbstract || node.isExternal) {
       return;
     }
     try {
@@ -155,6 +156,14 @@
   Class get closureClass =>
       _closureClass ??= libraryIndex.getClass('dart:core', '_Closure');
 
+  Procedure _objectInstanceOf;
+  Procedure get objectInstanceOf => _objectInstanceOf ??=
+      libraryIndex.getMember('dart:core', 'Object', '_instanceOf');
+
+  Procedure _objectAs;
+  Procedure get objectAs =>
+      _objectAs ??= libraryIndex.getMember('dart:core', 'Object', '_as');
+
   Field _closureInstantiatorTypeArguments;
   Field get closureInstantiatorTypeArguments =>
       _closureInstantiatorTypeArguments ??= libraryIndex.getMember(
@@ -318,9 +327,10 @@
     }
   }
 
-  void _genPushContextForVariable(VariableDeclaration variable) {
-    int depth =
-        locals.currentContextLevel - locals.getContextLevelOfVar(variable);
+  void _genPushContextForVariable(VariableDeclaration variable,
+      {int currentContextLevel}) {
+    currentContextLevel ??= locals.currentContextLevel;
+    int depth = currentContextLevel - locals.getContextLevelOfVar(variable);
     assert(depth >= 0);
 
     asm.emitPush(locals.contextVarIndexInFrame);
@@ -338,9 +348,9 @@
     }
   }
 
-  void _genLoadVar(VariableDeclaration v) {
+  void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
     if (locals.isCaptured(v)) {
-      _genPushContextForVariable(v);
+      _genPushContextForVariable(v, currentContextLevel: currentContextLevel);
       final int cpIndex = cp.add(
           new ConstantContextOffset.variable(locals.getVarIndexInContext(v)));
       asm.emitLoadFieldTOS(cpIndex);
@@ -422,7 +432,8 @@
     }
     asm.emitPushConstant(cp.add(new ConstantType(type)));
     final argDescIndex = cp.add(new ConstantArgDesc(4));
-    final icdataIndex = cp.add(new ConstantICData('_instanceOf', argDescIndex));
+    final icdataIndex = cp.add(new ConstantICData(
+        InvocationKind.method, objectInstanceOf.name, argDescIndex));
     asm.emitInstanceCall1(4, icdataIndex);
   }
 
@@ -438,6 +449,7 @@
     switchCases = <SwitchCase, Label>{};
     tryCatches = <TryCatch, TryBlock>{};
     finallyBlocks = <TryFinally, List<FinallyBlock>>{};
+    yieldPoints = null; // Initialized when entering sync-yielding closure.
     contextLevels = <TreeNode, int>{};
     closures = <ClosureBytecode>[];
     cp = new ConstantPool();
@@ -446,9 +458,10 @@
     savedAssemblers = <BytecodeAssembler>[];
 
     locals.enterScope(node);
+    assert(!locals.isSyncYieldingFrame);
 
     _genPrologue(node, node.function);
-
+    _setupInitialContext(node.function);
     _genEqualsOperatorNullHandling(node);
   }
 
@@ -489,6 +502,7 @@
     switchCases = null;
     tryCatches = null;
     finallyBlocks = null;
+    yieldPoints = null;
     contextLevels = null;
     closures = null;
     cp = null;
@@ -540,6 +554,27 @@
       asm.emitPopLocal(locals.contextVarIndexInFrame);
     }
 
+    if (locals.hasTypeArgsVar && isClosure) {
+      if (function.typeParameters.isNotEmpty) {
+        final int numParentTypeArgs = locals.numParentTypeArguments;
+        asm.emitPush(locals.typeArgsVarIndexInFrame);
+        asm.emitPush(locals.closureVarIndexInFrame);
+        asm.emitLoadFieldTOS(
+            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
+        _genPushInt(numParentTypeArgs);
+        _genPushInt(numParentTypeArgs + function.typeParameters.length);
+        _genStaticCall(prependTypeArguments, new ConstantArgDesc(4), 4);
+        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
+      } else {
+        asm.emitPush(locals.closureVarIndexInFrame);
+        asm.emitLoadFieldTOS(
+            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
+        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
+      }
+    }
+  }
+
+  void _setupInitialContext(FunctionNode function) {
     _allocateContextIfNeeded();
 
     if (locals.hasCapturedParameters) {
@@ -550,26 +585,6 @@
       function.positionalParameters.forEach(_copyParamIfCaptured);
       function.namedParameters.forEach(_copyParamIfCaptured);
     }
-
-    if (locals.hasTypeArgsVar && isClosure) {
-      if (function.typeParameters.isNotEmpty) {
-        final int numParentTypeArgs = locals.numParentTypeArguments;
-        asm.emitPush(locals.typeArgsVarIndexInFrame);
-        asm.emitPush(locals.closureVarIndexInFrame);
-        asm.emitLoadFieldTOS(
-            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
-        asm.emitPushConstant(cp.add(new ConstantInt(numParentTypeArgs)));
-        asm.emitPushConstant(cp.add(new ConstantInt(
-            numParentTypeArgs + function.typeParameters.length)));
-        _genStaticCall(prependTypeArguments, new ConstantArgDesc(4), 4);
-        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
-      } else {
-        asm.emitPush(locals.closureVarIndexInFrame);
-        asm.emitLoadFieldTOS(
-            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
-        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
-      }
-    }
   }
 
   void _copyParamIfCaptured(VariableDeclaration variable) {
@@ -595,28 +610,94 @@
     _pushAssemblerState();
 
     locals.enterScope(node);
+    List<Label> savedYieldPoints = yieldPoints;
+    yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;
 
     final int closureFunctionIndex = cp.add(new ConstantClosureFunction(
         name, new CloneWithoutBody().visitFunctionNode(function)));
 
     _genPrologue(node, function);
+
+    Label continuationSwitchLabel;
+    int continuationSwitchVar;
+    if (locals.isSyncYieldingFrame) {
+      continuationSwitchLabel = new Label();
+      continuationSwitchVar = locals.scratchVarIndexInFrame;
+      _genSyncYieldingPrologue(
+          function, continuationSwitchLabel, continuationSwitchVar);
+    }
+
+    _setupInitialContext(function);
+
+    // TODO(alexmarkov): support --causal_async_stacks.
+
     function.body.accept(this);
 
     // TODO(alexmarkov): figure out when 'return null' should be generated.
     _genPushNull();
     _genReturnTOS();
 
+    if (locals.isSyncYieldingFrame) {
+      _genSyncYieldingEpilogue(
+          function, continuationSwitchLabel, continuationSwitchVar);
+    }
+
     cp.add(new ConstantEndClosureFunctionScope());
 
     locals.leaveScope();
 
     closures.add(new ClosureBytecode(
         closureFunctionIndex, asm.bytecode, asm.exceptionsTable));
+
     _popAssemblerState();
+    yieldPoints = savedYieldPoints;
 
     return closureFunctionIndex;
   }
 
+  void _genSyncYieldingPrologue(FunctionNode function, Label continuationLabel,
+      int switchVarIndexInFrame) {
+    // switch_var = :await_jump_var
+    _genLoadVar(locals.awaitJumpVar);
+    asm.emitStoreLocal(switchVarIndexInFrame);
+
+    // if (switch_var != 0) goto continuationLabel
+    _genPushInt(0);
+    asm.emitIfNeStrictNumTOS();
+    asm.emitJump(continuationLabel);
+
+    // Proceed to normal entry.
+  }
+
+  void _genSyncYieldingEpilogue(FunctionNode function, Label continuationLabel,
+      int switchVarIndexInFrame) {
+    asm.bind(continuationLabel);
+
+    if (yieldPoints.isEmpty) {
+      asm.emitTrap();
+      return;
+    }
+
+    // context = :await_ctx_var
+    _genLoadVar(locals.awaitContextVar);
+    asm.emitPopLocal(locals.contextVarIndexInFrame);
+
+    for (int i = 0; i < yieldPoints.length; i++) {
+      // 0 is reserved for normal entry, yield points are counted from 1.
+      final int index = i + 1;
+
+      // if (switch_var == #index) goto yieldPoints[i]
+      // There is no need to test switch_var for the last yield statement.
+      if (i != yieldPoints.length - 1) {
+        asm.emitPush(switchVarIndexInFrame);
+        _genPushInt(index);
+        asm.emitIfEqStrictNumTOS();
+      }
+
+      asm.emitJump(yieldPoints[i]);
+    }
+  }
+
   void _genAllocateClosureInstance(
       TreeNode node, int closureFunctionIndex, FunctionNode function) {
     // TODO(alexmarkov): Consider adding a bytecode to allocate closure.
@@ -770,7 +851,8 @@
     final typeIndex = cp.add(new ConstantType(node.type));
     asm.emitPushConstant(typeIndex);
     final argDescIndex = cp.add(new ConstantArgDesc(4));
-    final icdataIndex = cp.add(new ConstantICData('_as', argDescIndex));
+    final icdataIndex = cp.add(
+        new ConstantICData(InvocationKind.method, objectAs.name, argDescIndex));
     asm.emitInstanceCall1(4, icdataIndex);
   }
 
@@ -1000,8 +1082,8 @@
     // TODO(alexmarkov): fast path smi ops
     final argDescIndex =
         cp.add(new ConstantArgDesc.fromArguments(args, hasReceiver: true));
-    final icdataIndex =
-        cp.add(new ConstantICData(node.name.name, argDescIndex));
+    final icdataIndex = cp.add(
+        new ConstantICData(InvocationKind.method, node.name, argDescIndex));
     // TODO(alexmarkov): figure out when generate InstanceCall2 (2 checked arguments).
     asm.emitInstanceCall1(
         args.positional.length + args.named.length + 1, icdataIndex);
@@ -1012,7 +1094,7 @@
     node.receiver.accept(this);
     final argDescIndex = cp.add(new ConstantArgDesc(1));
     final icdataIndex = cp.add(
-        new ConstantICData('$kGetterPrefix${node.name.name}', argDescIndex));
+        new ConstantICData(InvocationKind.getter, node.name, argDescIndex));
     asm.emitInstanceCall1(1, icdataIndex);
   }
 
@@ -1024,7 +1106,7 @@
     asm.emitStoreLocal(temp);
     final argDescIndex = cp.add(new ConstantArgDesc(2));
     final icdataIndex = cp.add(
-        new ConstantICData('$kSetterPrefix${node.name.name}', argDescIndex));
+        new ConstantICData(InvocationKind.setter, node.name, argDescIndex));
     asm.emitInstanceCall1(2, icdataIndex);
     asm.emitDrop1();
     asm.emitPush(temp);
@@ -1356,21 +1438,36 @@
 
     asm.emitInstanceCall1(
         1,
-        cp.add(new ConstantICData(
-            '$kGetterPrefix$kIterator', cp.add(new ConstantArgDesc(1)))));
+        cp.add(new ConstantICData(InvocationKind.getter, new Name(kIterator),
+            cp.add(new ConstantArgDesc(1)))));
 
     final iteratorTemp = locals.tempIndexInFrame(node);
     asm.emitPopLocal(iteratorTemp);
 
+    final capturedIteratorVar = locals.capturedIteratorVar(node);
+    if (capturedIteratorVar != null) {
+      _genPushContextForVariable(capturedIteratorVar);
+      asm.emitPush(iteratorTemp);
+      _genStoreVar(capturedIteratorVar);
+    }
+
     final Label done = new Label();
     final Label join = new Label();
 
     asm.bind(join);
     asm.emitCheckStack();
 
-    asm.emitPush(iteratorTemp);
-    asm.emitInstanceCall1(1,
-        cp.add(new ConstantICData(kMoveNext, cp.add(new ConstantArgDesc(1)))));
+    if (capturedIteratorVar != null) {
+      _genLoadVar(capturedIteratorVar);
+      asm.emitStoreLocal(iteratorTemp);
+    } else {
+      asm.emitPush(iteratorTemp);
+    }
+
+    asm.emitInstanceCall1(
+        1,
+        cp.add(new ConstantICData(InvocationKind.method, new Name(kMoveNext),
+            cp.add(new ConstantArgDesc(1)))));
     _genJumpIfFalse(/* negated = */ false, done);
 
     _enterScope(node);
@@ -1380,8 +1477,8 @@
     asm.emitPush(iteratorTemp);
     asm.emitInstanceCall1(
         1,
-        cp.add(new ConstantICData(
-            '$kGetterPrefix$kCurrent', cp.add(new ConstantArgDesc(1)))));
+        cp.add(new ConstantICData(InvocationKind.getter, new Name(kCurrent),
+            cp.add(new ConstantArgDesc(1)))));
 
     _genStoreVar(node.variable);
 
@@ -1509,7 +1606,9 @@
           asm.emitPush(temp);
           _genPushConstExpr(expr);
           asm.emitInstanceCall2(
-              2, cp.add(new ConstantICData('==', equalsArgDesc)));
+              2,
+              cp.add(new ConstantICData(
+                  InvocationKind.method, new Name('=='), equalsArgDesc)));
           _genJumpIfTrue(/* negated = */ false, caseLabel);
         }
       }
@@ -1537,6 +1636,7 @@
 
   int _savedContextVar(TreeNode node) {
     assert(_isTryBlock(node));
+    assert(locals.capturedSavedContextVar(node) == null);
     return locals.tempIndexInFrame(node, tempIndex: 0);
   }
 
@@ -1553,17 +1653,41 @@
   }
 
   _saveContextForTryBlock(TreeNode node) {
-    if (locals.hasContextVar) {
+    if (!locals.hasContextVar) {
+      return;
+    }
+    final capturedSavedContextVar = locals.capturedSavedContextVar(node);
+    if (capturedSavedContextVar != null) {
+      assert(locals.isSyncYieldingFrame);
+      _genPushContextForVariable(capturedSavedContextVar);
+      asm.emitPush(locals.contextVarIndexInFrame);
+      _genStoreVar(capturedSavedContextVar);
+    } else {
       asm.emitPush(locals.contextVarIndexInFrame);
       asm.emitPopLocal(_savedContextVar(node));
     }
   }
 
   _restoreContextForTryBlock(TreeNode node) {
-    if (locals.hasContextVar) {
-      asm.emitPush(_savedContextVar(node));
-      asm.emitPopLocal(locals.contextVarIndexInFrame);
+    if (!locals.hasContextVar) {
+      return;
     }
+    final capturedSavedContextVar = locals.capturedSavedContextVar(node);
+    if (capturedSavedContextVar != null) {
+      // 1. Restore context from closure var.
+      // This context has a context level at frame entry.
+      asm.emitPush(locals.closureVarIndexInFrame);
+      asm.emitLoadFieldTOS(cp.add(new ConstantFieldOffset(closureContext)));
+      asm.emitPopLocal(locals.contextVarIndexInFrame);
+
+      // 2. Restore context from captured :saved_try_context_var${depth}.
+      assert(locals.isCaptured(capturedSavedContextVar));
+      _genLoadVar(capturedSavedContextVar,
+          currentContextLevel: locals.contextLevelAtEntry);
+    } else {
+      asm.emitPush(_savedContextVar(node));
+    }
+    asm.emitPopLocal(locals.contextVarIndexInFrame);
   }
 
   /// Start try block
@@ -1587,11 +1711,39 @@
 
     asm.emitMoveSpecial(_exceptionVar(node), SpecialIndex.exception);
     asm.emitMoveSpecial(_stackTraceVar(node), SpecialIndex.stackTrace);
+
+    final capturedExceptionVar = locals.capturedExceptionVar(node);
+    if (capturedExceptionVar != null) {
+      _genPushContextForVariable(capturedExceptionVar);
+      asm.emitPush(_exceptionVar(node));
+      _genStoreVar(capturedExceptionVar);
+    }
+
+    final capturedStackTraceVar = locals.capturedStackTraceVar(node);
+    if (capturedStackTraceVar != null) {
+      _genPushContextForVariable(capturedStackTraceVar);
+      asm.emitPush(_stackTraceVar(node));
+      _genStoreVar(capturedStackTraceVar);
+    }
   }
 
   void _genRethrow(TreeNode node) {
-    asm.emitPush(_exceptionVar(node));
-    asm.emitPush(_stackTraceVar(node));
+    final capturedExceptionVar = locals.capturedExceptionVar(node);
+    if (capturedExceptionVar != null) {
+      assert(locals.isCaptured(capturedExceptionVar));
+      _genLoadVar(capturedExceptionVar);
+    } else {
+      asm.emitPush(_exceptionVar(node));
+    }
+
+    final capturedStackTraceVar = locals.capturedStackTraceVar(node);
+    if (capturedStackTraceVar != null) {
+      assert(locals.isCaptured(capturedStackTraceVar));
+      _genLoadVar(capturedStackTraceVar);
+    } else {
+      asm.emitPush(_stackTraceVar(node));
+    }
+
     asm.emitThrow(1);
   }
 
@@ -1737,9 +1889,53 @@
     asm.bind(done);
   }
 
-//  @override
-//  visitYieldStatement(YieldStatement node) {
-//  }
+  @override
+  visitYieldStatement(YieldStatement node) {
+    if (!node.isNative) {
+      throw 'YieldStatement must be desugared: $node';
+    }
+
+    // 0 is reserved for normal entry, yield points are counted from 1.
+    final int yieldIndex = yieldPoints.length + 1;
+    final Label continuationLabel = new Label();
+    yieldPoints.add(continuationLabel);
+
+    // :await_jump_var = #index
+    assert(locals.isCaptured(locals.awaitJumpVar));
+    _genPushContextForVariable(locals.awaitJumpVar);
+    _genPushInt(yieldIndex);
+    _genStoreVar(locals.awaitJumpVar);
+
+    // :await_ctx_var = context
+    assert(locals.isCaptured(locals.awaitContextVar));
+    _genPushContextForVariable(locals.awaitContextVar);
+    asm.emitPush(locals.contextVarIndexInFrame);
+    _genStoreVar(locals.awaitContextVar);
+
+    // return <expression>
+    // Note: finally blocks are *not* executed on the way out.
+    node.expression.accept(this);
+    asm.emitReturnTOS();
+
+    asm.bind(continuationLabel);
+
+    if (enclosingMember.function.dartAsyncMarker == AsyncMarker.Async ||
+        enclosingMember.function.dartAsyncMarker == AsyncMarker.AsyncStar) {
+      final int exceptionParam = locals.asyncExceptionParamIndexInFrame;
+      final int stackTraceParam = locals.asyncStackTraceParamIndexInFrame;
+
+      // if (:exception != null) rethrow (:exception, :stack_trace)
+      final Label cont = new Label();
+      asm.emitIfEqNull(exceptionParam);
+      asm.emitJump(cont);
+
+      asm.emitPush(exceptionParam);
+      asm.emitPush(stackTraceParam);
+      asm.emitThrow(1);
+
+      asm.bind(cont);
+    }
+  }
 
   @override
   visitFieldInitializer(FieldInitializer node) {
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 1bae25a..14ed800 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -7,6 +7,8 @@
 import 'dart:math' show max;
 
 import 'package:kernel/ast.dart';
+import 'package:kernel/transformations/continuation.dart'
+    show ContinuationVariables;
 import 'package:vm/bytecode/dbc.dart';
 
 class LocalVariables {
@@ -14,6 +16,14 @@
   final Map<VariableDeclaration, VarDesc> _vars =
       <VariableDeclaration, VarDesc>{};
   final Map<TreeNode, List<int>> _temps = <TreeNode, List<int>>{};
+  final Map<TreeNode, VariableDeclaration> _capturedSavedContextVars =
+      <TreeNode, VariableDeclaration>{};
+  final Map<TreeNode, VariableDeclaration> _capturedExceptionVars =
+      <TreeNode, VariableDeclaration>{};
+  final Map<TreeNode, VariableDeclaration> _capturedStackTraceVars =
+      <TreeNode, VariableDeclaration>{};
+  final Map<ForInStatement, VariableDeclaration> _capturedIteratorVars =
+      <ForInStatement, VariableDeclaration>{};
 
   Scope _currentScope;
   Frame _currentFrame;
@@ -54,6 +64,10 @@
   int get currentContextSize => _currentScope.contextSize;
   int get currentContextLevel => _currentScope.contextLevel;
 
+  int get contextLevelAtEntry =>
+      _currentFrame.contextLevelAtEntry ??
+      (throw "Current frame is top level and it doesn't have a context at entry");
+
   int getContextLevelOfVar(VariableDeclaration variable) {
     final v = _getVarDesc(variable);
     assert(v.isCaptured);
@@ -86,6 +100,45 @@
 
   bool get hasReceiver => _currentFrame.receiverVar != null;
 
+  bool get isSyncYieldingFrame => _currentFrame.isSyncYielding;
+
+  VariableDeclaration get awaitJumpVar {
+    assert(_currentFrame.isSyncYielding);
+    return _currentFrame.parent
+        .getSyntheticVar(ContinuationVariables.awaitJumpVar);
+  }
+
+  VariableDeclaration get awaitContextVar {
+    assert(_currentFrame.isSyncYielding);
+    return _currentFrame.parent
+        .getSyntheticVar(ContinuationVariables.awaitContextVar);
+  }
+
+  VariableDeclaration capturedSavedContextVar(TreeNode node) =>
+      _capturedSavedContextVars[node];
+  VariableDeclaration capturedExceptionVar(TreeNode node) =>
+      _capturedExceptionVars[node];
+  VariableDeclaration capturedStackTraceVar(TreeNode node) =>
+      _capturedStackTraceVars[node];
+  VariableDeclaration capturedIteratorVar(ForInStatement node) =>
+      _capturedIteratorVars[node];
+
+  int get asyncExceptionParamIndexInFrame {
+    assert(_currentFrame.isSyncYielding);
+    final function = (_currentFrame.function as FunctionDeclaration).function;
+    final param = function.positionalParameters
+        .firstWhere((p) => p.name == ContinuationVariables.exceptionParam);
+    return getVarIndexInFrame(param);
+  }
+
+  int get asyncStackTraceParamIndexInFrame {
+    assert(_currentFrame.isSyncYielding);
+    final function = (_currentFrame.function as FunctionDeclaration).function;
+    final param = function.positionalParameters
+        .firstWhere((p) => p.name == ContinuationVariables.stackTraceParam);
+    return getVarIndexInFrame(param);
+  }
+
   int get frameSize => _currentFrame.frameSize;
 
   int get numParameters => _currentFrame.numParameters;
@@ -121,7 +174,9 @@
   int index;
   int originalParamSlotIndex;
 
-  VarDesc(this.declaration, this.scope);
+  VarDesc(this.declaration, this.scope) {
+    scope.vars.add(this);
+  }
 
   Frame get frame => scope.frame;
 
@@ -146,20 +201,29 @@
   bool hasOptionalParameters = false;
   bool hasCapturedParameters = false;
   bool hasClosures = false;
+  bool isDartSync = true;
+  bool isSyncYielding = false;
   VariableDeclaration receiverVar;
   VariableDeclaration typeArgsVar;
   VariableDeclaration closureVar;
   VariableDeclaration contextVar;
   VariableDeclaration scratchVar;
+  Map<String, VariableDeclaration> syntheticVars;
   int frameSize = 0;
   List<int> temporaries = <int>[];
+  int contextLevelAtEntry;
 
   Frame(this.function, this.parent);
+
+  VariableDeclaration getSyntheticVar(String name) =>
+      syntheticVars[name] ??
+      (throw '${name} variable is not declared in ${function}');
 }
 
 class Scope {
   final Scope parent;
   final Frame frame;
+  final List<VarDesc> vars = <VarDesc>[];
 
   int localsUsed;
   int tempsUsed;
@@ -176,6 +240,8 @@
 
   Scope _currentScope;
   Frame _currentFrame;
+  List<TreeNode> _enclosingTryBlocks;
+  List<TreeNode> _enclosingTryCatches;
 
   _ScopeBuilder(this.locals);
 
@@ -188,6 +254,11 @@
   void _visitFunction(TreeNode node) {
     _enterFrame(node);
 
+    final savedEnclosingTryBlocks = _enclosingTryBlocks;
+    _enclosingTryBlocks = <TreeNode>[];
+    final savedEnclosingTryCatches = _enclosingTryCatches;
+    _enclosingTryCatches = <TreeNode>[];
+
     if (node is Field) {
       node.initializer.accept(this);
     } else {
@@ -199,6 +270,11 @@
       FunctionNode function = (node as dynamic).function;
       assert(function != null);
 
+      _currentFrame.isDartSync = function.dartAsyncMarker == AsyncMarker.Sync;
+
+      _currentFrame.isSyncYielding =
+          function.asyncMarker == AsyncMarker.SyncYielding;
+
       _currentFrame.numTypeArguments =
           (_currentFrame.parent?.numTypeArguments ?? 0) +
               function.typeParameters.length;
@@ -224,6 +300,15 @@
       visitList(function.positionalParameters, this);
       visitList(function.namedParameters, this);
 
+      if (_currentFrame.isSyncYielding) {
+        // The following variables from parent frame are used implicitly and need
+        // to be captured to preserve state across closure invocations.
+        _useVariable(_currentFrame.parent
+            .getSyntheticVar(ContinuationVariables.awaitJumpVar));
+        _useVariable(_currentFrame.parent
+            .getSyntheticVar(ContinuationVariables.awaitContextVar));
+      }
+
       if (node is Constructor) {
         for (var field in node.enclosingClass.fields) {
           if (!field.isStatic && field.initializer != null) {
@@ -245,6 +330,9 @@
       _declareVariable(_currentFrame.scratchVar);
     }
 
+    _enclosingTryBlocks = savedEnclosingTryBlocks;
+    _enclosingTryCatches = savedEnclosingTryCatches;
+
     _leaveFrame();
   }
 
@@ -290,6 +378,56 @@
     _useVariable(_currentFrame.receiverVar);
   }
 
+  void _captureAllVisibleVariablesInCurrentFrame() {
+    assert(_currentFrame.isSyncYielding);
+    final transient = new Set<VariableDeclaration>();
+    transient
+      ..addAll([
+        _currentFrame.typeArgsVar,
+        _currentFrame.closureVar,
+        _currentFrame.contextVar,
+        _currentFrame.scratchVar,
+      ]);
+    transient.addAll((_currentFrame.function as FunctionDeclaration)
+        .function
+        .positionalParameters);
+    for (Scope scope = _currentScope;
+        scope != null && scope.frame == _currentFrame;
+        scope = scope.parent) {
+      for (VarDesc v in scope.vars) {
+        if (!transient.contains(v.declaration)) {
+          v.capture();
+        }
+      }
+    }
+  }
+
+  // Capture synthetic variables for control flow statements.
+  void _captureSyntheticVariables() {
+    int depth = 0;
+    for (TreeNode tryBlock in _enclosingTryBlocks) {
+      _captureSyntheticVariable(ContinuationVariables.savedTryContextVar(depth),
+          tryBlock, locals._capturedSavedContextVars);
+      ++depth;
+    }
+    depth = 0;
+    for (TreeNode tryBlock in _enclosingTryCatches) {
+      _captureSyntheticVariable(ContinuationVariables.exceptionVar(depth),
+          tryBlock, locals._capturedExceptionVars);
+      _captureSyntheticVariable(ContinuationVariables.stackTraceVar(depth),
+          tryBlock, locals._capturedStackTraceVars);
+      ++depth;
+    }
+  }
+
+  void _captureSyntheticVariable(
+      String name, TreeNode node, Map<TreeNode, VariableDeclaration> map) {
+    final variable = _currentFrame.parent.getSyntheticVar(name);
+    _useVariable(variable);
+    assert(map[node] == null || map[node] == variable);
+    map[node] = variable;
+  }
+
   void _visitWithScope(TreeNode node) {
     _enterScope(node);
     node.visitChildren(this);
@@ -317,6 +455,13 @@
   @override
   visitVariableDeclaration(VariableDeclaration node) {
     _declareVariable(node);
+
+    if (!_currentFrame.isDartSync && node.name[0] == ':') {
+      _currentFrame.syntheticVars ??= <String, VariableDeclaration>{};
+      assert(_currentFrame.syntheticVars[node.name] == null);
+      _currentFrame.syntheticVars[node.name] = node;
+    }
+
     node.visitChildren(this);
   }
 
@@ -381,10 +526,28 @@
   visitForInStatement(ForInStatement node) {
     node.iterable.accept(this);
 
+    VariableDeclaration iteratorVar;
+    if (_currentFrame.isSyncYielding) {
+      // Declare a variable to hold 'iterator' so it could be captured.
+      iteratorVar = new VariableDeclaration(null);
+      _declareVariable(iteratorVar);
+      locals._capturedIteratorVars[node] = iteratorVar;
+    }
+
     _enterScope(node);
     node.variable.accept(this);
     node.body.accept(this);
     _leaveScope();
+
+    if (_currentFrame.isSyncYielding && !locals.isCaptured(iteratorVar)) {
+      // Iterator variable was not captured, as there are no yield points
+      // inside for-in statement body. The variable is needed only if captured,
+      // so undeclare it.
+      assert(_currentScope.vars.last == locals._vars[iteratorVar]);
+      _currentScope.vars.removeLast();
+      locals._vars.remove(iteratorVar);
+      locals._capturedIteratorVars.remove(node);
+    }
   }
 
   @override
@@ -396,6 +559,36 @@
   visitLet(Let node) {
     _visitWithScope(node);
   }
+
+  @override
+  visitYieldStatement(YieldStatement node) {
+    assert(_currentFrame.isSyncYielding);
+    _captureAllVisibleVariablesInCurrentFrame();
+    _captureSyntheticVariables();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitTryCatch(TryCatch node) {
+    _enclosingTryBlocks.add(node);
+    node.body?.accept(this);
+    _enclosingTryBlocks.removeLast();
+
+    _enclosingTryCatches.add(node);
+    visitList(node.catches, this);
+    _enclosingTryCatches.removeLast();
+  }
+
+  @override
+  visitTryFinally(TryFinally node) {
+    _enclosingTryBlocks.add(node);
+    node.body?.accept(this);
+    _enclosingTryBlocks.removeLast();
+
+    _enclosingTryCatches.add(node);
+    node.finalizer?.accept(this);
+    _enclosingTryCatches.removeLast();
+  }
 }
 
 class _Allocator extends RecursiveVisitor<Null> {
@@ -416,6 +609,10 @@
     if (_currentScope.frame != _currentFrame) {
       _currentFrame = _currentScope.frame;
 
+      if (_currentScope.parent != null) {
+        _currentFrame.contextLevelAtEntry = _currentScope.parent.contextLevel;
+      }
+
       _currentScope.localsUsed = 0;
       _currentScope.tempsUsed = 0;
     } else {
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 332017e..72a6607 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -163,7 +163,7 @@
     constants.transformComponent(component, vmConstants,
         keepFields: true,
         strongMode: true,
-        evaluateAnnotations: false,
+        evaluateAnnotations: true,
         enableAsserts: enableAsserts,
         errorReporter:
             new ForwardConstantEvaluationErrors(context, typeEnvironment));
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 40a3e79..4c6eff1 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -12,6 +12,7 @@
 import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
 import 'package:kernel/class_hierarchy.dart' show ClosedWorldClassHierarchy;
 import 'package:kernel/library_index.dart' show LibraryIndex;
+import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/type_environment.dart';
 
 import 'calls.dart';
@@ -1148,7 +1149,7 @@
   final Map<Member, Summary> _summaries = <Member, Summary>{};
   final Map<Field, _FieldValue> _fieldValues = <Field, _FieldValue>{};
 
-  TypeFlowAnalysis(
+  TypeFlowAnalysis(Component component, CoreTypes coreTypes,
       ClosedWorldClassHierarchy hierarchy, this.environment, this.libraryIndex,
       {List<String> entryPointsJSONFiles})
       : nativeCodeOracle = new NativeCodeOracle(libraryIndex) {
@@ -1161,6 +1162,8 @@
     if (entryPointsJSONFiles != null) {
       nativeCodeOracle.processEntryPointsJSONFiles(entryPointsJSONFiles, this);
     }
+
+    component.accept(new PragmaEntryPointsVisitor(coreTypes, this));
   }
 
   _Invocation get currentInvocation => workList.callStack.last;
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index d3f72d6..8e4a171 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -11,6 +11,7 @@
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/library_index.dart' show LibraryIndex;
+import 'package:kernel/core_types.dart' show CoreTypes;
 
 // TODO(alexmarkov): Move findNativeName out of treeshaker and avoid dependency
 // on unrelated transformation.
@@ -31,6 +32,66 @@
   ConcreteType addAllocatedClass(Class c);
 }
 
+/// Some entry points are not listed in any JSON file but are marked with the
+/// `@pragma('vm.entry_point', ...)` annotation instead.
+///
+/// Currently Procedure`s (action "call") can be annotated in this way.
+//
+// TODO(sjindel): Support all types of entry points.
+class PragmaEntryPointsVisitor extends RecursiveVisitor {
+  final EntryPointsListener entryPoints;
+  final CoreTypes coreTypes;
+
+  PragmaEntryPointsVisitor(this.coreTypes, this.entryPoints);
+
+  bool _definesRoot(InstanceConstant constant) {
+    if (constant.classReference.node != coreTypes.pragmaClass) return false;
+
+    Constant name = constant.fieldValues[coreTypes.pragmaName.reference];
+    assertx(name != null);
+    if (name is! StringConstant ||
+        (name as StringConstant).value != "vm.entry_point") {
+      return false;
+    }
+
+    Constant options = constant.fieldValues[coreTypes.pragmaOptions.reference];
+    assertx(options != null);
+    if (options is NullConstant) return true;
+    return options is BoolConstant && options.value;
+  }
+
+  bool _annotationsDefineRoot(List<Expression> annotations) {
+    for (var annotation in annotations) {
+      if (annotation is ConstantExpression) {
+        Constant constant = annotation.constant;
+        if (constant is InstanceConstant) {
+          if (_definesRoot(constant)) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  @override
+  visitClass(Class klass) {
+    if (_annotationsDefineRoot(klass.annotations)) {
+      entryPoints.addAllocatedClass(klass);
+    }
+    klass.visitChildren(this);
+  }
+
+  @override
+  visitProcedure(Procedure proc) {
+    if (_annotationsDefineRoot(proc.annotations)) {
+      entryPoints.addRawCall(proc.isInstanceMember
+          ? new InterfaceSelector(proc, callKind: CallKind.Method)
+          : new DirectSelector(proc, callKind: CallKind.Method));
+    }
+  }
+}
+
 /// Provides insights into the behavior of native code.
 class NativeCodeOracle {
   final Map<String, List<Map<String, dynamic>>> _nativeMethods =
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index b3a037a..cfcbec7 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -51,7 +51,8 @@
   Statistics.reset();
   final analysisStopWatch = new Stopwatch()..start();
 
-  final typeFlowAnalysis = new TypeFlowAnalysis(hierarchy, types, libraryIndex,
+  final typeFlowAnalysis = new TypeFlowAnalysis(
+      component, coreTypes, hierarchy, types, libraryIndex,
       entryPointsJSONFiles: entryPoints);
 
   Procedure main = component.mainMethod;
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 2a35304..bfd1219 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -33,7 +33,8 @@
 
   group('batch compile with mocked compiler', () {
     final CompilerInterface compiler = new _MockedCompiler();
-    when(compiler.compile(any, any, generator: any)).thenReturn(true);
+    when(compiler.compile(any, any, generator: anyNamed('generator')))
+        .thenAnswer((_) => new Future.value(true));
 
     test('compile from command line', () async {
       final List<String> args = <String>[
@@ -46,7 +47,7 @@
       final List<ArgResults> capturedArgs = verify(compiler.compile(
         argThat(equals('server.dart')),
         captureAny,
-        generator: any,
+        generator: anyNamed('generator'),
       )).captured;
       expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
       expect(capturedArgs.single['strong'], equals(false));
@@ -64,7 +65,7 @@
       final List<ArgResults> capturedArgs = verify(compiler.compile(
         argThat(equals('server.dart')),
         captureAny,
-        generator: any,
+        generator: anyNamed('generator'),
       )).captured;
       expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
       expect(capturedArgs.single['strong'], equals(true));
@@ -84,7 +85,7 @@
       final List<ArgResults> capturedArgs = verify(compiler.compile(
         argThat(equals('server.dart')),
         captureAny,
-        generator: any,
+        generator: anyNamed('generator'),
       )).captured;
       expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
       expect(capturedArgs.single['strong'], equals(true));
@@ -103,7 +104,7 @@
       final List<ArgResults> capturedArgs = verify(compiler.compile(
         argThat(equals('server.dart')),
         captureAny,
-        generator: any,
+        generator: anyNamed('generator'),
       )).captured;
       expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
       expect(capturedArgs.single['link-platform'], equals(true));
@@ -123,7 +124,7 @@
       final StreamController<List<int>> inputStreamController =
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
-      when(compiler.compile(any, any, generator: any))
+      when(compiler.compile(any, any, generator: anyNamed('generator')))
           .thenAnswer((Invocation invocation) {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
@@ -161,7 +162,7 @@
       final StreamController<List<int>> inputStreamController =
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
-      when(compiler.compile(any, any, generator: any))
+      when(compiler.compile(any, any, generator: anyNamed('generator')))
           .thenAnswer((Invocation invocation) {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
@@ -185,7 +186,7 @@
       final StreamController<List<int>> inputStreamController =
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
-      when(compiler.compile(any, any, generator: any))
+      when(compiler.compile(any, any, generator: anyNamed('generator')))
           .thenAnswer((Invocation invocation) {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
@@ -210,7 +211,7 @@
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
       int counter = 1;
-      when(compiler.compile(any, any, generator: any))
+      when(compiler.compile(any, any, generator: anyNamed('generator')))
           .thenAnswer((Invocation invocation) {
         expect(invocation.positionalArguments[0],
             equals('server${counter++}.dart'));
@@ -235,7 +236,8 @@
 
   group('interactive incremental compile with mocked compiler', () {
     final CompilerInterface compiler = new _MockedCompiler();
-    when(compiler.compile(any, any, generator: any)).thenReturn(true);
+    when(compiler.compile(any, any, generator: anyNamed('generator')))
+        .thenAnswer((_) => new Future.value(true));
 
     final List<String> args = <String>[
       '--sdk-root',
@@ -356,7 +358,8 @@
       await recompileCalled.first;
 
       verifyInOrder(<void>[
-        await compiler.compile('file1.dart', any, generator: any),
+        await compiler.compile('file1.dart', any,
+            generator: anyNamed('generator')),
         compiler.acceptLastDelta(),
         compiler.invalidate(Uri.base.resolve('file2.dart')),
         compiler.invalidate(Uri.base.resolve('file3.dart')),
@@ -430,7 +433,8 @@
 
     group('compile with output path', () {
       final CompilerInterface compiler = new _MockedCompiler();
-      when(compiler.compile(any, any, generator: any)).thenReturn(true);
+      when(compiler.compile(any, any, generator: anyNamed('generator')))
+          .thenAnswer((_) => new Future.value(true));
 
       test('compile from command line', () async {
         final List<String> args = <String>[
@@ -447,7 +451,7 @@
         final List<ArgResults> capturedArgs = verify(compiler.compile(
           argThat(equals('server.dart')),
           captureAny,
-          generator: any,
+          generator: anyNamed('generator'),
         )).captured;
         expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
         expect(capturedArgs.single['strong'], equals(false));
diff --git a/pkg/vm/testcases/bytecode/async.dart b/pkg/vm/testcases/bytecode/async.dart
new file mode 100644
index 0000000..e3900c7
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/async.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+Future<int> foo() async => 42;
+
+Future<int> simpleAsyncAwait(Future<int> a, Future<int> b) async {
+  return (await a) + (await b);
+}
+
+Future<int> loops(List<int> list) async {
+  int sum = 0;
+  for (int i = 0; i < 10; ++i) {
+    for (var j in list) {
+      sum += i + j + await foo();
+    }
+  }
+  for (int k = 0; k < 10; ++k) {
+    sum += k;
+  }
+  return sum;
+}
+
+Future<int> tryCatchRethrow(Future<int> a, Future<int> b, Future<int> c) async {
+  int x = 1;
+  try {
+    x = x + await a;
+  } catch (e) {
+    if (e is Error) {
+      return 42;
+    }
+    x = x + await b;
+    rethrow;
+  } finally {
+    print('fin');
+    x = x + await c;
+    return x;
+  }
+}
+
+closure(Future<int> a) {
+  int x = 3;
+  Future<int> nested() async {
+    int y = 4;
+    try {
+      x = 5;
+      y = await a;
+      return x + y;
+    } finally {
+      print('fin');
+    }
+  }
+
+  return nested;
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
new file mode 100644
index 0000000..cf1e13f
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -0,0 +1,2193 @@
+library #lib;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+[@vm.bytecode=
+Bytecode {
+  Entry                7
+  CheckStack
+  AllocateContext      4
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#1
+  PushConstant         CP#3
+  IndirectStaticCall   1, CP#2
+  StoreFieldTOS        CP#4
+  Push                 r0
+  PushConstant         CP#5
+  StoreFieldTOS        CP#6
+  PushConstant         CP#5
+  PopLocal             r2
+  PushConstant         CP#5
+  PopLocal             r3
+  PushConstant         CP#5
+  PopLocal             r4
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#8
+  Push                 r0
+  PushConstant         CP#5
+  StoreFieldTOS        CP#9
+  Allocate             CP#19
+  StoreLocal           r6
+  Push                 r6
+  PushConstant         CP#5
+  StoreFieldTOS        CP#20
+  Push                 r6
+  PushConstant         CP#5
+  StoreFieldTOS        CP#21
+  Push                 r6
+  PushConstant         CP#10
+  StoreFieldTOS        CP#22
+  Push                 r6
+  Push                 r0
+  StoreFieldTOS        CP#11
+  PopLocal             r5
+  Push                 r5
+  PushConstant         CP#24
+  IndirectStaticCall   1, CP#23
+  StoreLocal           r2
+  Drop1
+  Push                 r5
+  PushConstant         CP#25
+  IndirectStaticCall   1, CP#23
+  StoreLocal           r3
+  Drop1
+  Push                 r5
+  PushConstant         CP#26
+  IndirectStaticCall   1, CP#23
+  StoreLocal           r4
+  Drop1
+  PushConstant         CP#27
+  Push                 r5
+  PushConstant         CP#29
+  IndirectStaticCall   2, CP#28
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#4
+  InstanceCall1        1, CP#30
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#5
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = TypeArgs [dart.core::int]
+  [2] = ArgDesc num-args 0, num-type-args 1, names []
+  [3] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#2
+  [4] = ContextOffset var [3]
+  [5] = Null
+  [6] = ContextOffset var [2]
+  [7] = Int 0
+  [8] = ContextOffset var [0]
+  [9] = ContextOffset var [1]
+  [10] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [11] = FieldOffset dart.core::_Closure::_context
+  [12] = Int 42
+  [13] = ArgDesc num-args 2, num-type-args 0, names []
+  [14] = ICData target-name 'complete', arg-desc CP#13
+  [15] = Type dynamic
+  [16] = ArgDesc num-args 3, num-type-args 0, names []
+  [17] = ICData target-name 'completeError', arg-desc CP#16
+  [18] = EndClosureFunctionScope
+  [19] = Class dart.core::_Closure
+  [20] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [21] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [22] = FieldOffset dart.core::_Closure::_function
+  [23] = ArgDesc num-args 1, num-type-args 0, names []
+  [24] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#23
+  [25] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#23
+  [26] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#23
+  [27] = TypeArgs [dynamic]
+  [28] = ArgDesc num-args 1, num-type-args 1, names []
+  [29] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#28
+  [30] = ICData get target-name 'future', arg-desc CP#23
+}
+Closure CP#10 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#5
+  LoadConstant         r2, CP#5
+  LoadConstant         r3, CP#5
+  Frame                6
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#11
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#8
+  StoreLocal           r5
+  PushConstant         CP#7
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  PopLocal             r6
+Try #0 start:
+  Push                 r4
+  PushConstant         CP#12
+  StoreLocal           r8
+  StoreFieldTOS        CP#6
+  Push                 r8
+  Drop1
+  Jump                 L2
+L2:
+  Push                 r4
+  LoadFieldTOS         CP#4
+  Push                 r4
+  LoadFieldTOS         CP#6
+  InstanceCall1        2, CP#14
+  Drop1
+  PushConstant         CP#5
+  ReturnTOS
+  Jump                 L3
+Try #0 end:
+Try #0 handler:
+  Push                 r6
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#4
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#17
+  Drop1
+  Jump                 L3
+L3:
+  PushConstant         CP#5
+  ReturnTOS
+L1:
+  Trap
+
+}
+]static method foo() → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = 42;
+        break #L1;
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      2
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-6]
+  StoreFieldTOS        CP#1
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#2
+  AllocateContext      9
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#3
+  PushConstant         CP#5
+  IndirectStaticCall   1, CP#4
+  StoreFieldTOS        CP#6
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#8
+  PushConstant         CP#7
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#9
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#10
+  Push                 r0
+  PushConstant         CP#11
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#2
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#12
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#13
+  Push                 r0
+  Allocate             CP#29
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#7
+  StoreFieldTOS        CP#30
+  Push                 r3
+  PushConstant         CP#7
+  StoreFieldTOS        CP#31
+  Push                 r3
+  PushConstant         CP#14
+  StoreFieldTOS        CP#32
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#15
+  StoreFieldTOS        CP#17
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#34
+  IndirectStaticCall   1, CP#33
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#35
+  IndirectStaticCall   1, CP#33
+  StoreLocal           r3
+  StoreFieldTOS        CP#9
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#36
+  IndirectStaticCall   1, CP#33
+  StoreLocal           r3
+  StoreFieldTOS        CP#10
+  Push                 r3
+  Drop1
+  PushConstant         CP#37
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#39
+  IndirectStaticCall   2, CP#38
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#6
+  InstanceCall1        1, CP#40
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#7
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = ContextOffset var [1]
+  [3] = TypeArgs [dart.core::int]
+  [4] = ArgDesc num-args 0, num-type-args 1, names []
+  [5] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#4
+  [6] = ContextOffset var [8]
+  [7] = Null
+  [8] = ContextOffset var [7]
+  [9] = ContextOffset var [3]
+  [10] = ContextOffset var [4]
+  [11] = Int 0
+  [12] = ContextOffset var [2]
+  [13] = ContextOffset var [6]
+  [14] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [15] = FieldOffset dart.core::_Closure::_context
+  [16] = Int 1
+  [17] = ContextOffset var [5]
+  [18] = ArgDesc num-args 4, num-type-args 0, names []
+  [19] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#18
+  [20] = Int 2
+  [21] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#18
+  [22] = ArgDesc num-args 2, num-type-args 0, names []
+  [23] = ICData target-name '+', arg-desc CP#22
+  [24] = ICData target-name 'complete', arg-desc CP#22
+  [25] = Type dynamic
+  [26] = ArgDesc num-args 3, num-type-args 0, names []
+  [27] = ICData target-name 'completeError', arg-desc CP#26
+  [28] = EndClosureFunctionScope
+  [29] = Class dart.core::_Closure
+  [30] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [31] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [32] = FieldOffset dart.core::_Closure::_function
+  [33] = ArgDesc num-args 1, num-type-args 0, names []
+  [34] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#33
+  [35] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#33
+  [36] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#33
+  [37] = TypeArgs [dynamic]
+  [38] = ArgDesc num-args 1, num-type-args 1, names []
+  [39] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#38
+  [40] = ICData get target-name 'future', arg-desc CP#33
+}
+Closure CP#14 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#7
+  LoadConstant         r2, CP#7
+  LoadConstant         r3, CP#7
+  Frame                6
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#11
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#12
+Try #0 start:
+  Push                 r4
+  PushConstant         CP#16
+  StoreFieldTOS        CP#1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#9
+  Push                 r4
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#17
+  PushConstant         CP#19
+  IndirectStaticCall   4, CP#18
+  PopLocal             r8
+  PushConstant         CP#7
+  ReturnTOS
+L6:
+  IfEqNull             r2
+  Jump                 L2
+  Push                 r2
+  Push                 r3
+  Throw                1
+L2:
+  Push                 r4
+  Push                 r1
+  StoreLocal           r8
+  StoreFieldTOS        CP#13
+  Push                 r8
+  Drop1
+  Push                 r4
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#2
+  Push                 r4
+  LoadFieldTOS         CP#9
+  Push                 r4
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#17
+  PushConstant         CP#21
+  IndirectStaticCall   4, CP#18
+  PopLocal             r9
+  PushConstant         CP#7
+  ReturnTOS
+L7:
+  IfEqNull             r2
+  Jump                 L3
+  Push                 r2
+  Push                 r3
+  Throw                1
+L3:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#13
+  Push                 r1
+  InstanceCall1        2, CP#23
+  StoreLocal           r8
+  StoreFieldTOS        CP#8
+  Push                 r8
+  Drop1
+  Jump                 L4
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#6
+  Push                 r4
+  LoadFieldTOS         CP#8
+  InstanceCall1        2, CP#24
+  Drop1
+  PushConstant         CP#7
+  ReturnTOS
+  Jump                 L5
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#12
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#6
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#27
+  Drop1
+  Jump                 L5
+L5:
+  PushConstant         CP#7
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#2
+  PopLocal             r4
+  Push                 r5
+  PushConstant         CP#16
+  IfEqStrictNumTOS
+  Jump                 L6
+  Jump                 L7
+
+}
+]static method simpleAsyncAwait(asy::Future<core::int> a, asy::Future<core::int> b) → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :async_temporary_0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
+        :async_temporary_0 = :result;
+        [yield] let dynamic #t2 = asy::_awaitHelper(b, :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = :async_temporary_0.{core::num::+}(:result);
+        break #L2;
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      1
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#1
+  AllocateContext      10
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#2
+  PushConstant         CP#4
+  IndirectStaticCall   1, CP#3
+  StoreFieldTOS        CP#5
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#7
+  PushConstant         CP#6
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#8
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#9
+  Push                 r0
+  PushConstant         CP#10
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#11
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#12
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#13
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#14
+  Push                 r0
+  Allocate             CP#43
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#6
+  StoreFieldTOS        CP#44
+  Push                 r3
+  PushConstant         CP#6
+  StoreFieldTOS        CP#45
+  Push                 r3
+  PushConstant         CP#15
+  StoreFieldTOS        CP#46
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#16
+  StoreFieldTOS        CP#29
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#47
+  IndirectStaticCall   1, CP#21
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#48
+  IndirectStaticCall   1, CP#21
+  StoreLocal           r3
+  StoreFieldTOS        CP#8
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#49
+  IndirectStaticCall   1, CP#21
+  StoreLocal           r3
+  StoreFieldTOS        CP#9
+  Push                 r3
+  Drop1
+  PushConstant         CP#50
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#52
+  IndirectStaticCall   2, CP#51
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#5
+  InstanceCall1        1, CP#53
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#6
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = TypeArgs [dart.core::int]
+  [3] = ArgDesc num-args 0, num-type-args 1, names []
+  [4] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#3
+  [5] = ContextOffset var [9]
+  [6] = Null
+  [7] = ContextOffset var [8]
+  [8] = ContextOffset var [5]
+  [9] = ContextOffset var [6]
+  [10] = Int 0
+  [11] = ContextOffset var [1]
+  [12] = ContextOffset var [4]
+  [13] = ContextOffset var [3]
+  [14] = ContextOffset var [2]
+  [15] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [16] = FieldOffset dart.core::_Closure::_context
+  [17] = Int 10
+  [18] = ArgDesc num-args 2, num-type-args 0, names []
+  [19] = ICData target-name '<', arg-desc CP#18
+  [20] = Bool true
+  [21] = ArgDesc num-args 1, num-type-args 0, names []
+  [22] = ICData get target-name 'iterator', arg-desc CP#21
+  [23] = ICData target-name 'moveNext', arg-desc CP#21
+  [24] = ICData get target-name 'current', arg-desc CP#21
+  [25] = ICData target-name '+', arg-desc CP#18
+  [26] = Int 1
+  [27] = ArgDesc num-args 0, num-type-args 0, names []
+  [28] = StaticICData target '#lib::foo', arg-desc CP#27
+  [29] = ContextOffset var [7]
+  [30] = ArgDesc num-args 4, num-type-args 0, names []
+  [31] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#30
+  [32] = ICData target-name '+', arg-desc CP#18
+  [33] = ICData target-name '+', arg-desc CP#18
+  [34] = ICData target-name '+', arg-desc CP#18
+  [35] = ICData target-name '<', arg-desc CP#18
+  [36] = ICData target-name '+', arg-desc CP#18
+  [37] = ICData target-name '+', arg-desc CP#18
+  [38] = ICData target-name 'complete', arg-desc CP#18
+  [39] = Type dynamic
+  [40] = ArgDesc num-args 3, num-type-args 0, names []
+  [41] = ICData target-name 'completeError', arg-desc CP#40
+  [42] = EndClosureFunctionScope
+  [43] = Class dart.core::_Closure
+  [44] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [45] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [46] = FieldOffset dart.core::_Closure::_function
+  [47] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#21
+  [48] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#21
+  [49] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#21
+  [50] = TypeArgs [dynamic]
+  [51] = ArgDesc num-args 1, num-type-args 1, names []
+  [52] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#51
+  [53] = ICData get target-name 'future', arg-desc CP#21
+}
+Closure CP#15 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#6
+  LoadConstant         r2, CP#6
+  LoadConstant         r3, CP#6
+  Frame                7
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#10
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#12
+Try #0 start:
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#10
+  StoreFieldTOS        CP#1
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#10
+  StoreFieldTOS        CP#1
+L6:
+  CheckStack
+  Push                 r4
+  LoadFieldTOS         CP#1
+  PushConstant         CP#17
+  InstanceCall1        2, CP#19
+  PushConstant         CP#20
+  IfNeStrictTOS
+  Jump                 L2
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  InstanceCall1        1, CP#22
+  PopLocal             r8
+  Push                 r4
+  Push                 r8
+  StoreFieldTOS        CP#1
+L5:
+  CheckStack
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r8
+  InstanceCall1        1, CP#23
+  PushConstant         CP#20
+  IfNeStrictTOS
+  Jump                 L3
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  Push                 r8
+  InstanceCall1        1, CP#24
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  StoreLocal           r9
+  StoreFieldTOS        CP#14
+  Push                 r9
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#1
+  InstanceCall1        2, CP#25
+  StoreLocal           r9
+  StoreFieldTOS        CP#13
+  Push                 r9
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#26
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#11
+  PushConstant         CP#28
+  IndirectStaticCall   0, CP#27
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#8
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#31
+  IndirectStaticCall   4, CP#30
+  PopLocal             r10
+  PushConstant         CP#6
+  ReturnTOS
+L11:
+  IfEqNull             r2
+  Jump                 L4
+  Push                 r2
+  Push                 r3
+  Throw                1
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#14
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#13
+  Push                 r1
+  InstanceCall1        2, CP#32
+  InstanceCall1        2, CP#33
+  StoreLocal           r9
+  StoreFieldTOS        CP#1
+  Push                 r9
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L5
+L3:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Push                 r4
+  CloneContext
+  PopLocal             r4
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  PushConstant         CP#26
+  InstanceCall1        2, CP#34
+  StoreLocal           r8
+  StoreFieldTOS        CP#1
+  Push                 r8
+  Drop1
+  Jump                 L6
+L2:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  PushConstant         CP#10
+  PopLocal             r8
+L8:
+  CheckStack
+  Push                 r8
+  PushConstant         CP#17
+  InstanceCall1        2, CP#35
+  PushConstant         CP#20
+  IfNeStrictTOS
+  Jump                 L7
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  Push                 r8
+  InstanceCall1        2, CP#36
+  StoreLocal           r9
+  StoreFieldTOS        CP#1
+  Push                 r9
+  Drop1
+  Push                 r8
+  PushConstant         CP#26
+  InstanceCall1        2, CP#37
+  StoreLocal           r8
+  Drop1
+  Jump                 L8
+L7:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r8
+  StoreFieldTOS        CP#7
+  Push                 r8
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+L9:
+  Push                 r4
+  LoadFieldTOS         CP#5
+  Push                 r4
+  LoadFieldTOS         CP#7
+  InstanceCall1        2, CP#38
+  Drop1
+  PushConstant         CP#6
+  ReturnTOS
+  Jump                 L10
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#12
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#5
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#41
+  Drop1
+  Jump                 L10
+L10:
+  PushConstant         CP#6
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#11
+  PopLocal             r4
+  Jump                 L11
+
+}
+]static method loops(core::List<core::int> list) → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :async_temporary_0;
+  dynamic :async_temporary_1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        core::int sum = 0;
+        for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+          for (core::int j in list) {
+            :async_temporary_1 = sum;
+            :async_temporary_0 = i.{core::num::+}(j);
+            [yield] let dynamic #t3 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
+            sum = :async_temporary_1.{core::num::+}(:async_temporary_0.{core::num::+}(:result));
+          }
+        }
+        for (core::int k = 0; k.{core::num::<}(10); k = k.{core::num::+}(1)) {
+          sum = sum.{core::num::+}(k);
+        }
+        :return_value = sum;
+        break #L3;
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      3
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-7]
+  StoreFieldTOS        CP#1
+  Push                 r0
+  Push                 FP[-6]
+  StoreFieldTOS        CP#2
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#3
+  AllocateContext      13
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#4
+  PushConstant         CP#6
+  IndirectStaticCall   1, CP#5
+  StoreFieldTOS        CP#7
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#9
+  PushConstant         CP#8
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#10
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#11
+  Push                 r0
+  PushConstant         CP#12
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#2
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#13
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#14
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#15
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#16
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#17
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#3
+  Push                 r0
+  Allocate             CP#52
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#8
+  StoreFieldTOS        CP#53
+  Push                 r3
+  PushConstant         CP#8
+  StoreFieldTOS        CP#54
+  Push                 r3
+  PushConstant         CP#18
+  StoreFieldTOS        CP#55
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#19
+  StoreFieldTOS        CP#21
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#56
+  IndirectStaticCall   1, CP#35
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#57
+  IndirectStaticCall   1, CP#35
+  StoreLocal           r3
+  StoreFieldTOS        CP#10
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#58
+  IndirectStaticCall   1, CP#35
+  StoreLocal           r3
+  StoreFieldTOS        CP#11
+  Push                 r3
+  Drop1
+  PushConstant         CP#59
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#61
+  IndirectStaticCall   2, CP#60
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#7
+  InstanceCall1        1, CP#62
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#8
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = ContextOffset var [1]
+  [3] = ContextOffset var [2]
+  [4] = TypeArgs [dart.core::int]
+  [5] = ArgDesc num-args 0, num-type-args 1, names []
+  [6] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#5
+  [7] = ContextOffset var [12]
+  [8] = Null
+  [9] = ContextOffset var [9]
+  [10] = ContextOffset var [6]
+  [11] = ContextOffset var [7]
+  [12] = Int 0
+  [13] = ContextOffset var [3]
+  [14] = ContextOffset var [4]
+  [15] = ContextOffset var [5]
+  [16] = ContextOffset var [10]
+  [17] = ContextOffset var [11]
+  [18] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [19] = FieldOffset dart.core::_Closure::_context
+  [20] = Int 1
+  [21] = ContextOffset var [8]
+  [22] = ArgDesc num-args 4, num-type-args 0, names []
+  [23] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [24] = ArgDesc num-args 2, num-type-args 0, names []
+  [25] = ICData target-name '+', arg-desc CP#24
+  [26] = Type dynamic
+  [27] = Type dart.core::Error
+  [28] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#22
+  [29] = Bool true
+  [30] = Int 42
+  [31] = Int 2
+  [32] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [33] = ICData target-name '+', arg-desc CP#24
+  [34] = String 'fin'
+  [35] = ArgDesc num-args 1, num-type-args 0, names []
+  [36] = StaticICData target 'dart.core::print', arg-desc CP#35
+  [37] = Int 3
+  [38] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [39] = ICData target-name '+', arg-desc CP#24
+  [40] = StaticICData target 'dart.core::print', arg-desc CP#35
+  [41] = Int 4
+  [42] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [43] = ICData target-name '+', arg-desc CP#24
+  [44] = StaticICData target 'dart.core::print', arg-desc CP#35
+  [45] = Int 5
+  [46] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [47] = ICData target-name '+', arg-desc CP#24
+  [48] = ICData target-name 'complete', arg-desc CP#24
+  [49] = ArgDesc num-args 3, num-type-args 0, names []
+  [50] = ICData target-name 'completeError', arg-desc CP#49
+  [51] = EndClosureFunctionScope
+  [52] = Class dart.core::_Closure
+  [53] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [54] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [55] = FieldOffset dart.core::_Closure::_function
+  [56] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#35
+  [57] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#35
+  [58] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#35
+  [59] = TypeArgs [dynamic]
+  [60] = ArgDesc num-args 1, num-type-args 1, names []
+  [61] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#60
+  [62] = ICData get target-name 'future', arg-desc CP#35
+}
+Closure CP#18 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#8
+  LoadConstant         r2, CP#8
+  LoadConstant         r3, CP#8
+  Frame                10
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#12
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#13
+Try #0 start:
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#14
+Try #1 start:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#15
+Try #2 start:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r12
+  StoreFieldTOS        CP#3
+  Push                 r12
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#23
+  IndirectStaticCall   4, CP#22
+  PopLocal             r13
+  PushConstant         CP#8
+  ReturnTOS
+L13:
+  IfEqNull             r2
+  Jump                 L2
+  Push                 r2
+  Push                 r3
+  Throw                1
+L2:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#25
+  StoreLocal           r12
+  StoreFieldTOS        CP#1
+  Push                 r12
+  Drop1
+  Jump                 L3
+Try #2 end:
+Try #2 handler:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  MoveSpecial          r10, exception
+  MoveSpecial          r11, stackTrace
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r10
+  StoreFieldTOS        CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r11
+  StoreFieldTOS        CP#17
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  Push                 r10
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#1
+  PushConstant         CP#8
+  PushConstant         CP#8
+  PushConstant         CP#27
+  InstanceCall1        4, CP#28
+  PushConstant         CP#29
+  IfNeStrictTOS
+  Jump                 L4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#30
+  StoreLocal           r12
+  StoreFieldTOS        CP#9
+  Push                 r12
+  Drop1
+  Jump                 L5
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  StoreLocal           r12
+  StoreFieldTOS        CP#3
+  Push                 r12
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#31
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#32
+  IndirectStaticCall   4, CP#22
+  PopLocal             r13
+  PushConstant         CP#8
+  ReturnTOS
+L14:
+  IfEqNull             r2
+  Jump                 L6
+  Push                 r2
+  Push                 r3
+  Throw                1
+L6:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#33
+  StoreLocal           r12
+  StoreFieldTOS        CP#1
+  Push                 r12
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#17
+  Throw                1
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L3
+L3:
+  Jump                 L7
+Try #1 end:
+Try #1 handler:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  MoveSpecial          r8, exception
+  MoveSpecial          r9, stackTrace
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r8
+  StoreFieldTOS        CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r9
+  StoreFieldTOS        CP#17
+  PushConstant         CP#34
+  PushConstant         CP#36
+  IndirectStaticCall   1, CP#35
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#3
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#37
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#38
+  IndirectStaticCall   4, CP#22
+  PopLocal             r12
+  PushConstant         CP#8
+  ReturnTOS
+L15:
+  IfEqNull             r2
+  Jump                 L8
+  Push                 r2
+  Push                 r3
+  Throw                1
+L8:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#39
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#9
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#17
+  Throw                1
+L5:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  PushConstant         CP#34
+  PushConstant         CP#40
+  IndirectStaticCall   1, CP#35
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#3
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#41
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#42
+  IndirectStaticCall   4, CP#22
+  PopLocal             r12
+  PushConstant         CP#8
+  ReturnTOS
+L16:
+  IfEqNull             r2
+  Jump                 L10
+  Push                 r2
+  Push                 r3
+  Throw                1
+L10:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#43
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#9
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+L7:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  PushConstant         CP#34
+  PushConstant         CP#44
+  IndirectStaticCall   1, CP#35
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#3
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#45
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#46
+  IndirectStaticCall   4, CP#22
+  PopLocal             r12
+  PushConstant         CP#8
+  ReturnTOS
+L17:
+  IfEqNull             r2
+  Jump                 L11
+  Push                 r2
+  Push                 r3
+  Throw                1
+L11:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#47
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#9
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+L9:
+  Push                 r4
+  LoadFieldTOS         CP#7
+  Push                 r4
+  LoadFieldTOS         CP#9
+  InstanceCall1        2, CP#48
+  Drop1
+  PushConstant         CP#8
+  ReturnTOS
+  Jump                 L12
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#13
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#7
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#50
+  Drop1
+  Jump                 L12
+L12:
+  PushConstant         CP#8
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#2
+  PopLocal             r4
+  Push                 r5
+  PushConstant         CP#20
+  IfEqStrictNumTOS
+  Jump                 L13
+  Push                 r5
+  PushConstant         CP#31
+  IfEqStrictNumTOS
+  Jump                 L14
+  Push                 r5
+  PushConstant         CP#37
+  IfEqStrictNumTOS
+  Jump                 L15
+  Push                 r5
+  PushConstant         CP#41
+  IfEqStrictNumTOS
+  Jump                 L16
+  Jump                 L17
+
+}
+]static method tryCatchRethrow(asy::Future<core::int> a, asy::Future<core::int> b, asy::Future<core::int> c) → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :saved_try_context_var2;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  dynamic :async_temporary_0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        core::int x = 1;
+        try
+          try {
+            :async_temporary_0 = x;
+            [yield] let dynamic #t4 = asy::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
+            x = :async_temporary_0.{core::num::+}(:result);
+          }
+          on dynamic catch(final dynamic e) {
+            if(e is core::Error) {
+              :return_value = 42;
+              break #L4;
+            }
+            :async_temporary_0 = x;
+            [yield] let dynamic #t5 = asy::_awaitHelper(b, :async_op_then, :async_op_error, :async_op) in null;
+            x = :async_temporary_0.{core::num::+}(:result);
+            rethrow;
+          }
+        finally {
+          core::print("fin");
+          :async_temporary_0 = x;
+          [yield] let dynamic #t6 = asy::_awaitHelper(c, :async_op_then, :async_op_error, :async_op) in null;
+          x = :async_temporary_0.{core::num::+}(:result);
+          :return_value = x;
+          break #L4;
+        }
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      1
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#1
+  AllocateContext      1
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#2
+  StoreFieldTOS        CP#1
+  Allocate             CP#36
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#37
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#38
+  Push                 r3
+  PushConstant         CP#3
+  StoreFieldTOS        CP#39
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#4
+  PopLocal             r2
+  Push                 r2
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#9
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = Int 3
+  [3] = ClosureFunction nested () → dart.async::Future<dart.core::int> /* originally async */ ;
+  [4] = FieldOffset dart.core::_Closure::_context
+  [5] = TypeArgs [dart.core::int]
+  [6] = ArgDesc num-args 0, num-type-args 1, names []
+  [7] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#6
+  [8] = ContextOffset var [8]
+  [9] = Null
+  [10] = ContextOffset var [7]
+  [11] = ContextOffset var [4]
+  [12] = ContextOffset var [5]
+  [13] = Int 0
+  [14] = ContextOffset var [1]
+  [15] = ContextOffset var [2]
+  [16] = ContextOffset var [3]
+  [17] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [18] = Int 4
+  [19] = Int 5
+  [20] = Int 1
+  [21] = ContextOffset var [6]
+  [22] = ArgDesc num-args 4, num-type-args 0, names []
+  [23] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [24] = ArgDesc num-args 2, num-type-args 0, names []
+  [25] = ICData target-name '+', arg-desc CP#24
+  [26] = Type dynamic
+  [27] = String 'fin'
+  [28] = ArgDesc num-args 1, num-type-args 0, names []
+  [29] = StaticICData target 'dart.core::print', arg-desc CP#28
+  [30] = StaticICData target 'dart.core::print', arg-desc CP#28
+  [31] = StaticICData target 'dart.core::print', arg-desc CP#28
+  [32] = ICData target-name 'complete', arg-desc CP#24
+  [33] = ArgDesc num-args 3, num-type-args 0, names []
+  [34] = ICData target-name 'completeError', arg-desc CP#33
+  [35] = EndClosureFunctionScope
+  [36] = Class dart.core::_Closure
+  [37] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [38] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [39] = FieldOffset dart.core::_Closure::_function
+  [40] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#28
+  [41] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#28
+  [42] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#28
+  [43] = TypeArgs [dynamic]
+  [44] = ArgDesc num-args 1, num-type-args 1, names []
+  [45] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#44
+  [46] = ICData get target-name 'future', arg-desc CP#28
+  [47] = EndClosureFunctionScope
+}
+Closure CP#17 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#9
+  LoadConstant         r2, CP#9
+  LoadConstant         r3, CP#9
+  Frame                8
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#13
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#15
+Try #0 start:
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#18
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#16
+Try #1 start:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#19
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#14
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#12
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#23
+  IndirectStaticCall   4, CP#22
+  PopLocal             r11
+  PushConstant         CP#9
+  ReturnTOS
+L6:
+  Push                 r4
+  Push                 r1
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#1
+  InstanceCall1        2, CP#25
+  StoreLocal           r10
+  StoreFieldTOS        CP#10
+  Push                 r10
+  Drop1
+  Jump                 L2
+  Jump                 L3
+Try #1 end:
+Try #1 handler:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  MoveSpecial          r8, exception
+  MoveSpecial          r9, stackTrace
+  PushConstant         CP#27
+  PushConstant         CP#29
+  IndirectStaticCall   1, CP#28
+  Drop1
+  Push                 r8
+  Push                 r9
+  Throw                1
+L2:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  PushConstant         CP#27
+  PushConstant         CP#30
+  IndirectStaticCall   1, CP#28
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L4
+L3:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  PushConstant         CP#27
+  PushConstant         CP#31
+  IndirectStaticCall   1, CP#28
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#8
+  Push                 r4
+  LoadFieldTOS         CP#10
+  InstanceCall1        2, CP#32
+  Drop1
+  PushConstant         CP#9
+  ReturnTOS
+  Jump                 L5
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#8
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#34
+  Drop1
+  Jump                 L5
+L5:
+  PushConstant         CP#9
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  Jump                 L6
+
+}
+
+Closure CP#3 {
+  Entry                4
+  CheckStack
+  Push                 FP[-5]
+  LoadFieldTOS         CP#4
+  PopLocal             r0
+  AllocateContext      9
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#5
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#6
+  StoreFieldTOS        CP#8
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#10
+  PushConstant         CP#9
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#11
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#12
+  Push                 r0
+  PushConstant         CP#13
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#14
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#15
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#16
+  Push                 r0
+  Allocate             CP#36
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#37
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#38
+  Push                 r3
+  PushConstant         CP#17
+  StoreFieldTOS        CP#39
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#4
+  StoreFieldTOS        CP#21
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#40
+  IndirectStaticCall   1, CP#28
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#41
+  IndirectStaticCall   1, CP#28
+  StoreLocal           r3
+  StoreFieldTOS        CP#11
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#42
+  IndirectStaticCall   1, CP#28
+  StoreLocal           r3
+  StoreFieldTOS        CP#12
+  Push                 r3
+  Drop1
+  PushConstant         CP#43
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#45
+  IndirectStaticCall   2, CP#44
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#8
+  InstanceCall1        1, CP#46
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#9
+  ReturnTOS
+
+}
+]static method closure(asy::Future<core::int> a) → dynamic {
+  core::int x = 3;
+  function nested() → asy::Future<core::int> /* originally async */ {
+    final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+    asy::FutureOr<core::int> :return_value;
+    dynamic :async_stack_trace;
+    dynamic :async_op_then;
+    dynamic :async_op_error;
+    dynamic :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    dynamic :saved_try_context_var1;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L5:
+        {
+          core::int y = 4;
+          try {
+            x = 5;
+            [yield] let dynamic #t7 = asy::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
+            y = :result;
+            :return_value = x.{core::num::+}(y);
+            break #L5;
+          }
+          finally {
+            core::print("fin");
+          }
+        }
+        :async_completer.{asy::Completer::complete}(:return_value);
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+      }
+    :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+    :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+    asy::Future::microtask<dynamic>(:async_op);
+    return :async_completer.{asy::Completer::future};
+  }
+  return nested;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/boostrapping.dart b/pkg/vm/testcases/bytecode/bootstrapping.dart
similarity index 100%
rename from pkg/vm/testcases/bytecode/boostrapping.dart
rename to pkg/vm/testcases/bytecode/bootstrapping.dart
diff --git a/pkg/vm/testcases/bytecode/boostrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
similarity index 94%
rename from pkg/vm/testcases/bytecode/boostrapping.dart.expect
rename to pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index f84988b..5ff4e07 100644
--- a/pkg/vm/testcases/bytecode/boostrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -67,41 +67,11 @@
 ]  constructor _() → void
     : super core::Object::•()
     ;
-[@vm.bytecode=
-Bytecode {
-  Entry                0
-  CheckStack
-  PushConstant         CP#0
-  ReturnTOS
-}
-ConstantPool {
-  [0] = Null
-}
-]  @_in::ExternalName::•("Namespace_Create")
+  @_in::ExternalName::•("Namespace_Create")
   external static method _create(self::_NamespaceImpl namespace, dynamic n) → self::_NamespaceImpl;
-[@vm.bytecode=
-Bytecode {
-  Entry                0
-  CheckStack
-  PushConstant         CP#0
-  ReturnTOS
-}
-ConstantPool {
-  [0] = Null
-}
-]  @_in::ExternalName::•("Namespace_GetPointer")
+  @_in::ExternalName::•("Namespace_GetPointer")
   external static method _getPointer(self::_NamespaceImpl namespace) → core::int;
-[@vm.bytecode=
-Bytecode {
-  Entry                0
-  CheckStack
-  PushConstant         CP#0
-  ReturnTOS
-}
-ConstantPool {
-  [0] = Null
-}
-]  @_in::ExternalName::•("Namespace_GetDefault")
+  @_in::ExternalName::•("Namespace_GetDefault")
   external static method _getDefault() → core::int;
 [@vm.bytecode=
 Bytecode {
@@ -502,7 +472,7 @@
   [9] = ICData target-name 'call', arg-desc CP#8
 }
 ]  static get platformScript() → dynamic {
-    if(self::VMLibraryHooks::_cachedScript.==(null) && !self::VMLibraryHooks::_computeScriptUri.==(null)) {
+    if(self::VMLibraryHooks::_cachedScript.{core::Object::==}(null) && !self::VMLibraryHooks::_computeScriptUri.{core::Object::==}(null)) {
       self::VMLibraryHooks::_cachedScript = self::VMLibraryHooks::_computeScriptUri.call();
     }
     return self::VMLibraryHooks::_cachedScript;
@@ -542,17 +512,7 @@
 }
 ]static field core::int _stderrFD = 2;
 static field core::String _rawScript;
-[@vm.bytecode=
-Bytecode {
-  Entry                0
-  CheckStack
-  PushConstant         CP#0
-  ReturnTOS
-}
-ConstantPool {
-  [0] = Null
-}
-]@_in::ExternalName::•("Builtin_PrintString")
+@_in::ExternalName::•("Builtin_PrintString")
 external static method _printString(core::String s) → void;
 [@vm.bytecode=
 Bytecode {
@@ -573,7 +533,7 @@
   [3] = Null
 }
 ]static method _print(dynamic arg) → void {
-  self::_printString(arg.toString() as{TypeError} core::String);
+  self::_printString(arg.{core::Object::toString}());
 }
 [@vm.bytecode=
 Bytecode {
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 2f1906c..7bf2d87 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -628,7 +628,7 @@
   [13] = ClosureFunction closure2 () → void;
   [14] = ICData target-name '+', arg-desc CP#7
   [15] = ArgDesc num-args 1, num-type-args 0, names []
-  [16] = ICData target-name 'get:foo', arg-desc CP#15
+  [16] = ICData get target-name 'foo', arg-desc CP#15
   [17] = ICData target-name '+', arg-desc CP#7
   [18] = Null
   [19] = EndClosureFunctionScope
@@ -648,7 +648,7 @@
   [33] = StaticICData target 'dart.core::print', arg-desc CP#15
   [34] = Int 42
   [35] = ClosureFunction <anonymous closure> () → dart.core::Null;
-  [36] = ICData target-name 'set:foo', arg-desc CP#7
+  [36] = ICData set target-name 'foo', arg-desc CP#7
   [37] = EndClosureFunctionScope
   [38] = ICData target-name 'call', arg-desc CP#15
 }
@@ -1090,11 +1090,11 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData target-name 'get:iterator', arg-desc CP#0
+  [1] = ICData get target-name 'iterator', arg-desc CP#0
   [2] = ICData target-name 'moveNext', arg-desc CP#0
   [3] = Bool true
   [4] = ContextOffset parent
-  [5] = ICData target-name 'get:current', arg-desc CP#0
+  [5] = ICData get target-name 'current', arg-desc CP#0
   [6] = ContextOffset var [0]
   [7] = ClosureFunction <anonymous closure> () → dart.core::Null;
   [8] = FieldOffset dart.core::_Closure::_context
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index 635bc5b..f2bf88a 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -41,7 +41,7 @@
 ConstantPool {
   [0] = Int 0
   [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = ICData target-name 'get:length', arg-desc CP#1
+  [2] = ICData get target-name 'length', arg-desc CP#1
   [3] = ArgDesc num-args 2, num-type-args 0, names []
   [4] = ICData target-name '<', arg-desc CP#3
   [5] = Bool true
@@ -108,7 +108,7 @@
   [2] = ICData target-name '>=', arg-desc CP#1
   [3] = Bool true
   [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = ICData target-name 'get:length', arg-desc CP#4
+  [5] = ICData get target-name 'length', arg-desc CP#4
   [6] = ICData target-name '>=', arg-desc CP#1
   [7] = ICData target-name '[]', arg-desc CP#1
   [8] = ICData target-name '+', arg-desc CP#1
@@ -178,7 +178,7 @@
   [1] = Int 100
   [2] = ArgDesc num-args 1, num-type-args 0, names []
   [3] = ICData target-name 'unary-', arg-desc CP#2
-  [4] = ICData target-name 'get:length', arg-desc CP#2
+  [4] = ICData get target-name 'length', arg-desc CP#2
   [5] = ArgDesc num-args 2, num-type-args 0, names []
   [6] = ICData target-name '<', arg-desc CP#5
   [7] = Bool true
@@ -242,7 +242,7 @@
 ConstantPool {
   [0] = Int 0
   [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = ICData target-name 'get:length', arg-desc CP#1
+  [2] = ICData get target-name 'length', arg-desc CP#1
   [3] = ArgDesc num-args 2, num-type-args 0, names []
   [4] = ICData target-name '<', arg-desc CP#3
   [5] = Bool true
@@ -302,7 +302,7 @@
   [4] = Int 1
   [5] = ICData target-name '+', arg-desc CP#1
   [6] = ArgDesc num-args 1, num-type-args 0, names []
-  [7] = ICData target-name 'get:length', arg-desc CP#6
+  [7] = ICData get target-name 'length', arg-desc CP#6
   [8] = ICData target-name '<', arg-desc CP#1
   [9] = Bool true
   [10] = Null
@@ -351,10 +351,10 @@
 ConstantPool {
   [0] = Int 0
   [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = ICData target-name 'get:iterator', arg-desc CP#1
+  [2] = ICData get target-name 'iterator', arg-desc CP#1
   [3] = ICData target-name 'moveNext', arg-desc CP#1
   [4] = Bool true
-  [5] = ICData target-name 'get:current', arg-desc CP#1
+  [5] = ICData get target-name 'current', arg-desc CP#1
   [6] = ArgDesc num-args 2, num-type-args 0, names []
   [7] = ICData target-name '+', arg-desc CP#6
   [8] = Null
@@ -406,10 +406,10 @@
   [0] = Int 0
   [1] = Int 42
   [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = ICData target-name 'get:iterator', arg-desc CP#2
+  [3] = ICData get target-name 'iterator', arg-desc CP#2
   [4] = ICData target-name 'moveNext', arg-desc CP#2
   [5] = Bool true
-  [6] = ICData target-name 'get:current', arg-desc CP#2
+  [6] = ICData get target-name 'current', arg-desc CP#2
   [7] = ArgDesc num-args 2, num-type-args 0, names []
   [8] = ICData target-name '+', arg-desc CP#7
   [9] = Null
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index 0dbaad8..f3ac1e4 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -204,12 +204,12 @@
   [3] = Type dart.core::TypeError
   [4] = Null
   [5] = ArgDesc num-args 4, num-type-args 0, names []
-  [6] = ICData target-name '_instanceOf', arg-desc CP#5
+  [6] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#5
   [7] = Bool true
   [8] = String 'caught type error'
   [9] = StaticICData target 'dart.core::print', arg-desc CP#1
   [10] = Type dart.core::AssertionError
-  [11] = ICData target-name '_instanceOf', arg-desc CP#5
+  [11] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#5
   [12] = Int 2
   [13] = Int 0
   [14] = String 'caught assertion error '
@@ -217,7 +217,7 @@
   [16] = StaticICData target 'dart.core::_StringBase::_interpolate', arg-desc CP#1
   [17] = StaticICData target 'dart.core::print', arg-desc CP#1
   [18] = Type dart.core::Error
-  [19] = ICData target-name '_instanceOf', arg-desc CP#5
+  [19] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#5
   [20] = Int 4
   [21] = String 'caught error '
   [22] = String ' '
@@ -404,7 +404,7 @@
   [28] = StaticICData target 'dart.core::print', arg-desc CP#7
   [29] = Type dart.core::Error
   [30] = ArgDesc num-args 4, num-type-args 0, names []
-  [31] = ICData target-name '_instanceOf', arg-desc CP#30
+  [31] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#30
   [32] = Bool true
   [33] = String 'error '
   [34] = String ', captured stack trace: '
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index f0549ca..fe9a2d4 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -133,17 +133,17 @@
   [1] = Null
   [2] = Type #lib::A<#lib::D::P>
   [3] = ArgDesc num-args 4, num-type-args 0, names []
-  [4] = ICData target-name '_instanceOf', arg-desc CP#3
+  [4] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#3
   [5] = Bool true
   [6] = String '21'
   [7] = ArgDesc num-args 1, num-type-args 0, names []
   [8] = StaticICData target 'dart.core::print', arg-desc CP#7
   [9] = Type #lib::C<dynamic, #lib::D::Q, dart.core::List<#lib::D::P>>
-  [10] = ICData target-name '_instanceOf', arg-desc CP#3
+  [10] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#3
   [11] = String '22'
   [12] = StaticICData target 'dart.core::print', arg-desc CP#7
   [13] = ArgDesc num-args 2, num-type-args 0, names []
-  [14] = ICData target-name 'set:foo', arg-desc CP#13
+  [14] = ICData set target-name 'foo', arg-desc CP#13
 }
 ]  method foo2(dynamic y) → dynamic {
     if(y is self::A<self::D::P>) {
@@ -201,18 +201,18 @@
   [0] = TypeArgumentsFieldOffset #lib::D
   [1] = Type #lib::A<#lib::D::foo3::T1>
   [2] = ArgDesc num-args 4, num-type-args 0, names []
-  [3] = ICData target-name '_instanceOf', arg-desc CP#2
+  [3] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
   [4] = Bool true
   [5] = String '31'
   [6] = ArgDesc num-args 1, num-type-args 0, names []
   [7] = StaticICData target 'dart.core::print', arg-desc CP#6
   [8] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
-  [9] = ICData target-name '_instanceOf', arg-desc CP#2
+  [9] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
   [10] = String '32'
   [11] = StaticICData target 'dart.core::print', arg-desc CP#6
   [12] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
-  [13] = ICData target-name '_as', arg-desc CP#2
-  [14] = ICData target-name 'get:values', arg-desc CP#6
+  [13] = ICData target-name 'dart.core::_as', arg-desc CP#2
+  [14] = ICData get target-name 'values', arg-desc CP#6
   [15] = Null
 }
 ]  method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
@@ -268,17 +268,17 @@
   [0] = Null
   [1] = Type #lib::B
   [2] = ArgDesc num-args 4, num-type-args 0, names []
-  [3] = ICData target-name '_instanceOf', arg-desc CP#2
+  [3] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
   [4] = Bool true
   [5] = String '11'
   [6] = ArgDesc num-args 1, num-type-args 0, names []
   [7] = StaticICData target 'dart.core::print', arg-desc CP#6
   [8] = Type #lib::C<dart.core::int, dart.core::Object, dynamic>
-  [9] = ICData target-name '_instanceOf', arg-desc CP#2
+  [9] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
   [10] = String '12'
   [11] = StaticICData target 'dart.core::print', arg-desc CP#6
   [12] = Type #lib::A<dart.core::int>
-  [13] = ICData target-name '_as', arg-desc CP#2
+  [13] = ICData target-name 'dart.core::_as', arg-desc CP#2
 }
 ]static method foo1(dynamic x) → dynamic {
   if(x is self::B) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index e7c4fe3..49b8a68 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -17,7 +17,7 @@
   }
   operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
     core::double result = 0.0;
-    for (core::int i = 0; [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
+    for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
       result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]??] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
     return result;
   }
@@ -26,7 +26,7 @@
 [@vm.inferred-type.metadata=dart.core::_Double?]static field core::double x = 0.0;
 static method main(core::List<core::String> args) → dynamic {
   core::Stopwatch timer = let final core::Stopwatch #t4 = new core::Stopwatch::•() in let final dynamic #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t4.{core::Stopwatch::start}() in #t4;
-  for (core::int i = 0; [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
+  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
     self::x = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*??] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v));
   }
   [@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index 21c932f..0e43e97 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -49,10 +49,10 @@
   [@vm.direct-call.metadata=#lib::C::foo??] aa.{self::A::foo}();
 }
 static method callerE1([@vm.inferred-type.metadata=!] dynamic x) → void {
-  x.toString();
+  [@vm.direct-call.metadata=dart.core::_StringBase::toString] x.{core::Object::toString}();
 }
 static method callerE2([@vm.inferred-type.metadata=#lib::E?] dynamic x) → void {
-  x.toString();
+  x.{core::Object::toString}();
 }
 static method main(core::List<core::String> args) → dynamic {
   self::callerA1(new self::B::•());
diff --git a/pkg/vm/tool/dart2 b/pkg/vm/tool/dart2
index e127775..a41cfc2 100755
--- a/pkg/vm/tool/dart2
+++ b/pkg/vm/tool/dart2
@@ -43,5 +43,4 @@
      --preview_dart_2                                                          \
      --strong                                                                  \
      --reify-generic-functions                                                 \
-     --limit-ints-to-64-bits                                                   \
      "$@"
diff --git a/pkg/vm/tool/dart2.bat b/pkg/vm/tool/dart2.bat
index 83e73bb..5d82e33 100644
--- a/pkg/vm/tool/dart2.bat
+++ b/pkg/vm/tool/dart2.bat
@@ -35,4 +35,4 @@
 )
 set KERNEL_SERVICE_SNAPSHOT=%BUILD_DIR%/gen/kernel-service.dart.snapshot
 
-"%DART_BINARY%" --preview_dart_2 --strong --reify-generic-functions --limit-ints-to-64-bits %*
+"%DART_BINARY%" --preview_dart_2 --strong --reify-generic-functions %*
diff --git a/pkg/vm/tool/dart_precompiled_runtime2 b/pkg/vm/tool/dart_precompiled_runtime2
index eeb33e3..d8c490a 100755
--- a/pkg/vm/tool/dart_precompiled_runtime2
+++ b/pkg/vm/tool/dart_precompiled_runtime2
@@ -36,5 +36,4 @@
 exec "$BIN_DIR"/dart_precompiled_runtime               \
      --strong                                          \
      --reify-generic-functions                         \
-     --limit-ints-to-64-bits                           \
      "$@"
diff --git a/pkg/vm/tool/gen_kernel b/pkg/vm/tool/gen_kernel
index 551d2d5..63130b2 100755
--- a/pkg/vm/tool/gen_kernel
+++ b/pkg/vm/tool/gen_kernel
@@ -8,9 +8,6 @@
 
 set -e
 
-# Enable Dart 2.0 fixed-size integers for gen_kernel
-DART_VM_FLAGS="--limit-ints-to-64-bits $DART_VM_FLAGS"
-
 function follow_links() {
   file="$1"
   while [ -h "$file" ]; do
diff --git a/pkg/vm/tool/gen_kernel.bat b/pkg/vm/tool/gen_kernel.bat
index 83a99572..17af350 100644
--- a/pkg/vm/tool/gen_kernel.bat
+++ b/pkg/vm/tool/gen_kernel.bat
@@ -13,9 +13,6 @@
 
 set SDK_DIR=%SCRIPTPATH%/../../../
 
-REM Enable Dart 2.0 fixed-size integers for gen_kernel
-set DART_VM_OPTIONS=--limit-ints-to-64-bits %DART_VM_OPTIONS%
-
 set DART=%SDK_DIR%/tools/sdks/win/dart-sdk/bin/dart.exe
 
 "%DART%" %DART_VM_OPTIONS% "%SDK_DIR%/pkg/vm/bin/gen_kernel.dart" %*
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index d707213..5689819 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -95,7 +95,6 @@
 
 # Step 1: Generate Kernel binary from the input Dart source.
 "$BIN_DIR"/dart                                                                \
-     --limit-ints-to-64-bits                                                   \
      "${SDK_DIR}/pkg/vm/bin/gen_kernel.dart"                                   \
      --platform "${BIN_DIR}/vm_platform_strong.dill"                           \
      --aot                                                                     \
@@ -109,7 +108,6 @@
 "$BIN_DIR"/dart_bootstrap                                                      \
      --strong                                                                  \
      --reify-generic-functions                                                 \
-     --limit-ints-to-64-bits                                                   \
      --snapshot-kind=app-aot                                                   \
      --snapshot="$DART_BOOTSTRAP_OUT"                                          \
      "${OPTIONS[@]}"                                                           \
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 64b76f5..0096fa6 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -7,6 +7,7 @@
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/dfe.h"
+#include "bin/error_exit.h"
 #include "bin/extensions.h"
 #include "bin/file.h"
 #include "bin/gzip.h"
@@ -660,7 +661,6 @@
   if (Dart_IsError(result)) {
     return result;
   }
-  Dart_Isolate current = Dart_CurrentIsolate();
   if (tag == Dart_kKernelTag) {
     uint8_t* kernel_buffer = NULL;
     intptr_t kernel_buffer_size = 0;
@@ -687,7 +687,6 @@
 
     return Extensions::LoadExtension("/", absolute_path, library);
   }
-  ASSERT(Dart_IsKernelIsolate(current) || !dfe.UseDartFrontend());
   if (tag != Dart_kScriptTag) {
     // Special case for handling dart: imports and parts.
     // Grab the library's url.
@@ -766,8 +765,25 @@
     loader->SendImportExtensionRequest(url, Dart_LibraryUrl(library));
   } else {
     if (dfe.CanUseDartFrontend() && dfe.UseDartFrontend() &&
-        !Dart_IsKernelIsolate(current)) {
-      FATAL("Loader should not be called to compile scripts to kernel.");
+        (tag == Dart_kImportTag)) {
+      // E.g., IsolateMirror.loadUri.
+      char* error = NULL;
+      int exit_code = 0;
+      uint8_t* kernel_buffer = NULL;
+      intptr_t kernel_buffer_size = -1;
+      dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size,
+                               &error, &exit_code, true /* strong */, NULL);
+      if (exit_code == 0) {
+        return Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
+      } else if (exit_code == kCompilationErrorExitCode) {
+        Dart_Handle result = Dart_NewCompilationError(error);
+        free(error);
+        return result;
+      } else {
+        Dart_Handle result = Dart_NewApiError(error);
+        free(error);
+        return result;
+      }
     } else {
       loader->SendRequest(
           tag, url,
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index d46910b..7b8346b 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -857,7 +857,6 @@
     {"dart:isolate", "::", "_getIsolateScheduleImmediateClosure"},
     {"dart:isolate", "::", "_setupHooks"},
     {"dart:isolate", "::", "_startMainIsolate"},
-    {"dart:vmservice_io", "::", "main"},
     // Fields
     {"dart:_builtin", "::", "_isolateId"},
     {"dart:_builtin", "::", "_loadPort"},
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 3dfe66c..4fca3b2 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -70,7 +70,6 @@
   OPTION_FIELD(preview_dart_2) = true;
   vm_options->AddArgument("--strong");
   vm_options->AddArgument("--reify-generic-functions");
-  vm_options->AddArgument("--limit-ints-to-64-bits");
   vm_options->AddArgument("--sync-async");
 }
 
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 5bed503..c5db6b9 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -13,6 +13,8 @@
 #include "include/dart_api.h"
 #include "platform/utils.h"
 
+#define LOG_SECTION_BOUNDARIES false
+
 namespace dart {
 namespace bin {
 
@@ -288,12 +290,18 @@
   ASSERT(file->Position() == kAppSnapshotHeaderSize);
 
   file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+  if (LOG_SECTION_BOUNDARIES) {
+    Log::PrintErr("%" Px64 ": VM Data\n", file->Position());
+  }
   if (!file->WriteFully(vm_data_buffer, vm_data_size)) {
     ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
   }
 
   if (vm_instructions_size != 0) {
     file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+    if (LOG_SECTION_BOUNDARIES) {
+      Log::PrintErr("%" Px64 ": VM Instructions\n", file->Position());
+    }
     if (!file->WriteFully(vm_instructions_buffer, vm_instructions_size)) {
       ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
                 filename);
@@ -301,12 +309,18 @@
   }
 
   file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+  if (LOG_SECTION_BOUNDARIES) {
+    Log::PrintErr("%" Px64 ": Isolate Data\n", file->Position());
+  }
   if (!file->WriteFully(isolate_data_buffer, isolate_data_size)) {
     ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
   }
 
   if (isolate_instructions_size != 0) {
     file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+    if (LOG_SECTION_BOUNDARIES) {
+      Log::PrintErr("%" Px64 ": Isolate Instructions\n", file->Position());
+    }
     if (!file->WriteFully(isolate_instructions_buffer,
                           isolate_instructions_size)) {
       ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 14f6cb6..9dc5954 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -220,6 +220,7 @@
   _signalSubscription = _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
 }
 
+@pragma("vm.entry_point")
 main() {
   // Set embedder hooks.
   VMServiceEmbedderHooks.cleanup = cleanupCallback;
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index e287914..c52f569 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -351,6 +351,7 @@
  * \param error the error message.
  */
 DART_EXPORT Dart_Handle Dart_NewApiError(const char* error);
+DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error);
 
 /**
  * Produces a new unhandled exception error handle.
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index e167523..e2c0998 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -10,6 +10,12 @@
 
 namespace dart {
 
+DEFINE_NATIVE_ENTRY(List_new, 2) {
+  // This function is handled by flow-graph builder.
+  UNREACHABLE();
+  return Object::null();
+}
+
 DEFINE_NATIVE_ENTRY(List_allocate, 2) {
   // Implemented in FlowGraphBuilder::VisitNativeBody.
   UNREACHABLE();
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 27fc745..3ff5fda 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -4,28 +4,10 @@
 
 // part of "core_patch.dart";
 
-// The _GrowableArrayMarker class is used to signal to the List() factory
-// whether a parameter was passed.
-class _GrowableArrayMarker implements int {
-  const _GrowableArrayMarker();
-  noSuchMethod(_) {
-    throw new UnimplementedError();
-  }
-}
-
-const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
-
 @patch
 class List<E> {
   @patch
-  factory List([int length = _GROWABLE_ARRAY_MARKER]) {
-    if (identical(length, _GROWABLE_ARRAY_MARKER)) {
-      return new _GrowableList<E>(0);
-    }
-    // All error handling on the length parameter is done at the implementation
-    // of new _List.
-    return new _List<E>(length);
-  }
+  factory List([int length]) native "List_new";
 
   @patch
   factory List.filled(int length, E fill, {bool growable: false}) {
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 1651cfa..352a2ec 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -9,6 +9,7 @@
 #include "vm/class_finalizer.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
 #include "vm/compiler/jit/compiler.h"
+#include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
 #include "vm/exceptions.h"
 #include "vm/flags.h"
@@ -759,6 +760,95 @@
   return CreateIsolateMirror();
 }
 
+static void ThrowLanguageError(const char* message) {
+  const Error& error =
+      Error::Handle(LanguageError::New(String::Handle(String::New(message))));
+  Exceptions::PropagateError(error);
+}
+
+DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));
+
+  Dart_LibraryTagHandler handler = isolate->library_tag_handler();
+  if (handler == NULL) {
+    ThrowLanguageError("no library handler registered");
+  }
+
+  // Canonicalize library URI.
+  String& canonical_uri = String::Handle(zone);
+  if (uri.StartsWith(Symbols::DartScheme())) {
+    canonical_uri = uri.raw();
+  } else {
+    isolate->BlockClassFinalization();
+    Object& result = Object::Handle(zone);
+    {
+      TransitionVMToNative transition(thread);
+      Api::Scope api_scope(thread);
+      Dart_Handle retval = handler(
+          Dart_kCanonicalizeUrl,
+          Api::NewHandle(thread, isolate->object_store()->root_library()),
+          Api::NewHandle(thread, uri.raw()));
+      result = Api::UnwrapHandle(retval);
+    }
+    isolate->UnblockClassFinalization();
+    if (result.IsError()) {
+      if (result.IsLanguageError()) {
+        Exceptions::ThrowCompileTimeError(LanguageError::Cast(result));
+      }
+      Exceptions::PropagateError(Error::Cast(result));
+    } else if (!result.IsString()) {
+      ThrowLanguageError("library handler failed URI canonicalization");
+    }
+
+    canonical_uri ^= result.raw();
+  }
+
+  // Create a new library if it does not exist yet.
+  Library& library =
+      Library::Handle(zone, Library::LookupLibrary(thread, canonical_uri));
+  if (library.IsNull()) {
+    library = Library::New(canonical_uri);
+    library.Register(thread);
+  }
+
+  // Ensure loading started.
+  if (library.LoadNotStarted()) {
+    library.SetLoadRequested();
+
+    isolate->BlockClassFinalization();
+    Object& result = Object::Handle(zone);
+    {
+      TransitionVMToNative transition(thread);
+      Api::Scope api_scope(thread);
+      Dart_Handle retval = handler(
+          Dart_kImportTag,
+          Api::NewHandle(thread, isolate->object_store()->root_library()),
+          Api::NewHandle(thread, canonical_uri.raw()));
+      result = Api::UnwrapHandle(retval);
+    }
+    isolate->UnblockClassFinalization();
+    if (result.IsError()) {
+      if (result.IsLanguageError()) {
+        Exceptions::ThrowCompileTimeError(LanguageError::Cast(result));
+      }
+      Exceptions::PropagateError(Error::Cast(result));
+    }
+  }
+
+  if (!library.Loaded()) {
+    // This code assumes a synchronous tag handler (which dart::bin and tonic
+    // provide). Strictly though we should complete a future in response to
+    // Dart_FinalizeLoading.
+    UNIMPLEMENTED();
+  }
+
+  if (!ClassFinalizer::ProcessPendingClasses()) {
+    Exceptions::PropagateError(Error::Handle(thread->sticky_error()));
+  }
+
+  return CreateLibraryMirror(thread, library);
+}
+
 DEFINE_NATIVE_ENTRY(Mirrors_makeLocalClassMirror, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index eb0becb..639d6d8 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -125,6 +125,17 @@
   bool get isCurrent => true;
 
   String toString() => "IsolateMirror on '$debugName'";
+
+  Future<LibraryMirror> loadUri(Uri uri) async {
+    var result = _loadUri(uri.toString());
+    if (result == null) {
+      // Censored library.
+      throw new Exception("Cannot load $uri");
+    }
+    return result;
+  }
+
+  static LibraryMirror _loadUri(String uri) native "IsolateMirror_loadUri";
 }
 
 class _SyntheticAccessor implements MethodMirror {
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
index a15b9bd..28edcf1 100644
--- a/runtime/lib/stacktrace.cc
+++ b/runtime/lib/stacktrace.cc
@@ -139,7 +139,7 @@
 static void AppendFrames(const GrowableObjectArray& code_list,
                          const GrowableObjectArray& pc_offset_list,
                          int skip_frames) {
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index d023f6e..c2166c1 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -77,7 +77,7 @@
 /// The Dart VM can be embedded in Chromium or standalone.
 abstract class CommonWebSocketVM extends VM {
   final Completer _connected = new Completer();
-  final Completer _disconnected = new Completer<String>();
+  final Completer<String> _disconnected = new Completer<String>();
   final WebSocketVMTarget target;
   final Map<String, _WebSocketRequest> _delayedRequests =
       new Map<String, _WebSocketRequest>();
@@ -114,7 +114,7 @@
     }
   }
 
-  Future get onDisconnect => _disconnected.future;
+  Future<String> get onDisconnect => _disconnected.future;
   bool get isDisconnected => _disconnected.isCompleted;
 
   void disconnect({String reason: 'WebSocket closed'}) {
diff --git a/runtime/observatory/lib/src/elements/containers/search_bar.dart b/runtime/observatory/lib/src/elements/containers/search_bar.dart
index 3db5c16..e3cc4ea 100644
--- a/runtime/observatory/lib/src/elements/containers/search_bar.dart
+++ b/runtime/observatory/lib/src/elements/containers/search_bar.dart
@@ -138,7 +138,7 @@
           })
       ];
     }
-    _resultsArea.children = [
+    _resultsArea.nodes = [
       new ButtonElement()
         ..text = 'â–²'
         ..disabled = _results.isEmpty
diff --git a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
index 810de3a..4f9839e 100644
--- a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
+++ b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
@@ -151,7 +151,7 @@
         final rect = _header.getBoundingClientRect();
         _header.classes.add('attached');
         _viewport.style.top = '${rect.height}px';
-        final width = _header.children.fold(0, _foldWidth);
+        final width = _header.children.fold(0.0, _foldWidth);
         _buffer.style.minWidth = '${width}px';
       }
       _itemHeight = _buffer.children[0].getBoundingClientRect().height;
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 119e352..5cc6896 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -115,7 +115,7 @@
   Future<List<String>> complete(List<String> args) {
     var commands = debugger.cmd.matchCommand(args, false);
     var result = commands.map((command) => '${command.fullName} ');
-    return new Future.value(result);
+    return new Future.value(result.toList());
   }
 
   String helpShort =
@@ -1927,7 +1927,7 @@
 
   Future smartNext() async {
     if (isolatePaused()) {
-      var event = isolate.pauseEvent;
+      M.AsyncSuspensionEvent event = isolate.pauseEvent;
       if (event.atAsyncSuspension) {
         return asyncNext();
       } else {
@@ -1940,7 +1940,7 @@
 
   Future asyncNext() async {
     if (isolatePaused()) {
-      var event = isolate.pauseEvent;
+      M.AsyncSuspensionEvent event = isolate.pauseEvent;
       if (!event.atAsyncSuspension) {
         console.print("No async continuation at this location");
       } else {
@@ -2420,9 +2420,9 @@
 class DebuggerFrameElement extends HtmlElement implements Renderable {
   static const tag = const Tag<DebuggerFrameElement>('debugger-frame');
 
-  RenderingScheduler<DebuggerMessageElement> _r;
+  RenderingScheduler<DebuggerFrameElement> _r;
 
-  Stream<RenderedEvent<DebuggerMessageElement>> get onRendered => _r.onRendered;
+  Stream<RenderedEvent<DebuggerFrameElement>> get onRendered => _r.onRendered;
 
   Element _scroller;
   DivElement _varsDiv;
@@ -2475,7 +2475,7 @@
     assert(scripts != null);
     assert(events != null);
     final DebuggerFrameElement e = document.createElement(tag.name);
-    e._r = new RenderingScheduler(e, queue: queue);
+    e._r = new RenderingScheduler<DebuggerFrameElement>(e, queue: queue);
     e._isolate = isolate;
     e._frame = frame;
     e._scroller = scroller;
diff --git a/runtime/observatory/lib/src/elements/eval_box.dart b/runtime/observatory/lib/src/elements/eval_box.dart
index ca167b5..5096d75 100644
--- a/runtime/observatory/lib/src/elements/eval_box.dart
+++ b/runtime/observatory/lib/src/elements/eval_box.dart
@@ -74,12 +74,14 @@
     children = [
       new DivElement()
         ..classes = ['quicks']
-        ..children = _quickExpressions.map((q) => new ButtonElement()
-          ..text = q
-          ..onClick.listen((_) {
-            _expression = q;
-            _run();
-          })),
+        ..children = _quickExpressions
+            .map((q) => new ButtonElement()
+              ..text = q
+              ..onClick.listen((_) {
+                _expression = q;
+                _run();
+              }))
+            .toList(),
       new DivElement()
         ..classes = ['heading']
         ..children = [
diff --git a/runtime/observatory/lib/src/elements/heap_map.dart b/runtime/observatory/lib/src/elements/heap_map.dart
index f11f825..a5545d0 100644
--- a/runtime/observatory/lib/src/elements/heap_map.dart
+++ b/runtime/observatory/lib/src/elements/heap_map.dart
@@ -255,8 +255,8 @@
     var pages = _fragmentation['pages'];
     _status = 'Loaded $startPage of ${pages.length} pages';
     _r.dirty();
-    var startY = startPage * _pageHeight;
-    var endY = startY + _pageHeight;
+    var startY = (startPage * _pageHeight).round();
+    var endY = startY + _pageHeight.round();
     if (startPage >= pages.length || endY > _fragmentationData.height) {
       return;
     }
diff --git a/runtime/observatory/lib/src/elements/memory/allocations.dart b/runtime/observatory/lib/src/elements/memory/allocations.dart
index 64f9595..ad3c5dd 100644
--- a/runtime/observatory/lib/src/elements/memory/allocations.dart
+++ b/runtime/observatory/lib/src/elements/memory/allocations.dart
@@ -161,7 +161,7 @@
         ..children = [
           new SpanElement()
             ..classes = ['group']
-            ..children = [
+            ..nodes = [
               new Text('Since Last '),
               resetAccumulators
                 ..text = 'Reset'
diff --git a/runtime/observatory/lib/src/elements/memory/profile.dart b/runtime/observatory/lib/src/elements/memory/profile.dart
index 9a87ab2..4a4f1d8 100644
--- a/runtime/observatory/lib/src/elements/memory/profile.dart
+++ b/runtime/observatory/lib/src/elements/memory/profile.dart
@@ -108,7 +108,7 @@
         ..classes = ['content-centered-big']
         ..children = [
           new HeadingElement.h1()
-            ..children = [
+            ..nodes = [
               new Text(_isolate.name),
               bReload
                 ..classes = ['header_button']
diff --git a/runtime/observatory/lib/src/elements/nav/notify.dart b/runtime/observatory/lib/src/elements/nav/notify.dart
index cbba2db..5eb9a52 100644
--- a/runtime/observatory/lib/src/elements/nav/notify.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify.dart
@@ -72,7 +72,7 @@
 
   bool _filter(M.Notification notification) {
     if (!_notifyOnPause && notification is M.EventNotification) {
-      return !M.Event.isPauseEvent(notification.event);
+      return notification.event is! M.PauseEvent;
     }
     return true;
   }
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 6937c9e..aedb6a9 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -82,11 +82,8 @@
     super.attached();
     _r.enable();
     _subscription = _events.onDebugEvent
-        .where((e) =>
-            (e is M.BreakpointAddedEvent) ||
-            (e is M.BreakpointResolvedEvent) ||
-            (e is M.BreakpointRemovedEvent))
-        .map((e) => e.breakpoint)
+        .where((e) => e is M.BreakpointEvent)
+        .map((e) => (e as M.BreakpointEvent).breakpoint)
         .listen((M.Breakpoint b) {
       final loc = b.location;
       int line;
diff --git a/runtime/observatory/lib/src/elements/timeline/dashboard.dart b/runtime/observatory/lib/src/elements/timeline/dashboard.dart
index bfa7f57..0f40c14 100644
--- a/runtime/observatory/lib/src/elements/timeline/dashboard.dart
+++ b/runtime/observatory/lib/src/elements/timeline/dashboard.dart
@@ -97,7 +97,7 @@
     _frame.src = _makeFrameUrl();
     _content.children = [
       new HeadingElement.h2()
-        ..children = ([new Text("Timeline View")]
+        ..nodes = ([new Text("Timeline View")]
           ..addAll(_createButtons())
           ..addAll(_createTabs())),
       new ParagraphElement()
@@ -118,7 +118,7 @@
     }
   }
 
-  List<Element> _createButtons() {
+  List<Node> _createButtons() {
     if (_flags == null) {
       return [new Text('Loading')];
     }
diff --git a/runtime/observatory/lib/src/models/objects/event.dart b/runtime/observatory/lib/src/models/objects/event.dart
index 4739554..24ed7e3 100644
--- a/runtime/observatory/lib/src/models/objects/event.dart
+++ b/runtime/observatory/lib/src/models/objects/event.dart
@@ -55,13 +55,25 @@
   IsolateRef get isolate;
 }
 
+abstract class BreakpointEvent extends DebugEvent {
+  /// [optional] The breakpoint associated with this event.
+  Breakpoint get breakpoint;
+}
+
+abstract class PauseEvent extends DebugEvent {}
+
+abstract class AsyncSuspensionEvent extends PauseEvent {
+  /// Is the isolate paused at an await, yield, or yield* statement?
+  bool get atAsyncSuspension;
+}
+
 abstract class DebuggerSettingsUpdateEvent extends DebugEvent {}
 
-abstract class PauseStartEvent extends DebugEvent {}
+abstract class PauseStartEvent extends PauseEvent {}
 
-abstract class PauseExitEvent extends DebugEvent {}
+abstract class PauseExitEvent extends PauseEvent {}
 
-abstract class PauseBreakpointEvent extends DebugEvent {
+abstract class PauseBreakpointEvent extends AsyncSuspensionEvent {
   /// [optional] The breakpoint at which we are currently paused.
   Breakpoint get breakpoint;
 
@@ -77,28 +89,21 @@
 
   /// The top stack frame associated with this event.
   Frame get topFrame;
-  bool get atAsyncSuspension;
 }
 
-abstract class PauseInterruptedEvent extends DebugEvent {
+abstract class PauseInterruptedEvent extends AsyncSuspensionEvent {
   /// [optional] The top stack frame associated with this event. There will be
   /// no top frame if the isolate is idle (waiting in the message loop).
   Frame get topFrame;
-
-  /// Is the isolate paused at an await, yield, or yield* statement?
-  bool get atAsyncSuspension;
 }
 
-abstract class PausePostRequestEvent extends DebugEvent {
+abstract class PausePostRequestEvent extends AsyncSuspensionEvent {
   /// [optional] The top stack frame associated with this event. There will be
   /// no top frame if the isolate is idle (waiting in the message loop).
   Frame get topFrame;
-
-  /// Is the isolate paused at an await, yield, or yield* statement?
-  bool get atAsyncSuspension;
 }
 
-abstract class PauseExceptionEvent extends DebugEvent {
+abstract class PauseExceptionEvent extends PauseEvent {
   /// The top stack frame associated with this event.
   Frame get topFrame;
 
@@ -113,27 +118,18 @@
   Frame get topFrame;
 }
 
-abstract class BreakpointAddedEvent extends DebugEvent {
-  /// The breakpoint which was added.
-  Breakpoint get breakpoint;
-}
+abstract class BreakpointAddedEvent extends BreakpointEvent {}
 
-abstract class BreakpointResolvedEvent extends DebugEvent {
-  /// The breakpoint which was resolved.
-  Breakpoint get breakpoint;
-}
+abstract class BreakpointResolvedEvent extends BreakpointEvent {}
 
-abstract class BreakpointRemovedEvent extends DebugEvent {
-  /// The breakpoint which was removed.
-  Breakpoint get breakpoint;
-}
+abstract class BreakpointRemovedEvent extends BreakpointEvent {}
 
 abstract class InspectEvent extends DebugEvent {
   /// The argument passed to dart:developer.inspect.
   InstanceRef get inspectee;
 }
 
-abstract class NoneEvent extends DebugEvent {}
+abstract class NoneEvent extends PauseEvent {}
 
 abstract class GCEvent extends Event {
   /// The isolate with which this event is associated.
diff --git a/runtime/observatory/lib/src/repositories/notification.dart b/runtime/observatory/lib/src/repositories/notification.dart
index 8d952d1..78a81c4 100644
--- a/runtime/observatory/lib/src/repositories/notification.dart
+++ b/runtime/observatory/lib/src/repositories/notification.dart
@@ -51,13 +51,17 @@
     if (isolate == null) {
       deleteWhere((notification) {
         return notification is M.EventNotification &&
-            M.Event.isPauseEvent(notification.event);
+            notification.event is M.PauseEvent;
       });
     } else {
       deleteWhere((notification) {
-        return notification is M.EventNotification &&
-            M.Event.isPauseEvent(notification.event) &&
-            notification.event.isolate == isolate;
+        if (notification is M.EventNotification) {
+          var event = notification.event;
+          if (event is M.PauseEvent) {
+            return event.isolate == isolate;
+          }
+        }
+        return false;
       });
     }
   }
diff --git a/runtime/observatory/lib/src/sample_profile/sample_profile.dart b/runtime/observatory/lib/src/sample_profile/sample_profile.dart
index 569d4e3..e2f71e2 100644
--- a/runtime/observatory/lib/src/sample_profile/sample_profile.dart
+++ b/runtime/observatory/lib/src/sample_profile/sample_profile.dart
@@ -134,7 +134,8 @@
   FunctionCallTreeNodeCode(this.code, this.ticks);
 }
 
-class FunctionCallTreeNode extends CallTreeNode<FunctionCallTreeNode> {
+class FunctionCallTreeNode extends CallTreeNode<FunctionCallTreeNode>
+    implements M.FunctionCallTreeNode {
   final ProfileFunction profileFunction;
   final codes = new List<FunctionCallTreeNodeCode>();
   int _totalCodeTicks = 0;
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 6c52677..58503e1 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -963,7 +963,7 @@
   Future get onConnect;
 
   /// Completes when the VM disconnects or there was an error connecting.
-  Future get onDisconnect;
+  Future<String> get onDisconnect;
 
   void _update(Map map, bool mapIsRef) {
     name = map['name'];
@@ -1047,7 +1047,7 @@
 
   /// Force the VM to disconnect.
   void disconnect() {
-    _onDisconnect.complete(this);
+    _onDisconnect.complete('Disconnected');
   }
 
   // Always connected.
@@ -1062,8 +1062,8 @@
 
   bool get isConnected => !isDisconnected;
   // Only complete when requested.
-  Completer _onDisconnect = new Completer();
-  Future get onDisconnect => _onDisconnect.future;
+  Completer<String> _onDisconnect = new Completer<String>();
+  Future<String> get onDisconnect => _onDisconnect.future;
   bool get isDisconnected => _onDisconnect.isCompleted;
 
   Future<Map> invokeRpcRaw(String method, Map params) {
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart
index 8d0c8cc..8e4ccc0 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/guarded.dart
@@ -4,7 +4,7 @@
 
 part of mocks;
 
-class GuardedMock<T> implements M.Guarded {
+class GuardedMock<T> implements M.Guarded<T> {
   bool get isSentinel => asSentinel != null;
   bool get isValue => asValue != null;
   final T asValue;
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart
index b7fc2de..2149a4f 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/ports.dart
@@ -4,16 +4,23 @@
 
 part of mocks;
 
-class PortsMock implements M.Ports {
-  final Iterable<M.Port> elements;
+class PortsAndHandlesMock implements M.Ports, M.PersistentHandles {
+  final Iterable<PortMock> elements;
 
-  const PortsMock({this.elements: const []});
+  const PortsAndHandlesMock({this.elements: const []});
+
+  @override
+  Iterable<M.WeakPersistentHandle> get weakElements =>
+      throw new UnimplementedError();
 }
 
-class PortMock implements M.Port {
+class PortMock implements M.Port, M.PersistentHandle {
   final String name;
   final M.ObjectRef handler;
 
   const PortMock(
       {this.name: 'port-name', this.handler: const InstanceRefMock()});
+
+  @override
+  M.ObjectRef get object => throw new UnimplementedError();
 }
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart
index b37b21f..518381d 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/persistent_handles.dart
@@ -14,7 +14,7 @@
     if (_getter != null) {
       return _getter(i);
     }
-    return new Future.value(new PortsMock());
+    return new Future.value(new PortsAndHandlesMock());
   }
 
   PersistentHandlesRepositoryMock(
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart
index 273d40b..8bdbe4d 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/ports.dart
@@ -13,7 +13,7 @@
     if (_getter != null) {
       return _getter(i);
     }
-    return new Future.value(new PortsMock());
+    return new Future.value(new PortsAndHandlesMock());
   }
 
   PortsRepositoryMock({PortsRepositoryMockGetter getter}) : _getter = getter;
diff --git a/runtime/observatory/tests/observatory_ui/ports/element_test.dart b/runtime/observatory/tests/observatory_ui/ports/element_test.dart
index a78a6d2..f614a53 100644
--- a/runtime/observatory/tests/observatory_ui/ports/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/ports/element_test.dart
@@ -28,7 +28,7 @@
       const PortMock(name: 'port-2'),
       const PortMock(name: 'port-3')
     ];
-    const isolatePorts = const PortsMock(elements: elements);
+    const isolatePorts = const PortsAndHandlesMock(elements: elements);
     final ports = new PortsRepositoryMock(
         getter: expectAsync((i) async {
       expect(i, equals(isolate));
diff --git a/runtime/observatory/tests/service/eval_test.dart b/runtime/observatory/tests/service/eval_test.dart
index 7753d04..8a7ff74 100644
--- a/runtime/observatory/tests/service/eval_test.dart
+++ b/runtime/observatory/tests/service/eval_test.dart
@@ -20,11 +20,18 @@
   }
 }
 
+class _MyClass {
+  void foo() {
+    debugger();
+  }
+}
+
 void testFunction() {
   int i = 0;
   while (true) {
     if (++i % 100000000 == 0) {
       MyClass.method(10000);
+      (new _MyClass()).foo();
     }
   }
 }
@@ -67,6 +74,23 @@
     result = await instance.evaluate('this + frog');
     expect(result.type, equals('Error'));
   },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(2));
+    expect(stack['frames'][0].function.name, equals('foo'));
+    expect(stack['frames'][0].function.dartOwner.name, equals('_MyClass'));
+
+    var cls = stack['frames'][0].function.dartOwner;
+
+    dynamic result = await cls.evaluate("1+1");
+    print(result);
+    expect(result.valueAsString, equals("2"));
+  }
 ];
 
 main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart b/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart
index 1ee01db..998f4bb 100644
--- a/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart
+++ b/runtime/observatory/tests/service/evaluate_function_type_parameters_test.dart
@@ -11,11 +11,11 @@
 topLevel<S>() {
   debugger();
 
-  void inner1<T>() {
+  void inner1<T>(T x) {
     debugger();
   }
 
-  inner1<int>();
+  inner1<int>(3);
 
   void inner2() {
     debugger();
@@ -64,6 +64,10 @@
     result = await isolate.evalFrame(topFrame, "S.toString()");
     print(result);
     expect(result.valueAsString, equals("String"));
+
+    result = await isolate.evalFrame(topFrame, "x");
+    print(result);
+    expect(result.valueAsString, equals("3"));
   },
   resumeIsolate,
   hasStoppedAtBreakpoint,
diff --git a/runtime/tests/vm/dart/appjit_cha_deopt_test.dart b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
new file mode 100644
index 0000000..9c6f60f
--- /dev/null
+++ b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--optimization-counter-threshold=100
+
+// Verify that app-jit snapshot contains dependencies between classes and CHA
+// optimized code.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as p;
+
+import 'snapshot_test_helper.dart';
+
+const snapshotName = 'app.jit';
+
+Future<void> main() async {
+  final Directory temp = Directory.systemTemp.createTempSync();
+  final snapshotPath = p.join(temp.path, 'app.jit');
+  final testPath = Platform.script
+      .toFilePath()
+      .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+
+  await temp.create();
+  try {
+    final trainingResult = await runDartBinary('TRAINING RUN', [
+      '--snapshot=$snapshotPath',
+      '--snapshot-kind=app-jit',
+      testPath,
+      '--train'
+    ]);
+    expectOutput("OK(Trained)", trainingResult);
+    final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
+    expectOutput("OK(Run)", runResult);
+  } finally {
+    await temp.delete(recursive: true);
+  }
+}
diff --git a/runtime/tests/vm/dart/appjit_test_body.dart b/runtime/tests/vm/dart/appjit_cha_deopt_test_body.dart
similarity index 100%
rename from runtime/tests/vm/dart/appjit_test_body.dart
rename to runtime/tests/vm/dart/appjit_cha_deopt_test_body.dart
diff --git a/runtime/tests/vm/dart/appjit_determinism_test.dart b/runtime/tests/vm/dart/appjit_determinism_test.dart
new file mode 100644
index 0000000..f5116a8
--- /dev/null
+++ b/runtime/tests/vm/dart/appjit_determinism_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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.
+
+// Verify creating an app-jit snapshot twice generates the same bits.
+
+import 'dart:async';
+import 'snapshot_test_helper.dart';
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains('--child')) {
+    print(fib(35));
+    return;
+  }
+
+  await checkDeterministicSnapshot("app-jit", "14930352");
+}
diff --git a/runtime/tests/vm/dart/appjit_test.dart b/runtime/tests/vm/dart/appjit_test.dart
deleted file mode 100644
index 6fbe998..0000000
--- a/runtime/tests/vm/dart/appjit_test.dart
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--optimization-counter-threshold=100
-
-// Verify that app-jit snapshot contains dependencies between classes and CHA
-// optimized code.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:expect/expect.dart';
-import 'package:path/path.dart' as p;
-
-class Result {
-  final String cmdline;
-  final ProcessResult processResult;
-
-  Result(this.cmdline, this.processResult);
-}
-
-void reportError(Result result, String msg) {
-  print('running ${result.cmdline}:');
-  if (result.processResult.stdout.isNotEmpty) {
-    print('''
-
-Command stdout:
-${result.processResult.stdout}''');
-  }
-
-  if (result.processResult.stderr.isNotEmpty) {
-    print('''
-
-Command stderr:
-${result.processResult.stderr}''');
-  }
-
-  Expect.fail(msg);
-}
-
-void expectOutput(String what, Result result) {
-  if (result.processResult.stdout.trim() != what) {
-    reportError(result, 'Expected test to print \'${what}\' to stdout');
-  }
-}
-
-Future<Result> runDartBinary(String prefix, List<String> arguments) async {
-  final binary = Platform.executable;
-  final actualArguments = <String>[]
-    ..addAll(Platform.executableArguments)
-    ..addAll(arguments);
-  final processResult = await Process.run(binary, actualArguments);
-  final result = new Result(
-      '[$prefix] ${binary} ${actualArguments.join(' ')}', processResult);
-  if (result.processResult.exitCode != 0) {
-    reportError(result,
-        '[$prefix] Process finished with non-zero exit code ${result.processResult.exitCode}');
-  }
-  return result;
-}
-
-const snapshotName = 'app.jit';
-
-void main() async {
-  final Directory temp = Directory.systemTemp.createTempSync();
-  final snapshotPath = p.join(temp.path, 'app.jit');
-  final testPath = Platform.script
-      .toFilePath()
-      .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
-
-  await temp.create();
-  try {
-    final trainingResult = await runDartBinary('TRAINING RUN', [
-      '--snapshot=$snapshotPath',
-      '--snapshot-kind=app-jit',
-      testPath,
-      '--train'
-    ]);
-    expectOutput("OK(Trained)", trainingResult);
-    final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
-    expectOutput("OK(Run)", runResult);
-  } finally {
-    await temp.delete(recursive: true);
-  }
-}
diff --git a/runtime/tests/vm/dart/script_determinism_test.dart b/runtime/tests/vm/dart/script_determinism_test.dart
new file mode 100644
index 0000000..4b51b4f
--- /dev/null
+++ b/runtime/tests/vm/dart/script_determinism_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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.
+
+// Verify creating a script snapshot twice generates the same bits.
+
+import 'dart:async';
+import 'snapshot_test_helper.dart';
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains('--child')) {
+    print(fib(35));
+    return;
+  }
+
+  await checkDeterministicSnapshot("script", "");
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
new file mode 100644
index 0000000..2de2bbf
--- /dev/null
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as p;
+
+class Result {
+  final String cmdline;
+  final ProcessResult processResult;
+
+  Result(this.cmdline, this.processResult);
+}
+
+void reportError(Result result, String msg) {
+  print('running ${result.cmdline}:');
+  if (result.processResult.stdout.isNotEmpty) {
+    print('''
+
+Command stdout:
+${result.processResult.stdout}''');
+  }
+
+  if (result.processResult.stderr.isNotEmpty) {
+    print('''
+
+Command stderr:
+${result.processResult.stderr}''');
+  }
+
+  Expect.fail(msg);
+}
+
+void expectOutput(String what, Result result) {
+  if (result.processResult.stdout.trim() != what) {
+    reportError(result, 'Expected test to print \'${what}\' to stdout');
+  }
+}
+
+Future<Result> runDartBinary(String prefix, List<String> arguments) async {
+  final binary = Platform.executable;
+  final actualArguments = <String>[]
+    ..addAll(Platform.executableArguments)
+    ..addAll(arguments);
+  print("+ $binary " + actualArguments.join(" "));
+  final processResult = await Process.run(binary, actualArguments);
+  final result = new Result(
+      '[$prefix] ${binary} ${actualArguments.join(' ')}', processResult);
+  if (result.processResult.exitCode != 0) {
+    reportError(result,
+        '[$prefix] Process finished with non-zero exit code ${result.processResult.exitCode}');
+  }
+  return result;
+}
+
+Future<Null> checkDeterministicSnapshot(
+    String snapshotKind, String expectedStdout) async {
+  final Directory temp = Directory.systemTemp.createTempSync();
+  final snapshot1Path = p.join(temp.path, 'snapshot1');
+  final snapshot2Path = p.join(temp.path, 'snapshot2');
+
+  try {
+    final generate1Result = await runDartBinary('GENERATE SNAPSHOT 1', [
+      '--deterministic',
+      '--snapshot=$snapshot1Path',
+      '--snapshot-kind=$snapshotKind',
+      Platform.script.toFilePath(),
+      '--child',
+    ]);
+    expectOutput(expectedStdout, generate1Result);
+
+    final generate2Result = await runDartBinary('GENERATE SNAPSHOT 2', [
+      '--deterministic',
+      '--snapshot=$snapshot2Path',
+      '--snapshot-kind=$snapshotKind',
+      Platform.script.toFilePath(),
+      '--child',
+    ]);
+    expectOutput(expectedStdout, generate2Result);
+
+    var snapshot1Bytes = await new File(snapshot1Path).readAsBytes();
+    var snapshot2Bytes = await new File(snapshot2Path).readAsBytes();
+
+    Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
+    for (var i = 0; i < snapshot1Bytes.length; i++) {
+      if (snapshot1Bytes[i] != snapshot2Bytes[i]) {
+        Expect.fail("Snapshots are not bitwise equal!");
+      }
+    }
+  } finally {
+    await temp.delete(recursive: true);
+  }
+}
diff --git a/runtime/tests/vm/dart/truncating_ints_test.dart b/runtime/tests/vm/dart/truncating_ints_test.dart
index c464457..0050383 100644
--- a/runtime/tests/vm/dart/truncating_ints_test.dart
+++ b/runtime/tests/vm/dart/truncating_ints_test.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--limit-ints-to-64-bits --enable-inlining-annotations --optimization_counter_threshold=10 --no-use-osr --no-background-compilation
+// VMOptions=--enable-inlining-annotations --optimization_counter_threshold=10 --no-use-osr --no-background-compilation
 
-// Test for truncating (wrap-around) integer arithmetic in --limit-ints-to-64-bits mode.
+// Test for truncating (wrap-around) integer arithmetic.
 
 import "package:expect/expect.dart";
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 92c4f22..df6a616 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -23,6 +23,9 @@
 [ $builder_tag == asan ]
 cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
 
+[ $builder_tag == optimization_counter_threshold ]
+dart/appjit_cha_deopt_test: SkipByDesign # Test needs to a particular opt-counter value
+
 [ $compiler == app_jit ]
 dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
 
@@ -48,12 +51,12 @@
 dart/redirection_type_shuffling_test: Skip # Depends on lazy enforcement of type bounds
 dart/simd128float32_array_test: Skip # compilers not aware of Simd128
 dart/simd128float32_test: Skip # compilers not aware of Simd128
-dart/truncating_ints_test: Skip # dart2js doesn't know about --limit-ints-to-64-bits
+dart/truncating_ints_test: SkipByDesign # The test requires int64.
 dart/wrap_around_in_range_analysis_test: SkipByDesign # The test requires int64.
 
 [ $compiler == dartk ]
 cc/DartAPI_New: Fail # Issue #33041
-cc/DartAPI_TypeGetParameterizedTypes: Crash # Issue 33042
+dart/appjit_cha_deopt_test: SkipSlow # Issue 33266
 dart/redirection_type_shuffling_test/00: RuntimeError
 dart/redirection_type_shuffling_test/none: RuntimeError
 
@@ -206,6 +209,14 @@
 cc/Service_Address: Fail
 cc/Service_Code: Fail
 
+[ $compiler == dartk && $hot_reload ]
+dart/data_uri_import_test/base64: Crash
+dart/data_uri_import_test/nocharset: Crash
+dart/data_uri_import_test/nomime: Crash
+dart/data_uri_import_test/percentencoded: Crash
+dart/data_uri_import_test/utf16: Crash
+dart/data_uri_import_test/wrongmime: Crash
+
 [ $compiler == dartk && $strong ]
 cc/DartGeneratedArrayLiteralMessages: Crash # Issue 32190
 cc/FullSnapshot1: Crash # Issue 32190
@@ -214,6 +225,11 @@
 cc/ScriptSnapshot1: Fail, Crash, OK # Script snapshots not supported in Dart 2
 cc/ScriptSnapshotsUpdateSubclasses: Fail, Crash, OK # Script snapshots not supported in Dart 2
 
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) ]
+dart/appjit_cha_deopt_test: SkipSlow # DFE too slow
+dart/appjit_determinism_test: SkipSlow # DFE too slow
+dart/script_determinism_test: SkipSlow # DFE too slow
+
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
@@ -221,8 +237,13 @@
 dart/data_uri_spawn_test: Skip # Please triage.
 dart/snapshot_version_test: RuntimeError # Please triage.
 
-[ $compiler == dartkp && !$strong ]
-dart/truncating_ints_test: Skip # This test cannot be run in dartkp/legacy mode (gen_kernel does not pass --limit-ints-to-64-bits in legacy mode).
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+dart/data_uri_spawn_test: Skip # Timeout
+
+[ $compiler != dartk && $compiler != none ]
+dart/appjit_cha_deopt_test: SkipByDesign # Test needs to run from source
+dart/appjit_determinism_test: SkipByDesign # Test needs to run from source
+dart/script_determinism_test: SkipByDesign # Test needs to run from source
 
 [ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
 dart/data_uri_import_test/utf16: MissingRuntimeError # UTF-16 data URIs work in dartk
@@ -287,9 +308,6 @@
 cc/RegExp_TwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
 cc/RegenerateAllocStubs: Skip # This test is meaningless for DBC as allocation stubs are not used.
 
-[ $arch == simdbc64 || $builder_tag == optimization_counter_threshold || $compiler != none ]
-dart/appjit_test: Skip
-
 [ $compiler == dart2analyzer || $compiler == dart2js ]
 dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 
@@ -335,6 +353,12 @@
 cc/StandaloneSnapshotSize: SkipByDesign # Imports dart:mirrors
 dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
 
+[ $system == windows || $checked ]
+dart/appjit_determinism_test: Skip # Issue 31427 - Lingering non-determinism in checked mode and Windows.
+dart/script_determinism_test: Skip # Issue 31427 - Lingering non-determinism in checked mode and Windows.
+
 [ $hot_reload || $hot_reload_rollback ]
+dart/appjit_determinism_test: Skip # Reload affects determinisim
+dart/script_determinism_test: Skip # We can shutdown an isolate before it reloads.
 dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
 dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/runtime/vm/become.cc b/runtime/vm/become.cc
index 5a79324..b6512c6 100644
--- a/runtime/vm/become.cc
+++ b/runtime/vm/become.cc
@@ -286,7 +286,8 @@
   }
 
   // C++ pointers.
-  isolate->VisitObjectPointers(&pointer_visitor, true);
+  isolate->VisitObjectPointers(&pointer_visitor,
+                               ValidationPolicy::kValidateFrames);
 #ifndef PRODUCT
   if (FLAG_support_service) {
     ObjectIdRing* ring = isolate->object_id_ring();
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index ddce675..ffd9821 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -386,7 +386,7 @@
   Timer timer(true, "LookupDartCode benchmark");
   timer.Start();
   for (int i = 0; i < kNumIterations; i++) {
-    StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+    StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* frame = frames.NextFrame();
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index b4152ff..eb76282 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -111,6 +111,7 @@
   V(RegExp_getGroupCount, 1)                                                   \
   V(RegExp_ExecuteMatch, 3)                                                    \
   V(RegExp_ExecuteMatchSticky, 3)                                              \
+  V(List_new, 2)                                                               \
   V(List_allocate, 2)                                                          \
   V(List_getIndexed, 2)                                                        \
   V(List_setIndexed, 3)                                                        \
@@ -364,6 +365,7 @@
   V(MirrorReference_equals, 2)                                                 \
   V(MirrorSystem_libraries, 0)                                                 \
   V(MirrorSystem_isolate, 0)                                                   \
+  V(IsolateMirror_loadUri, 1)                                                  \
   V(InstanceMirror_invoke, 5)                                                  \
   V(InstanceMirror_invokeGetter, 3)                                            \
   V(InstanceMirror_invokeSetter, 4)                                            \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 3d4eea8..92ba3ed 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -3223,9 +3223,11 @@
     cls.set_super_type(super_type);
   }
 
-  // If cls belongs to core lib, restrictions about allowed interfaces
-  // are lifted.
-  const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary();
+  // If cls belongs to core lib or is a synthetic class which could belong to
+  // the core library, the restrictions about allowed interfaces are lifted.
+  const bool exempt_from_hierarchy_restrictions =
+      cls.library() == Library::CoreLibrary() ||
+      String::Handle(cls.Name()).Equals(Symbols::DebugClassName());
 
   // Resolve and check the super type and interfaces of cls.
   visited->Add(cls_index);
@@ -3256,7 +3258,7 @@
 
   // If cls belongs to core lib or to core lib's implementation, restrictions
   // about allowed interfaces are lifted.
-  if (!cls_belongs_to_core_lib) {
+  if (!exempt_from_hierarchy_restrictions) {
     // Prevent extending core implementation classes.
     bool is_error = false;
     switch (interface_class.id()) {
@@ -3335,7 +3337,7 @@
     }
     // Verify that unless cls belongs to core lib, it cannot extend, implement,
     // or mixin any of Null, bool, num, int, double, String, dynamic.
-    if (!cls_belongs_to_core_lib) {
+    if (!exempt_from_hierarchy_restrictions) {
       if (interface.IsBoolType() || interface.IsNullType() ||
           interface.IsNumberType() || interface.IsIntType() ||
           interface.IsDoubleType() || interface.IsStringType() ||
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 2208c17..4cce63f 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -19,6 +19,8 @@
 #include "vm/timeline.h"
 #include "vm/version.h"
 
+#define LOG_SECTION_BOUNDARIES false
+
 namespace dart {
 
 static RawObject* AllocateUninitialized(PageSpace* old_space, intptr_t size) {
@@ -31,6 +33,10 @@
   return RawObject::FromAddr(address);
 }
 
+static bool SnapshotContainsTypeTestingStubs(Snapshot::Kind kind) {
+  return kind == Snapshot::kFullAOT || kind == Snapshot::kFullJIT;
+}
+
 void Deserializer::InitializeHeader(RawObject* raw,
                                     intptr_t class_id,
                                     intptr_t size,
@@ -49,6 +55,10 @@
 }
 
 void SerializationCluster::WriteAndMeasureAlloc(Serializer* serializer) {
+  if (LOG_SECTION_BOUNDARIES) {
+    OS::PrintErr("Data + %" Px ": Alloc %s\n", serializer->bytes_written(),
+                 name_);
+  }
   intptr_t start_size = serializer->bytes_written() + serializer->GetDataSize();
   intptr_t start_objects = serializer->next_ref_index();
   WriteAlloc(serializer);
@@ -59,6 +69,10 @@
 }
 
 void SerializationCluster::WriteAndMeasureFill(Serializer* serializer) {
+  if (LOG_SECTION_BOUNDARIES) {
+    OS::PrintErr("Data + %" Px ": Fill %s\n", serializer->bytes_written(),
+                 name_);
+  }
   intptr_t start = serializer->bytes_written();
   WriteFill(serializer);
   intptr_t stop = serializer->bytes_written();
@@ -3048,6 +3062,8 @@
 
   void WriteFill(Serializer* s) {
     const bool is_vm_isolate = s->isolate() == Dart::vm_isolate();
+    const bool should_write_type_testing_stub =
+        SnapshotContainsTypeTestingStubs(s->kind());
 
     intptr_t count = canonical_objects_.length();
     for (intptr_t i = 0; i < count; i++) {
@@ -3059,7 +3075,7 @@
       }
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int8_t>(type->ptr()->type_state_);
-      if (s->kind() == Snapshot::kFullAOT) {
+      if (should_write_type_testing_stub) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
         s->WriteInstructions(instr, Code::null());
@@ -3075,7 +3091,7 @@
       }
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int8_t>(type->ptr()->type_state_);
-      if (s->kind() == Snapshot::kFullAOT) {
+      if (should_write_type_testing_stub) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
         s->WriteInstructions(instr, Code::null());
@@ -3084,7 +3100,7 @@
 
     // The dynamic/void objects are not serialized, so we manually send
     // the type testing stub for it.
-    if (s->kind() == Snapshot::kFullAOT && is_vm_isolate) {
+    if (should_write_type_testing_stub && is_vm_isolate) {
       RawInstructions* dynamic_instr = type_testing_stubs_.LookupByAddresss(
           Type::dynamic_type().type_test_stub_entry_point());
       s->WriteInstructions(dynamic_instr, Code::null());
@@ -3127,6 +3143,8 @@
 
   void ReadFill(Deserializer* d) {
     const bool is_vm_isolate = d->isolate() == Dart::vm_isolate();
+    const bool should_read_type_testing_stub =
+        SnapshotContainsTypeTestingStubs(d->kind());
 
     for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
          id++) {
@@ -3140,7 +3158,7 @@
       }
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
-      if (d->kind() == Snapshot::kFullAOT) {
+      if (should_read_type_testing_stub) {
         instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
@@ -3158,7 +3176,7 @@
       }
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
-      if (d->kind() == Snapshot::kFullAOT) {
+      if (should_read_type_testing_stub) {
         instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
@@ -3167,7 +3185,7 @@
 
     // The dynamic/void objects are not serialized, so we manually send
     // the type testing stub for it.
-    if (d->kind() == Snapshot::kFullAOT && is_vm_isolate) {
+    if (should_read_type_testing_stub && is_vm_isolate) {
       instr_ = d->ReadInstructions();
       Type::dynamic_type().SetTypeTestingStub(instr_);
       instr_ = d->ReadInstructions();
@@ -3176,7 +3194,7 @@
   }
 
   void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
-    if (kind != Snapshot::kFullAOT) {
+    if (!SnapshotContainsTypeTestingStubs(kind)) {
       for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
            id++) {
         type_ ^= refs.At(id);
@@ -3227,6 +3245,9 @@
   }
 
   void WriteFill(Serializer* s) {
+    const bool should_write_type_testing_stub =
+        SnapshotContainsTypeTestingStubs(s->kind());
+
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeRef* type = objects_[i];
@@ -3235,7 +3256,7 @@
       for (RawObject** p = from; p <= to; p++) {
         s->WriteRef(*p);
       }
-      if (s->kind() == Snapshot::kFullAOT) {
+      if (should_write_type_testing_stub) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
         s->WriteInstructions(instr, Code::null());
@@ -3266,7 +3287,9 @@
   }
 
   void ReadFill(Deserializer* d) {
-    bool is_vm_object = d->isolate() == Dart::vm_isolate();
+    const bool is_vm_object = d->isolate() == Dart::vm_isolate();
+    const bool should_read_type_testing_stub =
+        SnapshotContainsTypeTestingStubs(d->kind());
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTypeRef* type = reinterpret_cast<RawTypeRef*>(d->Ref(id));
@@ -3277,7 +3300,7 @@
       for (RawObject** p = from; p <= to; p++) {
         *p = d->ReadRef();
       }
-      if (d->kind() == Snapshot::kFullAOT) {
+      if (should_read_type_testing_stub) {
         instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
@@ -3285,6 +3308,16 @@
     }
   }
 
+  void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+    if (!SnapshotContainsTypeTestingStubs(kind)) {
+      for (intptr_t id = start_index_; id < stop_index_; id++) {
+        type_ ^= refs.At(id);
+        instr_ = TypeTestingStubGenerator::DefaultCodeForType(type_);
+        type_.SetTypeTestingStub(instr_);
+      }
+    }
+  }
+
  private:
   AbstractType& type_;
   Instructions& instr_;
@@ -3321,6 +3354,9 @@
   }
 
   void WriteFill(Serializer* s) {
+    const bool should_write_type_testing_stub =
+        SnapshotContainsTypeTestingStubs(s->kind());
+
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeParameter* type = objects_[i];
@@ -3333,7 +3369,7 @@
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int16_t>(type->ptr()->index_);
       s->Write<int8_t>(type->ptr()->type_state_);
-      if (s->kind() == Snapshot::kFullAOT) {
+      if (should_write_type_testing_stub) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
         s->WriteInstructions(instr, Code::null());
@@ -3366,6 +3402,8 @@
 
   void ReadFill(Deserializer* d) {
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
+    const bool should_read_type_testing_stub =
+        SnapshotContainsTypeTestingStubs(d->kind());
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTypeParameter* type = reinterpret_cast<RawTypeParameter*>(d->Ref(id));
@@ -3380,7 +3418,7 @@
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->index_ = d->Read<int16_t>();
       type->ptr()->type_state_ = d->Read<int8_t>();
-      if (d->kind() == Snapshot::kFullAOT) {
+      if (should_read_type_testing_stub) {
         instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
@@ -3389,7 +3427,7 @@
   }
 
   void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
-    if (kind != Snapshot::kFullAOT) {
+    if (!SnapshotContainsTypeTestingStubs(kind)) {
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type_ ^= refs.At(id);
         instr_ = TypeTestingStubGenerator::DefaultCodeForType(type_);
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 5b2415a..414b63a 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -313,6 +313,7 @@
 
         // Start with the allocations and invocations that happen from C++.
         AddRoots(embedder_entry_points);
+        AddAnnotatedRoots();
 
         // Compile newly found targets and add their callees until we reach a
         // fixed point.
@@ -339,6 +340,7 @@
       Class& null_class = Class::Handle(Z);
       Function& null_function = Function::Handle(Z);
       I->object_store()->set_future_class(null_class);
+      I->object_store()->set_pragma_class(null_class);
       I->object_store()->set_completer_class(null_class);
       I->object_store()->set_stream_iterator_class(null_class);
       I->object_store()->set_symbol_class(null_class);
@@ -732,6 +734,8 @@
 }
 
 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) {
+  PrecompilerEntryPointsPrinter entry_points_printer(zone());
+
   // Note that <rootlibrary>.main is not a root. The appropriate main will be
   // discovered through _getMainClosure.
 
@@ -739,8 +743,6 @@
 
   AddSelector(Symbols::Call());  // For speed, not correctness.
 
-  PrecompilerEntryPointsPrinter entry_points_printer(zone());
-
   // Allocated from C++.
   Class& cls = Class::Handle(Z);
   for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) {
@@ -1505,6 +1507,61 @@
   }
 }
 
+// Adds all values annotated with @pragma('vm.entry_point') as roots.
+void Precompiler::AddAnnotatedRoots() {
+  auto& lib = Library::Handle(Z);
+  auto& cls = Class::Handle(isolate()->object_store()->pragma_class());
+  auto& functions = Array::Handle(Z);
+  auto& function = Function::Handle(Z);
+  auto& metadata = Array::Handle(Z);
+  auto& pragma = Object::Handle(Z);
+  auto& pragma_options = Object::Handle(Z);
+  auto& pragma_name_field = Field::Handle(Z, cls.LookupField(Symbols::name()));
+  auto& pragma_options_field =
+      Field::Handle(Z, cls.LookupField(Symbols::options()));
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      functions = cls.functions();
+      for (intptr_t k = 0; k < functions.Length(); k++) {
+        function ^= functions.At(k);
+        if (!function.has_pragma()) continue;
+        metadata ^= lib.GetMetadata(function);
+        if (metadata.IsNull()) continue;
+
+        bool is_entry_point = false;
+        for (intptr_t i = 0; i < metadata.Length(); i++) {
+          pragma = metadata.At(i);
+          if (pragma.clazz() != isolate()->object_store()->pragma_class()) {
+            continue;
+          }
+          if (Instance::Cast(pragma).GetField(pragma_name_field) !=
+              Symbols::vm_entry_point().raw()) {
+            continue;
+          }
+          pragma_options =
+              Instance::Cast(pragma).GetField(pragma_options_field);
+          if (pragma_options.raw() == Bool::null() ||
+              pragma_options.raw() == Bool::True().raw()) {
+            is_entry_point = true;
+            break;
+          }
+        }
+
+        if (!is_entry_point) continue;
+
+        AddFunction(function);
+        if (function.IsGenerativeConstructor()) {
+          AddInstantiatedClass(cls);
+        }
+      }
+    }
+  }
+}
+
 void Precompiler::CheckForNewDynamicFunctions() {
   Library& lib = Library::Handle(Z);
   Class& cls = Class::Handle(Z);
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 93e8326..ccbac6c 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -351,6 +351,7 @@
 
   void DoCompileAll(Dart_QualifiedFunctionName embedder_entry_points[]);
   void AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]);
+  void AddAnnotatedRoots();
   void AddEntryPoints(Dart_QualifiedFunctionName entry_points[],
                       PrecompilerEntryPointsPrinter* entry_points_printer);
   void Iterate();
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 86e7876..c418f4f 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3240,13 +3240,6 @@
     BranchLink(&StubCode::PrintStopMessage_entry()->label());
     PopList((1 << R0) | (1 << IP) | (1 << LR));  // Restore R0, IP, LR.
   }
-  // Emit the message address before the svc instruction, so that we can
-  // 'unstop' and continue execution in the simulator or jump to the next
-  // instruction in gdb.
-  Label stop;
-  b(&stop);
-  Emit(reinterpret_cast<int32_t>(message));
-  Bind(&stop);
   bkpt(Instr::kStopMessageCode);
 }
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index a322f7c..305b3a9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -221,11 +221,6 @@
   if (FLAG_print_stop_message) {
     UNIMPLEMENTED();
   }
-  Label stop;
-  b(&stop);
-  Emit(Utils::Low32Bits(reinterpret_cast<int64_t>(message)));
-  Emit(Utils::High32Bits(reinterpret_cast<int64_t>(message)));
-  Bind(&stop);
   brk(Instr::kStopMessageCode);
 }
 
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 0ba938b..ae69a35 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2320,9 +2320,6 @@
     movl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
     Call(*StubCode::PrintStopMessage_entry());  // Passing message in EAX.
     popl(EAX);                                  // Restore EAX.
-  } else {
-    // Emit the message address as immediate operand in the test instruction.
-    testl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
   }
   // Emit the int3 instruction.
   int3();  // Execution can be resumed with the 'cont' command in gdb.
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index e08f526..7bcd4a0 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1307,8 +1307,8 @@
 }
 
 void Assembler::Stop(const char* message, bool fixed_length_encoding) {
-  int64_t message_address = reinterpret_cast<int64_t>(message);
   if (FLAG_print_stop_message) {
+    int64_t message_address = reinterpret_cast<int64_t>(message);
     pushq(TMP);  // Preserve TMP register.
     pushq(RDI);  // Preserve RDI register.
     if (fixed_length_encoding) {
@@ -1322,14 +1322,6 @@
     call(&StubCode::PrintStopMessage_entry()->label());
     popq(RDI);  // Restore RDI register.
     popq(TMP);  // Restore TMP register.
-  } else {
-    // Emit the lower half and the higher half of the message address as
-    // immediate operands in the test rax instructions.
-    testl(RAX, Immediate(Utils::Low32Bits(message_address)));
-    uint32_t hi = Utils::High32Bits(message_address);
-    if (hi != 0) {
-      testl(RAX, Immediate(hi));
-    }
   }
   // Emit the int3 instruction.
   int3();  // Execution can be resumed with the 'cont' command in gdb.
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index 5c718de..491a2b4 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -656,8 +656,11 @@
           if ((instr->Bits(21, 2) == 0x1) && (instr->ConditionField() == AL)) {
             Format(instr, "bkpt #'imm12_4");
             if (instr->BkptField() == Instr::kStopMessageCode) {
-              const char* message = *reinterpret_cast<const char**>(
-                  reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+              const char* message = "Stop messages not enabled";
+              if (FLAG_print_stop_message) {
+                message = *reinterpret_cast<const char**>(
+                    reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+              }
               buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
                                             remaining_size_in_buffer(),
                                             " ; \"%s\"", message);
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index f5b49f7..14fb8a6 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -886,8 +886,11 @@
              (instr->Bits(21, 3) == 1)) {
     Format(instr, "brk 'imm16");
     if (instr->Imm16Field() == Instr::kStopMessageCode) {
-      const char* message = *reinterpret_cast<const char**>(
-          reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+      const char* message = "Stop messages not enabled";
+      if (FLAG_print_stop_message) {
+        message = *reinterpret_cast<const char**>(
+            reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+      }
       buffer_pos_ +=
           Utils::SNPrint(current_position_in_buffer(),
                          remaining_size_in_buffer(), " ; \"%s\"", message);
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 56b3878..a25530c 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -1234,8 +1234,11 @@
 #if defined(TARGET_ARCH_IA32)
   // Recognize stop pattern.
   if (*data == 0xCC) {
-    const char* text = *reinterpret_cast<const char**>(data - 4);
-    Print("  STOP:'%s'", text);
+    const char* message = "Stop messages not enabled";
+    if (FLAG_print_stop_message) {
+      message = *reinterpret_cast<const char**>(data - 4);
+    }
+    Print("  STOP:'%s'", message);
   }
 #endif
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 199e17c..187e12f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1934,7 +1934,12 @@
   }
 }
 
-void FlowGraphCompiler::GenerateAssertAssignableAOT(
+bool FlowGraphCompiler::ShouldUseTypeTestingStubFor(bool optimizing,
+                                                    const AbstractType& type) {
+  return FLAG_precompiled_mode || (optimizing && type.IsTypeParameter());
+}
+
+void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
     const AbstractType& dst_type,
     const String& dst_name,
     const Register instance_reg,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index b4123f2..8185f32 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -364,21 +364,28 @@
                                 const AbstractType& dst_type,
                                 const String& dst_name,
                                 LocationSummary* locs);
-  void GenerateAssertAssignableAOT(TokenPosition token_pos,
-                                   intptr_t deopt_id,
-                                   const AbstractType& dst_type,
-                                   const String& dst_name,
-                                   LocationSummary* locs);
 
-  void GenerateAssertAssignableAOT(const AbstractType& dst_type,
-                                   const String& dst_name,
-                                   const Register instance_reg,
-                                   const Register instantiator_type_args_reg,
-                                   const Register function_type_args_reg,
-                                   const Register subtype_cache_reg,
-                                   const Register dst_type_reg,
-                                   const Register scratch_reg,
-                                   Label* done);
+  // Returns true if we can use a type testing stub based assert
+  // assignable code pattern for the given type.
+  static bool ShouldUseTypeTestingStubFor(bool optimizing,
+                                          const AbstractType& type);
+
+  void GenerateAssertAssignableViaTypeTestingStub(TokenPosition token_pos,
+                                                  intptr_t deopt_id,
+                                                  const AbstractType& dst_type,
+                                                  const String& dst_name,
+                                                  LocationSummary* locs);
+
+  void GenerateAssertAssignableViaTypeTestingStub(
+      const AbstractType& dst_type,
+      const String& dst_name,
+      const Register instance_reg,
+      const Register instantiator_type_args_reg,
+      const Register function_type_args_reg,
+      const Register subtype_cache_reg,
+      const Register dst_type_reg,
+      const Register scratch_reg,
+      Label* done);
 
 // DBC emits calls very differently from all other architectures due to its
 // interpreted nature.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index a27e76c..e41694f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -663,7 +663,8 @@
   }
 
   if (FLAG_precompiled_mode) {
-    GenerateAssertAssignableAOT(token_pos, deopt_id, dst_type, dst_name, locs);
+    GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
+                                               dst_name, locs);
   } else {
     Label is_assignable_fast, is_assignable, runtime_call;
 
@@ -691,10 +692,11 @@
     __ PushObject(dst_name);  // Push the name of the destination.
     __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
-    GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+    __ PushObject(Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
+    GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // type check runtime call is the checked value.
-    __ Drop(6);
+    __ Drop(7);
     __ Pop(R0);
     __ Bind(&is_assignable);
     __ PopList((1 << kFunctionTypeArgumentsReg) |
@@ -703,7 +705,7 @@
   }
 }
 
-void FlowGraphCompiler::GenerateAssertAssignableAOT(
+void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
     TokenPosition token_pos,
     intptr_t deopt_id,
     const AbstractType& dst_type,
@@ -719,10 +721,10 @@
 
   Label done;
 
-  GenerateAssertAssignableAOT(dst_type, dst_name, kInstanceReg,
-                              kInstantiatorTypeArgumentsReg,
-                              kFunctionTypeArgumentsReg, kSubtypeTestCacheReg,
-                              kDstTypeReg, kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(
+      dst_type, dst_name, kInstanceReg, kInstantiatorTypeArgumentsReg,
+      kFunctionTypeArgumentsReg, kSubtypeTestCacheReg, kDstTypeReg, kScratchReg,
+      &done);
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
   // but it will be used by the code throwing a TypeError if the type test fails
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index c76e56d..a74cec8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -643,8 +643,9 @@
     return;
   }
 
-  if (FLAG_precompiled_mode) {
-    GenerateAssertAssignableAOT(token_pos, deopt_id, dst_type, dst_name, locs);
+  if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
+    GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
+                                               dst_name, locs);
   } else {
     Label is_assignable_fast, is_assignable, runtime_call;
 
@@ -669,10 +670,11 @@
     __ PushObject(dst_name);  // Push the name of the destination.
     __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
-    GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+    __ PushObject(Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
+    GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // type check runtime call is the checked value.
-    __ Drop(6);
+    __ Drop(7);
     __ Pop(R0);
     __ Bind(&is_assignable);
     __ PopPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
@@ -680,7 +682,7 @@
   }
 }
 
-void FlowGraphCompiler::GenerateAssertAssignableAOT(
+void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
     TokenPosition token_pos,
     intptr_t deopt_id,
     const AbstractType& dst_type,
@@ -696,10 +698,10 @@
 
   Label done;
 
-  GenerateAssertAssignableAOT(dst_type, dst_name, kInstanceReg,
-                              kInstantiatorTypeArgumentsReg,
-                              kFunctionTypeArgumentsReg, kSubtypeTestCacheReg,
-                              kDstTypeReg, kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(
+      dst_type, dst_name, kInstanceReg, kInstantiatorTypeArgumentsReg,
+      kFunctionTypeArgumentsReg, kSubtypeTestCacheReg, kDstTypeReg, kScratchReg,
+      &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 0580e5c..f19eea3 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -686,10 +686,11 @@
   __ PushObject(dst_name);  // Push the name of the destination.
   __ LoadObject(EAX, test_cache);
   __ pushl(EAX);
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+  __ PushObject(Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
+  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
-  __ Drop(6);
+  __ Drop(7);
   __ popl(EAX);
 
   __ Bind(&is_assignable);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 4a2c58b..0ef54a5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -654,8 +654,9 @@
     return;
   }
 
-  if (FLAG_precompiled_mode) {
-    GenerateAssertAssignableAOT(token_pos, deopt_id, dst_type, dst_name, locs);
+  if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
+    GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
+                                               dst_name, locs);
   } else {
     Label is_assignable, runtime_call;
 
@@ -678,16 +679,17 @@
     __ PushObject(dst_name);  // Push the name of the destination.
     __ LoadUniqueObject(RAX, test_cache);
     __ pushq(RAX);
-    GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+    __ PushObject(Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
+    GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // type check runtime call is the checked value.
-    __ Drop(6);
+    __ Drop(7);
     __ popq(RAX);
     __ Bind(&is_assignable);
   }
 }
 
-void FlowGraphCompiler::GenerateAssertAssignableAOT(
+void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
     TokenPosition token_pos,
     intptr_t deopt_id,
     const AbstractType& dst_type,
@@ -702,10 +704,10 @@
   const Register subtype_cache_reg = R9;
   const Register kScratchReg = RBX;
 
-  GenerateAssertAssignableAOT(dst_type, dst_name, kInstanceReg,
-                              kInstantiatorTypeArgumentsReg,
-                              kFunctionTypeArgumentsReg, subtype_cache_reg,
-                              kScratchReg, kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(
+      dst_type, dst_name, kInstanceReg, kInstantiatorTypeArgumentsReg,
+      kFunctionTypeArgumentsReg, subtype_cache_reg, kScratchReg, kScratchReg,
+      &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 3d7b61d..e9a04e7 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -396,31 +396,45 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  // In AOT mode, we want to prevent spilling of the function/instantiator type
-  // argument vectors, since we preserve them.  So we make this a `kNoCall`
-  // summary.  Though most other registers can be modified by the type testing
-  // stubs we are calling.  To tell the register allocator about it, we reserve
+  // When using a type testing stub, we want to prevent spilling of the
+  // function/instantiator type argument vectors, since stub preserves them. So
+  // we make this a `kNoCall` summary, even though most other registers can be
+  // modified by the stub. To tell the register allocator about it, we reserve
   // all the other registers as temporary registers.
   // TODO(http://dartbug.com/32788): Simplify this.
   const Register kInstanceReg = R0;
   const Register kInstantiatorTypeArgumentsReg = R2;
   const Register kFunctionTypeArgumentsReg = R1;
 
+  const bool using_stub =
+      FlowGraphCompiler::ShouldUseTypeTestingStubFor(opt, dst_type());
+
   const intptr_t kNonChangeableInputRegs =
       (1 << kInstanceReg) | (1 << kInstantiatorTypeArgumentsReg) |
       (1 << kFunctionTypeArgumentsReg);
 
   const intptr_t kNumInputs = 3;
 
-  const intptr_t kNumTemps =
-      FLAG_precompiled_mode ? (Utils::CountOneBits64(kDartAvailableCpuRegs) -
-                               Utils::CountOneBits64(kNonChangeableInputRegs))
-                            : 0;
+  // We invoke a stub that can potentially clobber any CPU register
+  // but can only clobber FPU registers on the slow path when
+  // entering runtime. Preserve all FPU registers that are
+  // not guarateed to be preserved by the ABI.
+  const intptr_t kCpuRegistersToPreserve =
+      kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
+  const intptr_t kFpuRegistersToPreserve =
+      Utils::SignedNBitMask(kNumberOfFpuRegisters) &
+      ~(Utils::SignedNBitMask(kAbiPreservedFpuRegCount)
+        << kAbiFirstPreservedFpuReg) &
+      ~(1 << FpuTMP);
 
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps,
-                      FLAG_precompiled_mode ? LocationSummary::kCallCalleeSafe
-                                            : LocationSummary::kCall);
+  const intptr_t kNumTemps =
+      using_stub ? (Utils::CountOneBits64(kCpuRegistersToPreserve) +
+                    Utils::CountOneBits64(kFpuRegistersToPreserve))
+                 : 0;
+
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      using_stub ? LocationSummary::kCallCalleeSafe : LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(kInstanceReg));  // Value.
   summary->set_in(1,
                   Location::RegisterLocation(
@@ -432,17 +446,24 @@
   // once register allocator no longer hits assertion.
   summary->set_out(0, Location::RegisterLocation(kInstanceReg));
 
-  if (FLAG_precompiled_mode) {
+  if (using_stub) {
     // Let's reserve all registers except for the input ones.
     intptr_t next_temp = 0;
     for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-      const bool is_allocatable = ((1 << i) & kDartAvailableCpuRegs) != 0;
-      const bool is_input = ((1 << i) & kNonChangeableInputRegs) != 0;
-      if (is_allocatable && !is_input) {
+      const bool should_preserve = ((1 << i) & kCpuRegistersToPreserve) != 0;
+      if (should_preserve) {
         summary->set_temp(next_temp++,
                           Location::RegisterLocation(static_cast<Register>(i)));
       }
     }
+
+    for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+      const bool should_preserve = ((1 << i) & kFpuRegistersToPreserve) != 0;
+      if (should_preserve) {
+        summary->set_temp(next_temp++, Location::FpuRegisterLocation(
+                                           static_cast<FpuRegister>(i)));
+      }
+    }
   }
 
   return summary;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 9a9bc82..204dd69 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -394,31 +394,43 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  // In AOT mode, we want to prevent spilling of the function/instantiator type
-  // argument vectors, since we preserve them.  So we make this a `kNoCall`
-  // summary.  Though most other registers can be modified by the type testing
-  // stubs we are calling.  To tell the register allocator about it, we reserve
+  // When using a type testing stub, we want to prevent spilling of the
+  // function/instantiator type argument vectors, since stub preserves them. So
+  // we make this a `kNoCall` summary, even though most other registers can be
+  // modified by the stub. To tell the register allocator about it, we reserve
   // all the other registers as temporary registers.
   // TODO(http://dartbug.com/32788): Simplify this.
   const Register kInstanceReg = R0;
   const Register kInstantiatorTypeArgumentsReg = R1;
   const Register kFunctionTypeArgumentsReg = R2;
 
+  const bool using_stub =
+      FlowGraphCompiler::ShouldUseTypeTestingStubFor(opt, dst_type());
+
   const intptr_t kNonChangeableInputRegs =
       (1 << kInstanceReg) | (1 << kInstantiatorTypeArgumentsReg) |
       (1 << kFunctionTypeArgumentsReg);
 
   const intptr_t kNumInputs = 3;
 
-  const intptr_t kNumTemps =
-      FLAG_precompiled_mode ? (Utils::CountOneBits64(kDartAvailableCpuRegs) -
-                               Utils::CountOneBits64(kNonChangeableInputRegs))
-                            : 0;
+  // We invoke a stub that can potentially clobber any CPU register
+  // but can only clobber FPU registers on the slow path when
+  // entering runtime. ARM64 ABI only guarantees that lower
+  // 64-bits of an V registers are preserved so we block all
+  // of them except for FpuTMP.
+  const intptr_t kCpuRegistersToPreserve =
+      kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
+  const intptr_t kFpuRegistersToPreserve =
+      Utils::SignedNBitMask(kNumberOfFpuRegisters) & ~(1l << FpuTMP);
 
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps,
-                      FLAG_precompiled_mode ? LocationSummary::kCallCalleeSafe
-                                            : LocationSummary::kCall);
+  const intptr_t kNumTemps =
+      using_stub ? (Utils::CountOneBits64(kCpuRegistersToPreserve) +
+                    Utils::CountOneBits64(kFpuRegistersToPreserve))
+                 : 0;
+
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      using_stub ? LocationSummary::kCallCalleeSafe : LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(kInstanceReg));  // Value.
   summary->set_in(1,
                   Location::RegisterLocation(
@@ -430,17 +442,24 @@
   // once register allocator no longer hits assertion.
   summary->set_out(0, Location::RegisterLocation(kInstanceReg));
 
-  if (FLAG_precompiled_mode) {
+  if (using_stub) {
     // Let's reserve all registers except for the input ones.
     intptr_t next_temp = 0;
     for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-      const bool is_allocatable = ((1 << i) & kDartAvailableCpuRegs) != 0;
-      const bool is_input = ((1 << i) & kNonChangeableInputRegs) != 0;
-      if (is_allocatable && !is_input) {
+      const bool should_preserve = ((1 << i) & kCpuRegistersToPreserve) != 0;
+      if (should_preserve) {
         summary->set_temp(next_temp++,
                           Location::RegisterLocation(static_cast<Register>(i)));
       }
     }
+
+    for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+      const bool should_preserve = ((1l << i) & kFpuRegistersToPreserve) != 0;
+      if (should_preserve) {
+        summary->set_temp(next_temp++, Location::FpuRegisterLocation(
+                                           static_cast<FpuRegister>(i)));
+      }
+    }
   }
 
   return summary;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index cbbd640..aeb619b 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -362,31 +362,42 @@
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
                                                             bool opt) const {
-  // In AOT mode, we want to prevent spilling of the function/instantiator type
-  // argument vectors, since we preserve them.  So we make this a `kNoCall`
-  // summary.  Though most other registers can be modified by the type testing
-  // stubs we are calling.  To tell the register allocator about it, we reserve
+  // When using a type testing stub, we want to prevent spilling of the
+  // function/instantiator type argument vectors, since stub preserves them. So
+  // we make this a `kNoCall` summary, even though most other registers can be
+  // modified by the stub. To tell the register allocator about it, we reserve
   // all the other registers as temporary registers.
   // TODO(http://dartbug.com/32788): Simplify this.
   const Register kInstanceReg = RAX;
   const Register kInstantiatorTypeArgumentsReg = RDX;
   const Register kFunctionTypeArgumentsReg = RCX;
 
+  const bool using_stub =
+      FlowGraphCompiler::ShouldUseTypeTestingStubFor(opt, dst_type());
+
   const intptr_t kNonChangeableInputRegs =
       (1 << kInstanceReg) | (1 << kInstantiatorTypeArgumentsReg) |
       (1 << kFunctionTypeArgumentsReg);
 
   const intptr_t kNumInputs = 3;
 
-  const intptr_t kNumTemps =
-      FLAG_precompiled_mode ? (Utils::CountOneBits64(kDartAvailableCpuRegs) -
-                               Utils::CountOneBits64(kNonChangeableInputRegs))
-                            : 0;
+  // We invoke a stub that can potentially clobber any CPU register
+  // but can only clobber FPU registers on the slow path when
+  // entering runtime. Preserve all FPU registers that are
+  // not guarateed to be preserved by the ABI.
+  const intptr_t kCpuRegistersToPreserve =
+      kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
+  const intptr_t kFpuRegistersToPreserve =
+      CallingConventions::kVolatileXmmRegisters & ~(1 << FpuTMP);
 
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps,
-                      FLAG_precompiled_mode ? LocationSummary::kCallCalleeSafe
-                                            : LocationSummary::kCall);
+  const intptr_t kNumTemps =
+      using_stub ? (Utils::CountOneBits64(kCpuRegistersToPreserve) +
+                    Utils::CountOneBits64(kFpuRegistersToPreserve))
+                 : 0;
+
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      using_stub ? LocationSummary::kCallCalleeSafe : LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(kInstanceReg));  // Value.
   summary->set_in(1,
                   Location::RegisterLocation(
@@ -398,17 +409,24 @@
   // once register allocator no longer hits assertion.
   summary->set_out(0, Location::RegisterLocation(kInstanceReg));
 
-  if (FLAG_precompiled_mode) {
+  if (using_stub) {
     // Let's reserve all registers except for the input ones.
     intptr_t next_temp = 0;
     for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-      const bool is_allocatable = ((1 << i) & kDartAvailableCpuRegs) != 0;
-      const bool is_input = ((1 << i) & kNonChangeableInputRegs) != 0;
-      if (is_allocatable && !is_input) {
+      const bool should_preserve = ((1 << i) & kCpuRegistersToPreserve) != 0;
+      if (should_preserve) {
         summary->set_temp(next_temp++,
                           Location::RegisterLocation(static_cast<Register>(i)));
       }
     }
+
+    for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+      const bool should_preserve = ((1 << i) & kFpuRegistersToPreserve) != 0;
+      if (should_preserve) {
+        summary->set_temp(next_temp++, Location::FpuRegisterLocation(
+                                           static_cast<FpuRegister>(i)));
+      }
+    }
   }
 
   return summary;
@@ -4394,8 +4412,7 @@
     __ jmp(&done, Assembler::kNearJump);
 
     __ Bind(&returns_nan);
-    static double kNaN = NAN;
-    __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN)));
+    __ movq(temp, Address(THR, Thread::double_nan_address_offset()));
     __ movsd(result, Address(temp, 0));
     __ jmp(&done, Assembler::kNearJump);
 
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 9e2bd30..5512de8 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2605,51 +2605,55 @@
                                          intptr_t view_cid,
                                          Definition** array,
                                          Definition* byte_index,
-                                         Instruction** cursor) {
-  LoadFieldInstr* length = new (Z) LoadFieldInstr(
-      new (Z) Value(*array), CheckArrayBoundInstr::LengthOffsetFor(array_cid),
-      Type::ZoneHandle(Z, Type::SmiType()), call->token_pos());
-  length->set_is_immutable(true);
-  length->set_result_cid(kSmiCid);
-  length->set_recognized_kind(
-      LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
-  *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue);
+                                         Instruction** cursor,
+                                         bool needs_bounds_check) {
+  if (needs_bounds_check) {
+    LoadFieldInstr* length = new (Z) LoadFieldInstr(
+        new (Z) Value(*array), CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+        Type::ZoneHandle(Z, Type::SmiType()), call->token_pos());
+    length->set_is_immutable(true);
+    length->set_result_cid(kSmiCid);
+    length->set_recognized_kind(
+        LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+    *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue);
 
-  intptr_t element_size = Instance::ElementSizeFor(array_cid);
-  ConstantInstr* bytes_per_element =
-      flow_graph->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
-  BinarySmiOpInstr* len_in_bytes = new (Z)
-      BinarySmiOpInstr(Token::kMUL, new (Z) Value(length),
-                       new (Z) Value(bytes_per_element), call->deopt_id());
-  *cursor = flow_graph->AppendTo(*cursor, len_in_bytes, call->env(),
-                                 FlowGraph::kValue);
-
-  // adjusted_length = len_in_bytes - (element_size - 1).
-  Definition* adjusted_length = len_in_bytes;
-  intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
-  if (adjustment > 0) {
-    ConstantInstr* length_adjustment =
-        flow_graph->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
-    adjusted_length = new (Z)
-        BinarySmiOpInstr(Token::kSUB, new (Z) Value(len_in_bytes),
-                         new (Z) Value(length_adjustment), call->deopt_id());
-    *cursor = flow_graph->AppendTo(*cursor, adjusted_length, call->env(),
+    intptr_t element_size = Instance::ElementSizeFor(array_cid);
+    ConstantInstr* bytes_per_element =
+        flow_graph->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
+    BinarySmiOpInstr* len_in_bytes = new (Z)
+        BinarySmiOpInstr(Token::kMUL, new (Z) Value(length),
+                         new (Z) Value(bytes_per_element), call->deopt_id());
+    *cursor = flow_graph->AppendTo(*cursor, len_in_bytes, call->env(),
                                    FlowGraph::kValue);
-  }
 
-  // Check adjusted_length > 0.
-  ConstantInstr* zero = flow_graph->GetConstant(Smi::Handle(Z, Smi::New(0)));
-  *cursor = flow_graph->AppendTo(
-      *cursor,
-      new (Z) CheckArrayBoundInstr(new (Z) Value(adjusted_length),
-                                   new (Z) Value(zero), call->deopt_id()),
-      call->env(), FlowGraph::kEffect);
-  // Check 0 <= byte_index < adjusted_length.
-  *cursor = flow_graph->AppendTo(
-      *cursor,
-      new (Z) CheckArrayBoundInstr(new (Z) Value(adjusted_length),
-                                   new (Z) Value(byte_index), call->deopt_id()),
-      call->env(), FlowGraph::kEffect);
+    // adjusted_length = len_in_bytes - (element_size - 1).
+    Definition* adjusted_length = len_in_bytes;
+    intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
+    if (adjustment > 0) {
+      ConstantInstr* length_adjustment =
+          flow_graph->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
+      adjusted_length = new (Z)
+          BinarySmiOpInstr(Token::kSUB, new (Z) Value(len_in_bytes),
+                           new (Z) Value(length_adjustment), call->deopt_id());
+      *cursor = flow_graph->AppendTo(*cursor, adjusted_length, call->env(),
+                                     FlowGraph::kValue);
+    }
+
+    // Check adjusted_length > 0.
+    ConstantInstr* zero = flow_graph->GetConstant(Smi::Handle(Z, Smi::New(0)));
+    *cursor = flow_graph->AppendTo(
+        *cursor,
+        new (Z) CheckArrayBoundInstr(new (Z) Value(adjusted_length),
+                                     new (Z) Value(zero), call->deopt_id()),
+        call->env(), FlowGraph::kEffect);
+    // Check 0 <= byte_index < adjusted_length.
+    *cursor = flow_graph->AppendTo(
+        *cursor,
+        new (Z)
+            CheckArrayBoundInstr(new (Z) Value(adjusted_length),
+                                 new (Z) Value(byte_index), call->deopt_id()),
+        call->env(), FlowGraph::kEffect);
+  }
 
   if (RawObject::IsExternalTypedDataClassId(array_cid)) {
     LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
@@ -2679,8 +2683,13 @@
   (*entry)->InheritDeoptTarget(Z, call);
   Instruction* cursor = *entry;
 
+  // All getters that go through InlineByteArrayBaseLoad() have explicit
+  // bounds checks in all their clients in the library, so we can omit
+  // yet another inlined bounds check when compiling for Dart2.
+  const bool needs_bounds_check = !FLAG_strong;
+
   PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array,
-                               index, &cursor);
+                               index, &cursor, needs_bounds_check);
 
   intptr_t deopt_id = Thread::kNoDeoptId;
   if ((array_cid == kTypedDataInt32ArrayCid) ||
@@ -2726,8 +2735,13 @@
   (*entry)->InheritDeoptTarget(Z, call);
   Instruction* cursor = *entry;
 
+  // All setters that go through InlineByteArrayBaseStore() have explicit
+  // bounds checks in all their clients in the library, so we can omit
+  // yet another inlined bounds check when compiling for Dart2.
+  const bool needs_bounds_check = !FLAG_strong;
+
   PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array,
-                               index, &cursor);
+                               index, &cursor, needs_bounds_check);
 
   Cids* value_check = NULL;
   switch (view_cid) {
@@ -3502,6 +3516,28 @@
       return true;
     }
 
+    case MethodRecognizer::kListFactory: {
+      // We only want to inline new List(n) which decreases code size and
+      // improves performance. We don't want to inline new List().
+      if (call->ArgumentCount() != 2) {
+        return false;
+      }
+
+      const auto type = new (Z) Value(call->ArgumentAt(0));
+      const auto num_elements = new (Z) Value(call->ArgumentAt(1));
+      *entry = new (Z)
+          TargetEntryInstr(flow_graph->allocate_block_id(),
+                           call->GetBlock()->try_index(), Thread::kNoDeoptId);
+      (*entry)->InheritDeoptTarget(Z, call);
+      *last = new (Z) CreateArrayInstr(call->token_pos(), type, num_elements,
+                                       call->deopt_id());
+      flow_graph->AppendTo(
+          *entry, *last,
+          call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
+          FlowGraph::kValue);
+      return true;
+    }
+
     case MethodRecognizer::kObjectArrayAllocate: {
       Value* num_elements = new (Z) Value(call->ArgumentAt(1));
       if (num_elements->BindsToConstant() &&
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index aa65f19..e7ecaac 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -3247,6 +3247,87 @@
         length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength);
         return ReturnDefinition(length_load);
       }
+      case MethodRecognizer::kListFactory: {
+        // factory List<E>([int length]) {
+        //   return (:arg_desc.positional_count == 2) ? new _List<E>(length)
+        //                                            : new _GrowableList<E>(0);
+        // }
+        ASSERT(owner_->parsed_function().has_arg_desc_var());
+        const auto type_args_parameter = node->scope()->LookupVariable(
+            Symbols::TypeArgumentsParameter(), true);
+        const auto length_parameter =
+            node->scope()->LookupVariable(Symbols::Length(), true);
+        const Library& core_lib = Library::Handle(Z, Library::CoreLibrary());
+
+        // Build: :arg_desc.positional_count == 2
+        TestGraphVisitor comparison(owner(), token_pos);
+        auto arg_descriptor = comparison.Bind(new (Z) LoadLocalInstr(
+            *owner_->parsed_function().arg_desc_var(), token_pos));
+        auto positional_count = comparison.Bind(new (Z) LoadFieldInstr(
+            arg_descriptor, ArgumentsDescriptor::positional_count_offset(),
+            AbstractType::ZoneHandle(Z, Type::SmiType()), token_pos));
+        auto constant_1 = comparison.Bind(
+            new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(2))));
+        comparison.ReturnDefinition(new (Z) StrictCompareInstr(
+            token_pos, Token::kEQ_STRICT, positional_count, constant_1, false,
+            owner()->GetNextDeoptId()));  // No number check.
+
+        // Build: :expr_temp = new _List<E>(length)
+        ValueGraphVisitor allocate_non_growable(owner());
+        {
+          auto arguments = new (Z) ZoneGrowableArray<PushArgumentInstr*>(Z, 2);
+          arguments->Add(
+              allocate_non_growable.PushArgument(allocate_non_growable.Bind(
+                  new (Z) LoadLocalInstr(*type_args_parameter, token_pos))));
+          arguments->Add(
+              allocate_non_growable.PushArgument(allocate_non_growable.Bind(
+                  new (Z) LoadLocalInstr(*length_parameter, token_pos))));
+          const Class& cls = Class::Handle(
+              Z, core_lib.LookupClass(
+                     Library::PrivateCoreLibName(Symbols::_List())));
+          ASSERT(!cls.IsNull());
+          const intptr_t kTypeArgsLen = 0;
+          const Function& func = Function::ZoneHandle(
+              Z, cls.LookupFactoryAllowPrivate(Symbols::_ListFactory()));
+          ASSERT(!func.IsNull());
+          allocate_non_growable.ReturnDefinition(new (Z) StaticCallInstr(
+              token_pos, func, kTypeArgsLen,
+              Object::null_array(),  // No names.
+              arguments, owner()->ic_data_array(), owner()->GetNextDeoptId(),
+              ICData::kStatic));
+          allocate_non_growable.Do(
+              BuildStoreExprTemp(allocate_non_growable.value(), token_pos));
+        }
+
+        // Build: :expr_temp = new _GrowableList<E>(0)
+        ValueGraphVisitor allocate_growable(owner());
+        {
+          auto arguments = new (Z) ZoneGrowableArray<PushArgumentInstr*>(Z, 1);
+          arguments->Add(allocate_growable.PushArgument(allocate_growable.Bind(
+              new (Z) LoadLocalInstr(*type_args_parameter, token_pos))));
+          arguments->Add(allocate_growable.PushArgument(allocate_growable.Bind(
+              new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(0))))));
+          const Class& cls = Class::Handle(
+              Z, core_lib.LookupClass(
+                     Library::PrivateCoreLibName(Symbols::_GrowableList())));
+          ASSERT(!cls.IsNull());
+          const intptr_t kTypeArgsLen = 0;
+          const Function& func = Function::ZoneHandle(
+              Z,
+              cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory()));
+          ASSERT(!func.IsNull());
+          allocate_growable.ReturnDefinition(new (Z) StaticCallInstr(
+              token_pos, func, kTypeArgsLen,
+              Object::null_array(),  // No names.
+              arguments, owner()->ic_data_array(), owner()->GetNextDeoptId(),
+              ICData::kStatic));
+          allocate_growable.Do(
+              BuildStoreExprTemp(allocate_growable.value(), token_pos));
+        }
+
+        Join(comparison, allocate_non_growable, allocate_growable);
+        return ReturnDefinition(BuildLoadExprTemp(token_pos));
+      }
       case MethodRecognizer::kObjectArrayAllocate: {
         LocalVariable* type_args_parameter = node->scope()->LookupVariable(
             Symbols::TypeArgumentsParameter(), true);
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.h b/runtime/vm/compiler/frontend/flow_graph_builder.h
index f737103..057cf56 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.h
@@ -492,6 +492,8 @@
   Value* value_;
 
  private:
+  friend class EffectGraphVisitor;
+
   // Helper to set the output state to return a Value.
   virtual void ReturnValue(Value* value) { value_ = value; }
 
@@ -539,6 +541,8 @@
   TokenPosition condition_token_pos() const { return condition_token_pos_; }
 
  private:
+  friend class EffectGraphVisitor;
+
   // Construct and concatenate a Branch instruction to this graph fragment.
   // Closes the fragment and sets the output parameters.
   virtual void ReturnValue(Value* value);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 93d70f3..501c73f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3894,11 +3894,12 @@
 
   const AbstractType& type = T.BuildType();
   if (!type.IsInstantiated() || type.IsMalformed()) {
+    const String& type_str = String::Handle(type.UserVisibleName());
     H.ReportError(
         script_, TokenPosition::kNoSource,
         "Not a constant expression: right hand side of an implicit "
         "as-expression is expected to be an instantiated type, got %s",
-        type.ToCString());
+        type_str.ToCString());
   }
 
   const TypeArguments& instantiator_type_arguments = TypeArguments::Handle();
@@ -3906,9 +3907,13 @@
   Error& error = Error::Handle();
   if (!result_.IsInstanceOf(type, instantiator_type_arguments,
                             function_type_arguments, &error)) {
+    const AbstractType& rtype =
+        AbstractType::Handle(result_.GetType(Heap::kNew));
+    const String& result_str = String::Handle(rtype.UserVisibleName());
+    const String& type_str = String::Handle(type.UserVisibleName());
     H.ReportError(script_, TokenPosition::kNoSource,
                   "Not a constant expression: %s is not an instance of %s",
-                  result_.ToCString(), type.ToCString());
+                  result_str.ToCString(), type_str.ToCString());
   }
 }
 
@@ -5955,9 +5960,8 @@
         bound = forwarding_param.bound();
       }
 
-      if (I->strong() && !bound.IsObjectType() &&
+      if (I->strong() && !bound.IsObjectType() && !bound.IsDynamicType() &&
           (I->reify_generic_functions() || dart_function.IsFactory())) {
-        ASSERT(!bound.IsDynamicType());
         TypeParameter& param = TypeParameter::Handle(Z);
         if (dart_function.IsFactory()) {
           param ^= TypeArguments::Handle(
@@ -11097,10 +11101,10 @@
   intptr_t list_length = ReadListLength();  // read list length.
   const Array& metadata_values =
       Array::Handle(Z, Array::New(list_length, H.allocation_space()));
+  Instance& value = Instance::Handle(Z);
   for (intptr_t i = 0; i < list_length; ++i) {
     // this will (potentially) read the expression, but reset the position.
-    Instance& value = Instance::ZoneHandle(
-        Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
+    value = constant_evaluator_.EvaluateExpression(ReaderOffset());
     SkipExpression();  // read (actual) initializer.
     metadata_values.SetAt(i, value);
   }
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 34aa36e..73619a7 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -2135,6 +2135,71 @@
                               Array::length_offset(),
                               Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
       break;
+    case MethodRecognizer::kListFactory: {
+      // factory List<E>([int length]) {
+      //   return (:arg_desc.positional_count == 2) ? new _List<E>(length)
+      //                                            : new _GrowableList<E>(0);
+      // }
+      const Library& core_lib = Library::Handle(Z, Library::CoreLibrary());
+
+      TargetEntryInstr *allocate_non_growable, *allocate_growable;
+
+      body += LoadArgDescriptor();
+      body +=
+          LoadField(ArgumentsDescriptor::positional_count_offset(), kSmiCid);
+      body += IntConstant(2);
+      body += BranchIfStrictEqual(&allocate_non_growable, &allocate_growable);
+
+      JoinEntryInstr* join = BuildJoinEntry();
+
+      {
+        const Class& cls = Class::Handle(
+            Z, core_lib.LookupClass(
+                   Library::PrivateCoreLibName(Symbols::_List())));
+        ASSERT(!cls.IsNull());
+        const Function& func = Function::ZoneHandle(
+            Z, cls.LookupFactoryAllowPrivate(Symbols::_ListFactory()));
+        ASSERT(!func.IsNull());
+
+        Fragment allocate(allocate_non_growable);
+        allocate += LoadLocal(scopes_->type_arguments_variable);
+        allocate += PushArgument();
+        allocate += LoadLocal(LookupVariable(first_positional_offset));
+        allocate += PushArgument();
+        allocate +=
+            StaticCall(TokenPosition::kNoSource, func, 2, ICData::kStatic);
+        allocate += StoreLocal(TokenPosition::kNoSource,
+                               parsed_function_->expression_temp_var());
+        allocate += Drop();
+        allocate += Goto(join);
+      }
+
+      {
+        const Class& cls = Class::Handle(
+            Z, core_lib.LookupClass(
+                   Library::PrivateCoreLibName(Symbols::_GrowableList())));
+        ASSERT(!cls.IsNull());
+        const Function& func = Function::ZoneHandle(
+            Z, cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory()));
+        ASSERT(!func.IsNull());
+
+        Fragment allocate(allocate_growable);
+        allocate += LoadLocal(scopes_->type_arguments_variable);
+        allocate += PushArgument();
+        allocate += IntConstant(0);
+        allocate += PushArgument();
+        allocate +=
+            StaticCall(TokenPosition::kNoSource, func, 2, ICData::kStatic);
+        allocate += StoreLocal(TokenPosition::kNoSource,
+                               parsed_function_->expression_temp_var());
+        allocate += Drop();
+        allocate += Goto(join);
+      }
+
+      body = Fragment(body.entry, join);
+      body += LoadLocal(parsed_function_->expression_temp_var());
+      break;
+    }
     case MethodRecognizer::kObjectArrayAllocate:
       body += LoadLocal(scopes_->type_arguments_variable);
       body += LoadLocal(LookupVariable(first_positional_offset));
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index afffc77..6f97c60 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -19,6 +19,7 @@
   V(::, identical, ObjectIdentical, Bool, 0x49c6e96a)                          \
   V(ClassID, getID, ClassIDgetID, Smi, 0x7b18b257)                             \
   V(Object, Object., ObjectConstructor, Dynamic, 0x681617fe)                   \
+  V(List, ., ListFactory, Dynamic, 0x629f8324)                                 \
   V(_List, ., ObjectArrayAllocate, Array, 0x2121902f)                          \
   V(_TypedList, _getInt8, ByteArrayBaseGetInt8, Smi, 0x7041895a)               \
   V(_TypedList, _getUint8, ByteArrayBaseGetUint8, Smi, 0x336fa3ea)             \
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 02fa964..88854cd 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -791,8 +791,6 @@
   }
 }
 
-// TODO(turnidge): This clones Api::NewError.  I need to use va_copy to
-// fix this but not sure if it available on all of our builds.
 DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
   DARTSCOPE(Thread::Current());
   CHECK_CALLBACK_STATE(T);
@@ -801,6 +799,14 @@
   return Api::NewHandle(T, ApiError::New(message));
 }
 
+DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error) {
+  DARTSCOPE(Thread::Current());
+  CHECK_CALLBACK_STATE(T);
+
+  const String& message = String::Handle(Z, String::New(error));
+  return Api::NewHandle(T, LanguageError::New(message));
+}
+
 DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception) {
   DARTSCOPE(Thread::Current());
   CHECK_CALLBACK_STATE(T);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 52bd15c..5867cf5 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3618,22 +3618,26 @@
       "Type getMyClass1_1Type() {\n"
       "  return new MyClass1<List<int>, List<double>>().runtimeType;\n"
       "}\n";
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-  bool instanceOf = false;
+
+  Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
+  EXPECT_VALID(corelib);
 
   // First get type objects of some of the basic types used in the test.
-  Dart_Handle int_type = Dart_GetType(lib, NewString("int"), 0, NULL);
+  Dart_Handle int_type = Dart_GetType(corelib, NewString("int"), 0, NULL);
   EXPECT_VALID(int_type);
-  Dart_Handle double_type = Dart_GetType(lib, NewString("double"), 0, NULL);
+  Dart_Handle double_type = Dart_GetType(corelib, NewString("double"), 0, NULL);
   EXPECT_VALID(double_type);
-  Dart_Handle list_type = Dart_GetType(lib, NewString("List"), 0, NULL);
+  Dart_Handle list_type = Dart_GetType(corelib, NewString("List"), 0, NULL);
   EXPECT_VALID(list_type);
   Dart_Handle type_args = Dart_NewList(1);
   EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
   Dart_Handle list_int_type =
-      Dart_GetType(lib, NewString("List"), 1, &type_args);
+      Dart_GetType(corelib, NewString("List"), 1, &type_args);
   EXPECT_VALID(list_int_type);
 
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  bool instanceOf = false;
+
   // Now instantiate MyClass0 and MyClass1 types with the same type arguments
   // used in the code above.
   type_args = Dart_NewList(2);
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 15ab7b8..2d50aad 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -438,7 +438,7 @@
   descriptor.SetAt(kCountIndex, arg_count);
 
   // Set number of positional arguments.
-  descriptor.SetAt(kPositionalCountIndex, Smi::Handle(Smi::New(num_arguments)));
+  descriptor.SetAt(kPositionalCountIndex, arg_count);
 
   // Set terminating null.
   descriptor.SetAt((descriptor_len - 1), Object::null_object());
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 00cc771..f6587d6 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -674,7 +674,7 @@
   DisassembleToStdout formatter;
   code().Disassemble(&formatter);
   PcDescriptors::Handle(code().pc_descriptors()).Print();
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
@@ -1174,7 +1174,7 @@
   OS::PrintErr(
       "-------------------------\n"
       "All frames...\n\n");
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
@@ -1872,7 +1872,7 @@
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
   DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   Code& code = Code::Handle(zone);
@@ -1961,7 +1961,7 @@
   // asynchronous function. We truncate the remainder of the synchronous
   // stack trace because it contains activations that are part of the
   // asynchronous dispatch mechanisms.
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
@@ -2028,7 +2028,7 @@
   Isolate* isolate = thread->isolate();
   DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
 
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
 
@@ -2199,7 +2199,7 @@
 }
 
 ActivationFrame* Debugger::TopDartFrame() const {
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
@@ -3440,7 +3440,7 @@
       OS::PrintErr(
           "-------------------------\n"
           "All frames...\n\n");
-      StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+      StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                                   Thread::Current(),
                                   StackFrameIterator::kNoCrossThreadIteration);
       StackFrame* frame = iterator.NextFrame();
@@ -3558,7 +3558,7 @@
   Function& function = Function::Handle(zone);
 
   // Find the requested frame.
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   intptr_t current_frame = 0;
@@ -3659,7 +3659,7 @@
     OS::PrintErr(
         "-------------------------\n"
         "All frames...\n\n");
-    StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+    StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                                 Thread::Current(),
                                 StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* frame = iterator.NextFrame();
@@ -3674,7 +3674,7 @@
   Zone* zone = thread->zone();
   Code& code = Code::Handle(zone);
 
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   intptr_t current_frame = 0;
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index b4bcec3..c5bfcce 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -122,7 +122,7 @@
 }
 
 static void BuildStackTrace(StackTraceBuilder* builder) {
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
@@ -163,7 +163,7 @@
   // can continue in that frame. Sets 'needs_stacktrace' if there is no
   // cath-all handler or if a stack-trace is specified in the catch.
   bool Find() {
-    StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+    StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* frame = frames.NextFrame();
@@ -342,7 +342,7 @@
 static void FindErrorHandler(uword* handler_pc,
                              uword* handler_sp,
                              uword* handler_fp) {
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
diff --git a/runtime/vm/gc_compactor.cc b/runtime/vm/gc_compactor.cc
index 4aec300..b10d0b6 100644
--- a/runtime/vm/gc_compactor.cc
+++ b/runtime/vm/gc_compactor.cc
@@ -556,7 +556,7 @@
   // N.B.: Heap pointers have already been forwarded. We forward the heap before
   // forwarding the stack to limit the number of places that need to be aware of
   // forwarding when reading stack maps.
-  isolate()->VisitObjectPointers(this, StackFrameIterator::kDontValidateFrames);
+  isolate()->VisitObjectPointers(this, ValidationPolicy::kDontValidateFrames);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index fd0ee4e..21aa17d 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -475,7 +475,7 @@
   ASSERT(0 <= slice_index && slice_index < num_slices);
   if ((slice_index == 0) || (num_slices <= 1)) {
     isolate->VisitObjectPointers(visitor,
-                                 StackFrameIterator::kDontValidateFrames);
+                                 ValidationPolicy::kDontValidateFrames);
   }
   if ((slice_index == 1) || (num_slices <= 1)) {
     heap_->new_space()->VisitObjectPointers(visitor);
diff --git a/runtime/vm/gdb_helpers.cc b/runtime/vm/gdb_helpers.cc
index a15676c..44ba132 100644
--- a/runtime/vm/gdb_helpers.cc
+++ b/runtime/vm/gdb_helpers.cc
@@ -35,7 +35,7 @@
 // in the middle of a GC or interested in stub frames.
 DART_EXPORT
 void _printStackTrace() {
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
@@ -60,7 +60,7 @@
 DART_EXPORT
 void _printStackTraceWithLocals() {
   PrintObjectPointersVisitor visitor;
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 7468e02..905ba26 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -29,6 +29,8 @@
 
 namespace dart {
 
+DEFINE_FLAG(bool, write_protect_vm_isolate, true, "Write protect vm_isolate.");
+
 Heap::Heap(Isolate* isolate,
            intptr_t max_new_gen_semi_words,
            intptr_t max_old_gen_words,
@@ -138,9 +140,12 @@
   } else {
     ASSERT(space == kOld);
     old_space_.AllocateExternal(cid, size);
-    if (old_space_.NeedsGarbageCollection()) {
-      CollectAllGarbage();
-    }
+  }
+  // Idle GC does not check whether promotions should trigger a full GC.
+  // As a workaround, we check here on every external allocation. See issue
+  // dartbug.com/33314.
+  if (old_space_.NeedsGarbageCollection()) {
+    CollectAllGarbage();
   }
 }
 
@@ -262,13 +267,15 @@
   Dart::vm_isolate()->heap()->VisitObjects(visitor);
 }
 
-void HeapIterationScope::IterateObjectPointers(ObjectPointerVisitor* visitor,
-                                               bool validate_frames) {
+void HeapIterationScope::IterateObjectPointers(
+    ObjectPointerVisitor* visitor,
+    ValidationPolicy validate_frames) {
   isolate()->VisitObjectPointers(visitor, validate_frames);
 }
 
-void HeapIterationScope::IterateStackPointers(ObjectPointerVisitor* visitor,
-                                              bool validate_frames) {
+void HeapIterationScope::IterateStackPointers(
+    ObjectPointerVisitor* visitor,
+    ValidationPolicy validate_frames) {
   isolate()->VisitStackPointers(visitor, validate_frames);
 }
 
@@ -878,12 +885,16 @@
 
 WritableVMIsolateScope::WritableVMIsolateScope(Thread* thread)
     : StackResource(thread) {
-  Dart::vm_isolate()->heap()->WriteProtect(false);
+  if (FLAG_write_protect_vm_isolate) {
+    Dart::vm_isolate()->heap()->WriteProtect(false);
+  }
 }
 
 WritableVMIsolateScope::~WritableVMIsolateScope() {
   ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0);
-  Dart::vm_isolate()->heap()->WriteProtect(true);
+  if (FLAG_write_protect_vm_isolate) {
+    Dart::vm_isolate()->heap()->WriteProtect(true);
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 79e81b2..9678e61 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -384,9 +384,9 @@
   void IterateVMIsolateObjects(ObjectVisitor* visitor) const;
 
   void IterateObjectPointers(ObjectPointerVisitor* visitor,
-                             bool validate_frames);
+                             ValidationPolicy validate_frames);
   void IterateStackPointers(ObjectPointerVisitor* visitor,
-                            bool validate_frames);
+                            ValidationPolicy validate_frames);
 
  private:
   Heap* heap_;
diff --git a/runtime/vm/instructions.h b/runtime/vm/instructions.h
index e0ec51f..eb39a5d 100644
--- a/runtime/vm/instructions.h
+++ b/runtime/vm/instructions.h
@@ -28,7 +28,7 @@
 
 bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj);
 
-#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC)
 
 class TypeTestingStubCallPattern : public ValueObject {
  public:
@@ -40,7 +40,7 @@
   const uword pc_;
 };
 
-#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC)
 
 }  // namespace dart
 
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index f62215f..38dbee5 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -285,8 +285,6 @@
   return false;
 }
 
-#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
-
 intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
   // Calls to the type testing stubs look like:
   //   ldr R3, [PP+idx]
@@ -304,8 +302,6 @@
   return pool_index;
 }
 
-#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index f728ffd..a08eda0 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -351,8 +351,6 @@
   return bx_lr->InstructionBits() == instruction;
 }
 
-#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
-
 intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
   // Calls to the type testing stubs look like:
   //   ldr R3, [PP+idx]
@@ -370,8 +368,6 @@
   return pool_index;
 }
 
-#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM64
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 3c63a75..4765a52 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -64,8 +64,6 @@
   return false;
 }
 
-#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
-
 intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
   const intptr_t kCallPatternSize = 10;
   static int16_t pattern[kCallPatternSize] = {
@@ -78,8 +76,6 @@
   return IndexFromPPLoad(start + 3);
 }
 
-#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_X64
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index d8b68f7..dba91ad 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -3368,8 +3368,9 @@
       SP[4] = args[2];  // function type args
       SP[5] = args[4];  // name
       SP[6] = cache;
-      Exit(thread, FP, SP + 7, pc);
-      NativeArguments native_args(thread, 6, SP + 1, SP - 4);
+      SP[7] = Smi::New(kTypeCheckFromInline);
+      Exit(thread, FP, SP + 8, pc);
+      NativeArguments native_args(thread, 7, SP + 1, SP - 4);
       INVOKE_RUNTIME(DRT_TypeCheck, native_args);
     }
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index d927ba9..c00b259 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -84,13 +84,15 @@
 
 static void DeterministicModeHandler(bool value) {
   if (value) {
-    FLAG_background_compilation = false;
-    FLAG_collect_code = false;
+    FLAG_background_compilation = false;  // Timing dependent.
+    FLAG_collect_code = false;            // Timing dependent.
     FLAG_random_seed = 0x44617274;  // "Dart"
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
     FLAG_load_deferred_eagerly = true;
+    FLAG_print_stop_message = false;  // Embedds addresses in instructions.
 #else
     COMPILE_ASSERT(FLAG_load_deferred_eagerly);
+    COMPILE_ASSERT(!FLAG_print_stop_message);
 #endif
   }
 }
@@ -1845,6 +1847,7 @@
 
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_check_reloaded && is_runnable() && (this != Dart::vm_isolate()) &&
+      !KernelIsolate::IsKernelIsolate(this) &&
       !ServiceIsolate::IsServiceIsolateDescendant(this)) {
     if (!HasAttemptedReload()) {
       FATAL(
@@ -1885,7 +1888,7 @@
 bool Isolate::creation_enabled_ = false;
 
 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
-                                  bool validate_frames) {
+                                  ValidationPolicy validate_frames) {
   ASSERT(visitor != NULL);
 
   // Visit objects in the object store.
@@ -1963,7 +1966,7 @@
 }
 
 void Isolate::VisitStackPointers(ObjectPointerVisitor* visitor,
-                                 bool validate_frames) {
+                                 ValidationPolicy validate_frames) {
   // Visit objects in all threads (e.g., Dart stack, handles in zones).
   thread_registry()->VisitObjectPointers(visitor, validate_frames);
 }
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 6584382..2dad860 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -791,8 +791,10 @@
 
   // Visit all object pointers. Caller must ensure concurrent sweeper is not
   // running, and the visitor must not allocate.
-  void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
-  void VisitStackPointers(ObjectPointerVisitor* visitor, bool validate_frames);
+  void VisitObjectPointers(ObjectPointerVisitor* visitor,
+                           ValidationPolicy validate_frames);
+  void VisitStackPointers(ObjectPointerVisitor* visitor,
+                          ValidationPolicy validate_frames);
 
   void set_user_tag(uword tag) { user_tag_ = tag; }
 
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index b8f24ef..4832667 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -854,7 +854,7 @@
 
 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() {
   TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack);
-  StackFrameIterator it(StackFrameIterator::kDontValidateFrames,
+  StackFrameIterator it(ValidationPolicy::kDontValidateFrames,
                         Thread::Current(),
                         StackFrameIterator::kNoCrossThreadIteration);
 
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index cc0b1e6c..bdba931 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -162,7 +162,6 @@
     }
 
     ASSERT(KernelIsolate::IsKernelIsolate(I));
-    KernelIsolate::SetKernelIsolate(NULL);
     KernelIsolate::SetLoadPort(ILLEGAL_PORT);
 
     // Shut the isolate down.
@@ -170,6 +169,9 @@
     if (FLAG_trace_kernel) {
       OS::Print(DART_KERNEL_ISOLATE_NAME ": Shutdown.\n");
     }
+    // This should be the last line so the check
+    // IsKernelIsolate works during the shutdown process.
+    KernelIsolate::SetKernelIsolate(NULL);
   }
 
   bool RunMain(Isolate* I) {
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index e7f45d2..e473239 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -416,6 +416,7 @@
             native_name ^= constant.GetField(external_name_field_);
             function.set_is_native(true);
             function.set_native_name(native_name);
+            function.set_is_external(false);
             break;
           }
         } else {
@@ -432,23 +433,14 @@
   ASSERT(constant_table.Release().raw() == constant_table_array.raw());
 }
 
-RawString* KernelLoader::DetectExternalName() {
+RawString* KernelLoader::DetectExternalNameCtor() {
   builder_.ReadTag();
   builder_.ReadPosition();
   NameIndex annotation_class = H.EnclosingName(
       builder_.ReadCanonicalNameReference());  // read target reference,
-  ASSERT(H.IsClass(annotation_class));
-  StringIndex class_name_index = H.CanonicalNameString(annotation_class);
 
-  // Just compare by name, do not generate the annotation class.
-  if (!H.StringEquals(class_name_index, "ExternalName")) {
-    builder_.SkipArguments();
-    return String::null();
-  }
-  ASSERT(H.IsLibrary(H.CanonicalNameParent(annotation_class)));
-  StringIndex library_name_index =
-      H.CanonicalNameString(H.CanonicalNameParent(annotation_class));
-  if (!H.StringEquals(library_name_index, "dart:_internal")) {
+  if (!IsClassName(annotation_class, Symbols::DartInternal(),
+                   Symbols::ExternalName())) {
     builder_.SkipArguments();
     return String::null();
   }
@@ -471,6 +463,30 @@
   return result.raw();
 }
 
+bool KernelLoader::IsClassName(NameIndex name,
+                               const String& library,
+                               const String& klass) {
+  ASSERT(H.IsClass(name));
+  StringIndex class_name_index = H.CanonicalNameString(name);
+
+  if (!H.StringEquals(class_name_index, klass.ToCString())) {
+    return false;
+  }
+  ASSERT(H.IsLibrary(H.CanonicalNameParent(name)));
+  StringIndex library_name_index =
+      H.CanonicalNameString(H.CanonicalNameParent(name));
+  return H.StringEquals(library_name_index, library.ToCString());
+}
+
+bool KernelLoader::DetectPragmaCtor() {
+  builder_.ReadTag();
+  builder_.ReadPosition();
+  NameIndex annotation_class = H.EnclosingName(
+      builder_.ReadCanonicalNameReference());  // read target reference
+  builder_.SkipArguments();
+  return IsClassName(annotation_class, Symbols::DartCore(), Symbols::Pragma());
+}
+
 void KernelLoader::LoadNativeExtensionLibraries(
     const Array& constant_table_array) {
   const intptr_t length = !potential_extension_libraries_.IsNull()
@@ -510,7 +526,7 @@
         }
       } else if (tag == kConstructorInvocation ||
                  tag == kConstConstructorInvocation) {
-        uri_path = DetectExternalName();
+        uri_path = DetectExternalNameCtor();
       } else {
         builder_.SkipExpression();
       }
@@ -1292,6 +1308,106 @@
                                    class_index, &class_helper);
 }
 
+// Read annotations on a procedure to identify potential VM-specific directives.
+//
+// Output parameters:
+//
+//   `native_name`: non-null if `ExternalName(<name>)` was identified.
+//
+//   `is_potential_native`: non-null if there may be an `ExternalName`
+//   annotation and we need to re-try after reading the constants table.
+//
+//   `has_pragma_annotation`: non-null if @pragma(...) was found (no information
+//   is given on the kind of pragma directive).
+//
+void KernelLoader::ReadProcedureAnnotations(intptr_t annotation_count,
+                                            String* native_name,
+                                            bool* is_potential_native,
+                                            bool* has_pragma_annotation) {
+  *is_potential_native = false;
+  *has_pragma_annotation = false;
+  String& detected_name = String::Handle(Z);
+  Class& pragma_class = Class::Handle(Z, I->object_store()->pragma_class());
+  for (intptr_t i = 0; i < annotation_count; ++i) {
+    const intptr_t tag = builder_.PeekTag();
+    if (tag == kConstructorInvocation || tag == kConstConstructorInvocation) {
+      const intptr_t start = builder_.ReaderOffset();
+      detected_name = DetectExternalNameCtor();
+      if (!detected_name.IsNull()) {
+        *native_name = detected_name.raw();
+        continue;
+      }
+
+      builder_.SetOffset(start);
+      if (DetectPragmaCtor()) {
+        *has_pragma_annotation = true;
+      }
+    } else if (tag == kConstantExpression) {
+      const Array& constant_table_array =
+          Array::Handle(kernel_program_info_.constants());
+      if (constant_table_array.IsNull()) {
+        // We can only read in the constant table once all classes have been
+        // finalized (otherwise we can't create instances of the classes!).
+        //
+        // We therefore delay the scanning for `ExternalName {name: ... }`
+        // constants in the annotation list to later.
+        *is_potential_native = true;
+
+        if (program_ == nullptr) {
+          builder_.SkipExpression();
+          continue;
+        }
+
+        // For pragma annotations, we seek into the constants table and peek
+        // into the Kernel representation of the constant.
+        //
+        // TODO(sjindel): Refactor `ExternalName` handling to do this as well
+        // and avoid the "potential natives" list.
+
+        builder_.ReadByte();  // Skip the tag.
+
+        const intptr_t offset_in_constant_table = builder_.ReadUInt();
+
+        AlternativeReadingScope scope(&builder_.reader_,
+                                      program_->constant_table_offset());
+
+        // Seek into the position within the constant table where we can inspect
+        // this constant's Kernel representation.
+        builder_.ReadUInt();  // skip constant table size
+        builder_.SetOffset(builder_.ReaderOffset() + offset_in_constant_table);
+        uint8_t tag = builder_.ReadTag();
+        if (tag == kInstanceConstant) {
+          *has_pragma_annotation =
+              IsClassName(builder_.ReadCanonicalNameReference(),
+                          Symbols::DartCore(), Symbols::Pragma());
+        }
+      } else {
+        KernelConstantsMap constant_table(constant_table_array.raw());
+        builder_.ReadByte();  // Skip the tag.
+
+        // Obtain `dart:_internal::ExternalName.name`.
+        EnsureExternalClassIsLookedUp();
+
+        const intptr_t constant_table_index = builder_.ReadUInt();
+        const Object& constant =
+            Object::Handle(constant_table.GetOrDie(constant_table_index));
+        if (constant.clazz() == external_name_class_.raw()) {
+          const Instance& instance =
+              Instance::Handle(Instance::RawCast(constant.raw()));
+          *native_name =
+              String::RawCast(instance.GetField(external_name_field_));
+        } else if (constant.clazz() == pragma_class.raw()) {
+          *has_pragma_annotation = true;
+        }
+        ASSERT(constant_table.Release().raw() == constant_table_array.raw());
+      }
+    } else {
+      builder_.SkipExpression();
+      continue;
+    }
+  }
+}
+
 void KernelLoader::LoadProcedure(const Library& library,
                                  const Class& owner,
                                  bool in_class,
@@ -1308,78 +1424,16 @@
   bool is_method = in_class && !procedure_helper.IsStatic();
   bool is_abstract = procedure_helper.IsAbstract();
   bool is_external = procedure_helper.IsExternal();
-  String* native_name = NULL;
-  intptr_t annotation_count;
-  bool is_potential_native = false;
-  if (is_external) {
-    // Maybe it has a native implementation, which is not external as far as
-    // the VM is concerned because it does have an implementation.  Check for
-    // an ExternalName annotation and extract the string from it.
-    annotation_count = builder_.ReadListLength();  // read list length.
-    for (int i = 0; i < annotation_count; ++i) {
-      const intptr_t tag = builder_.PeekTag();
-      if (tag == kConstructorInvocation || tag == kConstConstructorInvocation) {
-        String& detected_name = String::Handle(DetectExternalName());
-        if (detected_name.IsNull()) continue;
-
-        is_external = false;
-        native_name = &detected_name;
-
-        // Skip remaining annotations
-        for (++i; i < annotation_count; ++i) {
-          builder_.SkipExpression();  // read ith annotation.
-        }
-      } else if (tag == kConstantExpression) {
-        if (kernel_program_info_.constants() == Array::null()) {
-          // We can only read in the constant table once all classes have been
-          // finalized (otherwise we can't create instances of the classes!).
-          //
-          // We therefore delay the scanning for `ExternalName {name: ... }`
-          // constants in the annotation list to later.
-          is_potential_native = true;
-          builder_.SkipExpression();
-        } else {
-          builder_.ReadByte();  // Skip the tag.
-
-          // Obtain `dart:_internal::ExternalName.name`.
-          EnsureExternalClassIsLookedUp();
-
-          const Array& constant_table_array =
-              Array::Handle(kernel_program_info_.constants());
-          KernelConstantsMap constant_table(constant_table_array.raw());
-
-          // We have a candiate.  Let's look if it's an instance of the
-          // ExternalName class.
-          const intptr_t constant_table_index = builder_.ReadUInt();
-          const Object& constant =
-              Object::Handle(constant_table.GetOrDie(constant_table_index));
-          ASSERT(constant_table.Release().raw() == constant_table_array.raw());
-          if (constant.clazz() == external_name_class_.raw()) {
-            const Instance& instance =
-                Instance::Handle(Instance::RawCast(constant.raw()));
-
-            // We found the annotation, let's flag the function as native and
-            // set the native name!
-            native_name = &String::Handle(
-                String::RawCast(instance.GetField(external_name_field_)));
-
-            // Skip remaining annotations
-            for (++i; i < annotation_count; ++i) {
-              builder_.SkipExpression();  // read ith annotation.
-            }
-            break;
-          }
-        }
-      } else {
-        builder_.SkipExpression();
-        continue;
-      }
-    }
-    procedure_helper.SetJustRead(ProcedureHelper::kAnnotations);
-  } else {
-    procedure_helper.ReadUntilIncluding(ProcedureHelper::kAnnotations);
-    annotation_count = procedure_helper.annotation_count_;
-  }
+  String& native_name = String::Handle(Z);
+  bool is_potential_native;
+  bool has_pragma_annotation;
+  const intptr_t annotation_count = builder_.ReadListLength();
+  ReadProcedureAnnotations(annotation_count, &native_name, &is_potential_native,
+                           &has_pragma_annotation);
+  // If this is a potential native, we'll unset is_external in
+  // AnnotateNativeProcedures instead.
+  is_external = is_external && native_name.IsNull();
+  procedure_helper.SetJustRead(ProcedureHelper::kAnnotations);
   const Object& script_class =
       ClassForScriptAt(owner, procedure_helper.source_uri_index_);
   RawFunction::Kind kind = GetFunctionType(procedure_helper.kind_);
@@ -1388,8 +1442,9 @@
                        !is_method,  // is_static
                        false,       // is_const
                        is_abstract, is_external,
-                       native_name != NULL,  // is_native
+                       !native_name.IsNull(),  // is_native
                        script_class, procedure_helper.position_));
+  function.set_has_pragma(has_pragma_annotation);
   function.set_end_token_pos(procedure_helper.end_position_);
   functions_.Add(&function);
   function.set_kernel_offset(procedure_offset);
@@ -1430,8 +1485,8 @@
   }
   ASSERT(function_node_helper.async_marker_ == FunctionNodeHelper::kSync);
 
-  if (native_name != NULL) {
-    function.set_native_name(*native_name);
+  if (!native_name.IsNull()) {
+    function.set_native_name(native_name);
   }
   if (is_potential_native) {
     EnsurePotentialNatives();
@@ -1455,7 +1510,7 @@
                 .IsNull());
   }
 
-  if (FLAG_enable_mirrors && annotation_count > 0) {
+  if (annotation_count > 0) {
     library.AddFunctionMetadata(function, TokenPosition::kNoSource,
                                 procedure_offset);
   }
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index 21f4bb2..b8a70a9 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -142,10 +142,26 @@
   static void FinishLoading(const Class& klass);
 
   const Array& ReadConstantTable();
-  RawString* DetectExternalName();
+
+  // Check for the presence of a (possibly const) constructor for the
+  // 'ExternalName' class. If found, returns the name parameter to the
+  // constructor.
+  RawString* DetectExternalNameCtor();
+
+  // Check for the presence of a (possibly const) constructor for the 'pragma'
+  // class. Returns whether it was found (no details about the type of pragma).
+  bool DetectPragmaCtor();
+
+  bool IsClassName(NameIndex name, const String& library, const String& klass);
+
   void AnnotateNativeProcedures(const Array& constant_table);
   void LoadNativeExtensionLibraries(const Array& constant_table);
 
+  void ReadProcedureAnnotations(intptr_t annotation_count,
+                                String* native_name,
+                                bool* is_potential_native,
+                                bool* has_pragma_annotation);
+
   const String& DartSymbolPlain(StringIndex index) {
     return translation_helper_.DartSymbolPlain(index);
   }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d379d22..ed6ecb1 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7067,9 +7067,11 @@
                            Heap::Space space) {
   ASSERT(!owner.IsNull() || (kind == RawFunction::kSignatureFunction));
   const Function& result = Function::Handle(Function::New(space));
+  result.set_kind_tag(0);
   result.set_parameter_types(Object::empty_array());
   result.set_parameter_names(Object::empty_array());
   result.set_name(name);
+  result.set_kind_tag(0);  // Ensure determinism of uninitialized bits.
   result.set_kind(kind);
   result.set_recognized_kind(MethodRecognizer::kUnknown);
   result.set_modifier(RawFunction::kNoModifier);
@@ -7084,6 +7086,7 @@
   result.set_is_intrinsic(false);
   result.set_is_redirecting(false);
   result.set_is_generated_body(false);
+  result.set_has_pragma(false);
   result.set_always_inline(false);
   result.set_is_polymorphic_target(false);
   NOT_IN_PRECOMPILED(result.set_state_bits(0));
@@ -11548,7 +11551,8 @@
   // Load the program with the debug procedure as a regular, independent
   // program.
   kernel::KernelLoader loader(kernel_pgm);
-  loader.LoadProgram();
+  const Object& result = Object::Handle(loader.LoadProgram());
+  if (result.IsError()) return result.raw();
   ASSERT(I->class_table()->NumCids() > num_cids &&
          GrowableObjectArray::Handle(I->object_store()->libraries()).Length() ==
              num_libs + 1);
@@ -11562,7 +11566,7 @@
       String::New(Symbols::Symbol(Symbols::kDebugProcedureNameId)));
   Class& fake_class = Class::Handle();
   if (!klass.IsNull()) {
-    fake_class = loaded.LookupClass(String::Handle(String::New(klass)));
+    fake_class = loaded.LookupClass(Symbols::DebugClassName());
     ASSERT(!fake_class.IsNull());
     callee = fake_class.LookupFunctionAllowPrivate(debug_name);
   } else {
@@ -11584,7 +11588,7 @@
   ASSERT(!real_library.IsNull());
   Class& real_class = Class::Handle();
   if (!klass.IsNull()) {
-    real_class = real_library.LookupClass(String::Handle(String::New(klass)));
+    real_class = real_library.LookupClassAllowPrivate(klass);
   } else {
     real_class = real_library.toplevel_class();
   }
@@ -11617,7 +11621,7 @@
     real_arguments.SetAt(i + 1, arg);
   }
   const Array& args_desc = Array::Handle(
-      ArgumentsDescriptor::New(num_type_args, real_arguments.Length()));
+      ArgumentsDescriptor::New(num_type_args, arguments.Length()));
   return DartEntry::InvokeFunction(callee, real_arguments, args_desc);
 #endif
 }
@@ -18243,6 +18247,8 @@
   cloned_ref_type = ref_type.CloneUninstantiated(new_owner, trail);
   ASSERT(!cloned_ref_type.IsTypeRef());
   cloned_type_ref.set_type(cloned_ref_type);
+  cloned_type_ref.SetTypeTestingStub(Instructions::Handle(
+      TypeTestingStubGenerator::DefaultCodeForType(cloned_type_ref)));
   return cloned_type_ref.raw();
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ee04799..41efcde 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2884,7 +2884,8 @@
   V(External, is_external)                                                     \
   V(GeneratedBody, is_generated_body)                                          \
   V(AlwaysInline, always_inline)                                               \
-  V(PolymorphicTarget, is_polymorphic_target)
+  V(PolymorphicTarget, is_polymorphic_target)                                  \
+  V(HasPragma, has_pragma)
 
 #define DEFINE_ACCESSORS(name, accessor_name)                                  \
   void set_##accessor_name(bool value) const {                                 \
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 727857a..6a56a57 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -207,7 +207,7 @@
 
 void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) {
   Stack stack(isolate());
-  isolate()->VisitObjectPointers(&stack, false);
+  isolate()->VisitObjectPointers(&stack, ValidationPolicy::kDontValidateFrames);
   stack.TraverseGraph(visitor);
   Unmarker::UnmarkAll(isolate());
 }
@@ -642,7 +642,8 @@
     // Write root "object".
     WriteHeader(kRootAddress, 0, kRootCid, stream);
     WritePointerVisitor ptr_writer(isolate(), stream, false);
-    isolate()->VisitObjectPointers(&ptr_writer, false);
+    isolate()->VisitObjectPointers(&ptr_writer,
+                                   ValidationPolicy::kDontValidateFrames);
     stream->WriteUnsigned(0);
   } else {
     {
@@ -658,7 +659,8 @@
       // Write stack "object".
       WriteHeader(kStackAddress, 0, kStackCid, stream);
       WritePointerVisitor ptr_writer(isolate(), stream, true);
-      isolate()->VisitStackPointers(&ptr_writer, false);
+      isolate()->VisitStackPointers(&ptr_writer,
+                                    ValidationPolicy::kDontValidateFrames);
       stream->WriteUnsigned(0);
     }
   }
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 2d62110..e2d676d 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -220,6 +220,10 @@
   ASSERT(!cls.IsNull());
   set_compiletime_error_class(cls);
 
+  cls = core_lib.LookupClassAllowPrivate(Symbols::Pragma());
+  ASSERT(!cls.IsNull());
+  set_pragma_class(cls);
+
   // Cache the core private functions used for fast instance of checks.
   simple_instance_of_function_ =
       PrivateObjectLookup(Symbols::_simpleInstanceOf());
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 891760f..5c9e90f 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -56,6 +56,7 @@
   RW(TypeArguments, type_argument_string)                                      \
   RW(TypeArguments, type_argument_int)                                         \
   RW(Class, compiletime_error_class)                                           \
+  RW(Class, pragma_class)                                                      \
   RW(Class, future_class)                                                      \
   RW(Class, completer_class)                                                   \
   RW(Class, stream_iterator_class)                                             \
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 727542f..6284307 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -44,7 +44,7 @@
                                                  int32_t* local_offset,
                                                  int32_t* dst_offset) {
   time_zone::TimezoneSyncPtr time_svc;
-  component::ConnectToEnvironmentService(time_svc.NewRequest());
+  fuchsia::sys::ConnectToEnvironmentService(time_svc.NewRequest());
   if (!time_svc->GetTimezoneOffsetMinutes(seconds_since_epoch * 1000,
                                           local_offset, dst_offset))
     return ZX_ERR_UNAVAILABLE;
@@ -57,7 +57,7 @@
   // TODO(abarth): Handle time zone changes.
   static const auto* tz_name = new std::string([] {
     time_zone::TimezoneSyncPtr time_svc;
-    component::ConnectToEnvironmentService(time_svc.NewRequest());
+    fuchsia::sys::ConnectToEnvironmentService(time_svc.NewRequest());
     fidl::StringPtr result;
     time_svc->GetTimezoneId(&result);
     return *result;
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 169b5c9..a73de36 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -45,6 +45,7 @@
             "Generate jitdump file to use with perf-inject");
 
 DECLARE_FLAG(bool, write_protect_code);
+DECLARE_FLAG(bool, write_protect_vm_isolate);
 
 // Linux CodeObservers.
 
@@ -122,7 +123,7 @@
       : out_file_(nullptr), mapped_(nullptr), mapped_size_(0), code_id_(0) {
     const intptr_t pid = getpid();
     char* const filename = OS::SCreate(nullptr, "/tmp/jit-%" Pd ".dump", pid);
-    const int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR);
+    const int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666);
     free(filename);
 
     if (fd == -1) {
@@ -155,9 +156,11 @@
     // writing all JIT generated code out.
     setvbuf(out_file_, nullptr, _IOFBF, 2 * MB);
 
-    // Disable code write protection, constant flickering of page attributes
+    // Disable code write protection and vm isolate write protection, because
+    // calling mprotect on the pages filled with JIT generated code objects
     // confuses perf.
     FLAG_write_protect_code = false;
+    FLAG_write_protect_vm_isolate = false;
 
     // Write JITDUMP header.
     WriteHeader();
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index ac5cd08..0226504 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -5585,6 +5585,16 @@
   return IsSymbol(Symbols::Patch());
 }
 
+bool Parser::IsPragmaAnnotation(TokenPosition pos) {
+  if (pos == TokenPosition::kNoSource) {
+    return false;
+  }
+  TokenPosScope saved_pos(this);
+  SetPosition(pos);
+  ExpectToken(Token::kAT);
+  return IsSymbol(Symbols::Pragma());
+}
+
 TokenPosition Parser::SkipMetadata() {
   if (CurrentToken() != Token::kAT) {
     return TokenPosition::kNoSource;
@@ -5966,6 +5976,8 @@
     ConsumeToken();
     is_external = true;
   }
+  const bool has_pragma = IsPragmaAnnotation(metadata_pos);
+
   // Parse optional result type.
   if (IsFunctionReturnType()) {
     // It is too early to resolve the type here, since it can be a result type
@@ -5999,7 +6011,7 @@
                        /* is_abstract = */ false, is_external,
                        /* is_native = */ false,  // May change.
                        owner, decl_begin_pos));
-
+  func.set_has_pragma(has_pragma);
   ASSERT(innermost_function().IsNull());
   innermost_function_ = func.raw();
 
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 12d0557..ca45d6c 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -414,6 +414,7 @@
   void SkipBlock();
   TokenPosition SkipMetadata();
   bool IsPatchAnnotation(TokenPosition pos);
+  bool IsPragmaAnnotation(TokenPosition pos);
   void SkipTypeArguments();
   void SkipTypeParameters();
   void SkipType(bool allow_void);
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 5b3ba92..7d83c25 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -539,8 +539,8 @@
       const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
           StackFrameIterator::kNoCrossThreadIteration;
 #endif
-      StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
-                                  thread, cross_thread_policy);
+      StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
+                                  cross_thread_policy);
       pc_ = NULL;
       fp_ = NULL;
       sp_ = NULL;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index e62baec..f1c80c5 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1811,6 +1811,13 @@
     kFinalizedInstantiated,    // Instantiated type ready for use.
     kFinalizedUninstantiated,  // Uninstantiated type ready for use.
   };
+
+  // Note: we don't handle this field in GC in any special way.
+  // Instead we rely on two things:
+  //   (1) GC not moving code objects and
+  //   (2) lifetime of optimized stubs exceeding that of types;
+  // Practically (2) means that optimized stubs never die because
+  // canonical types to which they are attached never die.
   uword type_test_stub_entry_point_;  // Accessed from generated code.
 
  private:
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index e8af8b8..e5571e4 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -9,6 +9,7 @@
 #include "vm/snapshot.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
+#include "vm/type_testing_stubs.h"
 #include "vm/visitor.h"
 
 namespace dart {
@@ -236,6 +237,11 @@
     type.SetCanonical();
   }
 
+  // Fill in the type testing stub.
+  Instructions& instr = *reader->InstructionsHandle();
+  instr = TypeTestingStubGenerator::DefaultCodeForType(type);
+  type.SetTypeTestingStub(instr);
+
   return type.raw();
 }
 
@@ -306,6 +312,11 @@
   READ_OBJECT_FIELDS(type_ref, type_ref.raw()->from(), type_ref.raw()->to(),
                      kAsReference);
 
+  // Fill in the type testing stub.
+  Instructions& instr = *reader->InstructionsHandle();
+  instr = TypeTestingStubGenerator::DefaultCodeForType(type_ref);
+  type_ref.SetTypeTestingStub(instr);
+
   return type_ref.raw();
 }
 
@@ -357,6 +368,11 @@
       Class::RawCast(reader->ReadObjectImpl(kAsReference));
   type_parameter.set_parameterized_class(*reader->ClassHandle());
 
+  // Fill in the type testing stub.
+  Instructions& instr = *reader->InstructionsHandle();
+  instr = TypeTestingStubGenerator::DefaultCodeForType(type_parameter);
+  type_parameter.SetTypeTestingStub(instr);
+
   return type_parameter.raw();
 }
 
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 645f1ea..bc13a5b 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -26,6 +26,7 @@
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 #include "vm/thread_registry.h"
+#include "vm/type_testing_stubs.h"
 #include "vm/verifier.h"
 
 namespace dart {
@@ -680,8 +681,9 @@
 // Arg3: type arguments of the function of the type being assigned to.
 // Arg4: name of variable being assigned to.
 // Arg5: SubtypeTestCache.
+// Arg6: invocation mode (see TypeCheckMode)
 // Return value: instance if a subtype, otherwise throw a TypeError.
-DEFINE_RUNTIME_ENTRY(TypeCheck, 6) {
+DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
   const Instance& src_instance =
       Instance::CheckedHandle(zone, arguments.ArgAt(0));
   AbstractType& dst_type =
@@ -698,6 +700,13 @@
   cache ^= arguments.ArgAt(5);
   ASSERT(cache.IsNull() || cache.IsSubtypeTestCache());
 
+  const TypeCheckMode mode = static_cast<TypeCheckMode>(
+      Smi::CheckedHandle(zone, arguments.ArgAt(6)).Value());
+
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
+  ASSERT(mode == kTypeCheckFromInline);
+#endif
+
   ASSERT(!dst_type.IsMalformed());    // Already checked in code generator.
   ASSERT(!dst_type.IsMalbounded());   // Already checked in code generator.
   ASSERT(!dst_type.IsDynamicType());  // No need to check assignment.
@@ -731,8 +740,10 @@
       bound_error_message = String::New(bound_error.ToErrorCString());
     }
     if (dst_name.IsNull()) {
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) &&                 \
-    (defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME))
+#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+      // Can only come here from type testing stub.
+      ASSERT(mode != kTypeCheckFromInline);
+
       // Grab the [dst_name] from the pool.  It's stored at one pool slot after
       // the subtype-test-cache.
       DartFrameIterator iterator(thread,
@@ -756,14 +767,20 @@
     UNREACHABLE();
   }
 
-  if (cache.IsNull()) {
+  bool should_update_cache = true;
 #if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) &&                 \
-    (defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME))
+    !defined(DART_PRECOMPILED_RUNTIME)
+  if (mode == kTypeCheckFromLazySpecializeStub) {
+    TypeTestingStubGenerator::SpecializeStubFor(thread, dst_type);
+    // Only create the cache when we come from a normal stub.
+    should_update_cache = false;
+  }
+#endif
 
-#if defined(DART_PRECOMPILER)
-    if (FLAG_precompiled_mode) {
-#endif  // defined(DART_PRECOMPILER)
-
+  if (should_update_cache) {
+    if (cache.IsNull()) {
+#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+      ASSERT(mode == kTypeCheckFromSlowStub);
       // We lazily create [SubtypeTestCache] for those call sites which actually
       // need one and will patch the pool entry.
       DartFrameIterator iterator(thread,
@@ -780,37 +797,15 @@
       ASSERT(pool.ObjectAt(stc_pool_idx) == Object::null());
       cache = SubtypeTestCache::New();
       pool.SetObjectAt(stc_pool_idx, cache);
-
-#if defined(DART_PRECOMPILER)
-    }
-#endif  // defined(DART_PRECOMPILER)
-
 #else
-    // WARNING: If we ever come here, it's a really bad sign, because it means
-    // that there was a type test, which generated code could not handle but we
-    // have no subtype cache.  Which means that this successfully-passing type
-    // check will always go to runtime.
-    //
-    // Currently there is one known case when this happens:
-    //
-    // The [FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest] is
-    // handling type checks against int/num specially: It generates a number of
-    // class-id checks.  Unfortunately it handles only normal implementations of
-    // 'int', such as kSmiCid, kMintCid, kBigintCid.  It will signal that there
-    // is no subtype-cache necessary on that call site, because all integer
-    // types have been handled.
-    //
-    // -> Though this is not true, due to (from runtime/lib/array_patch.dart):
-    //
-    //    class _GrowableArrayMarker implements int { }
-    //
-    // Because of this, we cannot have an `UNREACHABLE()` here, but rather just
-    // have a NOP and return `true`, to signal the type check passed.
-#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
+      UNREACHABLE();
+#endif
+    }
+
+    UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments,
+                        function_type_arguments, Bool::True(), cache);
   }
 
-  UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments,
-                      function_type_arguments, Bool::True(), cache);
   arguments.SetReturn(src_instance);
 }
 
@@ -2059,7 +2054,7 @@
 // Patch static call to point to valid code's entry point.
 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, thread,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
                               StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
   ASSERT(frame != NULL);
@@ -2100,7 +2095,7 @@
 // stub.
 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, thread,
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
                               StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
   ASSERT(frame != NULL);
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index 87b3b3c..9ca79a7 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -578,8 +578,7 @@
 
 void Scavenger::IterateRoots(Isolate* isolate, ScavengerVisitor* visitor) {
   int64_t start = OS::GetCurrentMonotonicMicros();
-  isolate->VisitObjectPointers(visitor,
-                               StackFrameIterator::kDontValidateFrames);
+  isolate->VisitObjectPointers(visitor, ValidationPolicy::kDontValidateFrames);
   int64_t middle = OS::GetCurrentMonotonicMicros();
   IterateStoreBuffers(isolate, visitor);
   IterateObjectIdTable(isolate, visitor);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 1efbaa8..3415481 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -267,7 +267,7 @@
 void SimulatorDebugger::PrintBacktrace() {
   StackFrameIterator frames(
       sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(),
-      StackFrameIterator::kDontValidateFrames, Thread::Current(),
+      ValidationPolicy::kDontValidateFrames, Thread::Current(),
       StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);
@@ -1559,8 +1559,11 @@
             SimulatorDebugger dbg(this);
             int32_t imm = instr->BkptField();
             if (imm == Instr::kStopMessageCode) {
-              const char* message = *reinterpret_cast<const char**>(
-                  reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+              const char* message = "Stop messages not enabled";
+              if (FLAG_print_stop_message) {
+                message = *reinterpret_cast<const char**>(
+                    reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+              }
               set_pc(get_pc() + Instr::kInstrSize);
               dbg.Stop(instr, message);
             } else {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 5493d43..020321c 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -289,7 +289,7 @@
 void SimulatorDebugger::PrintBacktrace() {
   StackFrameIterator frames(
       sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(),
-      StackFrameIterator::kDontValidateFrames, Thread::Current(),
+      ValidationPolicy::kDontValidateFrames, Thread::Current(),
       StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);
@@ -1651,8 +1651,11 @@
     SimulatorDebugger dbg(this);
     int32_t imm = instr->Imm16Field();
     if (imm == Instr::kStopMessageCode) {
-      const char* message = *reinterpret_cast<const char**>(
-          reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+      const char* message = "Stop messages not enabled";
+      if (FLAG_print_stop_message) {
+        message = *reinterpret_cast<const char**>(
+            reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+      }
       set_pc(get_pc() + Instr::kInstrSize);
       dbg.Stop(instr, message);
     } else {
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 487143f..46e467b 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -3060,8 +3060,9 @@
       SP[4] = args[2];  // function type args
       SP[5] = args[4];  // name
       SP[6] = cache;
-      Exit(thread, FP, SP + 7, pc);
-      NativeArguments native_args(thread, 6, SP + 1, SP - 4);
+      SP[7] = Smi::New(kTypeCheckFromInline);
+      Exit(thread, FP, SP + 8, pc);
+      NativeArguments native_args(thread, 7, SP + 1, SP - 4);
       INVOKE_RUNTIME(DRT_TypeCheck, native_args);
     }
 
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index d3667ce..d1fb4ba 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -192,6 +192,7 @@
       old_space_(thread_->isolate()->heap()->old_space()),
       cls_(Class::Handle(zone_)),
       code_(Code::Handle(zone_)),
+      instructions_(Instructions::Handle(zone_)),
       obj_(Object::Handle(zone_)),
       pobj_(PassiveObject::Handle(zone_)),
       array_(Array::Handle(zone_)),
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 60a944f..b630cc3 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -335,6 +335,7 @@
   Array* ArrayHandle() { return &array_; }
   Class* ClassHandle() { return &cls_; }
   Code* CodeHandle() { return &code_; }
+  Instructions* InstructionsHandle() { return &instructions_; }
   String* StringHandle() { return &str_; }
   AbstractType* TypeHandle() { return &type_; }
   TypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
@@ -440,20 +441,21 @@
 
   bool is_vm_isolate() const;
 
-  Snapshot::Kind kind_;   // Indicates type of snapshot(full, script, message).
-  Thread* thread_;        // Current thread.
-  Zone* zone_;            // Zone for allocations while reading snapshot.
-  Heap* heap_;            // Heap of the current isolate.
-  PageSpace* old_space_;  // Old space of the current isolate.
-  Class& cls_;            // Temporary Class handle.
-  Code& code_;            // Temporary Code handle.
-  Object& obj_;           // Temporary Object handle.
-  PassiveObject& pobj_;   // Temporary PassiveObject handle.
-  Array& array_;          // Temporary Array handle.
-  Field& field_;          // Temporary Field handle.
-  String& str_;           // Temporary String handle.
-  Library& library_;      // Temporary library handle.
-  AbstractType& type_;    // Temporary type handle.
+  Snapshot::Kind kind_;            // Indicates type of the snapshot.
+  Thread* thread_;                 // Current thread.
+  Zone* zone_;                     // Zone for allocations while reading.
+  Heap* heap_;                     // Heap of the current isolate.
+  PageSpace* old_space_;           // Old space of the current isolate.
+  Class& cls_;                     // Temporary Class handle.
+  Code& code_;                     // Temporary Code handle.
+  Instructions& instructions_;     // Temporary Instructions handle
+  Object& obj_;                    // Temporary Object handle.
+  PassiveObject& pobj_;            // Temporary PassiveObject handle.
+  Array& array_;                   // Temporary Array handle.
+  Field& field_;                   // Temporary Field handle.
+  String& str_;                    // Temporary String handle.
+  Library& library_;               // Temporary library handle.
+  AbstractType& type_;             // Temporary type handle.
   TypeArguments& type_arguments_;  // Temporary type argument handle.
   GrowableObjectArray& tokens_;    // Temporary tokens handle.
   TokenStream& stream_;            // Temporary token stream handle.
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 50105f9..578129c 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -353,7 +353,7 @@
 StackFrameIterator::StackFrameIterator(ValidationPolicy validation_policy,
                                        Thread* thread,
                                        CrossThreadPolicy cross_thread_policy)
-    : validate_(validation_policy == kValidateFrames),
+    : validate_(validation_policy == ValidationPolicy::kValidateFrames),
       entry_(thread),
       exit_(thread),
       frames_(thread),
@@ -368,7 +368,7 @@
                                        ValidationPolicy validation_policy,
                                        Thread* thread,
                                        CrossThreadPolicy cross_thread_policy)
-    : validate_(validation_policy == kValidateFrames),
+    : validate_(validation_policy == ValidationPolicy::kValidateFrames),
       entry_(thread),
       exit_(thread),
       frames_(thread),
@@ -388,7 +388,7 @@
                                        ValidationPolicy validation_policy,
                                        Thread* thread,
                                        CrossThreadPolicy cross_thread_policy)
-    : validate_(validation_policy == kValidateFrames),
+    : validate_(validation_policy == ValidationPolicy::kValidateFrames),
       entry_(thread),
       exit_(thread),
       frames_(thread),
@@ -441,7 +441,7 @@
 #endif  // !defined(TARGET_ARCH_DBC)
     return current_frame_;
   }
-  ASSERT((validate_ == kDontValidateFrames) || current_frame_->IsValid());
+  ASSERT(!validate_ || current_frame_->IsValid());
   if (current_frame_->IsEntryFrame()) {
     if (HasNextFrame()) {  // We have another chained block.
       current_frame_ = NextExitFrame();
@@ -450,7 +450,7 @@
     current_frame_ = NULL;  // No more frames.
     return current_frame_;
   }
-  ASSERT((validate_ == kDontValidateFrames) || current_frame_->IsExitFrame() ||
+  ASSERT(!validate_ || current_frame_->IsExitFrame() ||
          current_frame_->IsDartFrame(validate_) ||
          current_frame_->IsStubFrame());
 
@@ -472,7 +472,7 @@
   sp_ = frame->GetCallerSp();
   fp_ = frame->GetCallerFp();
   pc_ = frame->GetCallerPc();
-  ASSERT((validate == kDontValidateFrames) || frame->IsValid());
+  ASSERT(!validate || frame->IsValid());
   return frame;
 }
 
@@ -483,7 +483,7 @@
   frames_.sp_ = exit_.GetCallerSp();
   frames_.fp_ = exit_.GetCallerFp();
   frames_.pc_ = exit_.GetCallerPc();
-  ASSERT((validate_ == kDontValidateFrames) || exit_.IsValid());
+  ASSERT(!validate_ || exit_.IsValid());
   return &exit_;
 }
 
@@ -493,7 +493,7 @@
   entry_.fp_ = frames_.fp_;
   entry_.pc_ = frames_.pc_;
   SetupNextExitFrameData();  // Setup data for next exit frame in chain.
-  ASSERT((validate_ == kDontValidateFrames) || entry_.IsValid());
+  ASSERT(!validate_ || entry_.IsValid());
   return &entry_;
 }
 
@@ -586,7 +586,7 @@
 
 #if defined(DEBUG)
 void ValidateFrames() {
-  StackFrameIterator frames(StackFrameIterator::kValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index d809dbc..cfc3d71 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -201,10 +201,6 @@
 // concurrently.
 class StackFrameIterator : public ValueObject {
  public:
-  enum ValidationPolicy {
-    kValidateFrames = 0,
-    kDontValidateFrames = 1,
-  };
   enum CrossThreadPolicy {
     kNoCrossThreadIteration = 0,
     kAllowCrossThreadIteration = 1,
@@ -308,7 +304,7 @@
   explicit DartFrameIterator(
       Thread* thread,
       StackFrameIterator::CrossThreadPolicy cross_thread_policy)
-      : frames_(StackFrameIterator::kDontValidateFrames,
+      : frames_(ValidationPolicy::kDontValidateFrames,
                 thread,
                 cross_thread_policy) {}
   explicit DartFrameIterator(
@@ -316,7 +312,7 @@
       Thread* thread,
       StackFrameIterator::CrossThreadPolicy cross_thread_policy)
       : frames_(last_fp,
-                StackFrameIterator::kDontValidateFrames,
+                ValidationPolicy::kDontValidateFrames,
                 thread,
                 cross_thread_policy) {}
 
@@ -329,7 +325,7 @@
       : frames_(fp,
                 sp,
                 pc,
-                StackFrameIterator::kDontValidateFrames,
+                ValidationPolicy::kDontValidateFrames,
                 thread,
                 cross_thread_policy) {}
 #endif
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index eadc9bf..f5c5684 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -18,7 +18,7 @@
 
 // Unit test for empty stack frame iteration.
 ISOLATE_UNIT_TEST_CASE(EmptyStackFrameIteration) {
-  StackFrameIterator iterator(StackFrameIterator::kValidateFrames,
+  StackFrameIterator iterator(ValidationPolicy::kValidateFrames,
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   EXPECT(!iterator.HasNextFrame());
@@ -50,7 +50,7 @@
 
 void FUNCTION_NAME(StackFrame_frameCount)(Dart_NativeArguments args) {
   int count = 0;
-  StackFrameIterator frames(StackFrameIterator::kValidateFrames,
+  StackFrameIterator frames(ValidationPolicy::kValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
   while (frames.NextFrame() != NULL) {
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 0174f5c..8f5829d 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -13,7 +13,7 @@
                                       const Function& async_function) {
   Zone* zone = thread->zone();
   intptr_t frame_count = 0;
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, thread,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
@@ -48,7 +48,7 @@
                                         intptr_t count,
                                         int skip_frames) {
   Zone* zone = thread->zone();
-  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, thread,
+  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 01ffc6f..b6c1c3c 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -74,6 +74,7 @@
   V(TypeRefTypeTest)                                                           \
   V(UnreachableTypeTest)                                                       \
   V(SlowTypeTest)                                                              \
+  V(LazySpecializeTypeTest)                                                    \
   V(CallClosureNoSuchMethod)                                                   \
   V(FrameAwaitingMaterialization)                                              \
   V(AsynchronousGapMarker)
@@ -94,6 +95,7 @@
   V(TypeRefTypeTest)                                                           \
   V(UnreachableTypeTest)                                                       \
   V(SlowTypeTest)                                                              \
+  V(LazySpecializeTypeTest)                                                    \
   V(FrameAwaitingMaterialization)                                              \
   V(AsynchronousGapMarker)
 
@@ -215,6 +217,23 @@
 
 enum DeoptStubKind { kLazyDeoptFromReturn, kLazyDeoptFromThrow, kEagerDeopt };
 
+// Invocation mode for TypeCheck runtime entry that describes
+// where we are calling it from.
+enum TypeCheckMode {
+  // TypeCheck is invoked from LazySpecializeTypeTest stub.
+  // It should replace stub on the type with a specialized version.
+  kTypeCheckFromLazySpecializeStub,
+
+  // TypeCheck is invoked from the SlowTypeTest stub.
+  // This means that cache can be lazily created (if needed)
+  // and dst_name can be fetched from the pool.
+  kTypeCheckFromSlowStub,
+
+  // TypeCheck is invoked from normal inline AssertAssignable.
+  // Both cache and dst_name must be already populated.
+  kTypeCheckFromInline
+};
+
 // Zap value used to indicate unused CODE_REG in deopt.
 static const uword kZapCodeReg = 0xf1f1f1f1;
 
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index a97ccc5..6aa0494 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1952,11 +1952,54 @@
   __ Breakpoint();
 }
 
+static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
+                                            TypeCheckMode mode) {
+  const Register kInstanceReg = R0;
+  const Register kInstantiatorTypeArgumentsReg = R2;
+  const Register kFunctionTypeArgumentsReg = R1;
+  const Register kDstTypeReg = R8;
+  const Register kSubtypeTestCacheReg = R3;
+
+  __ PushObject(Object::null_object());  // Make room for result.
+  __ Push(kInstanceReg);
+  __ Push(kDstTypeReg);
+  __ Push(kInstantiatorTypeArgumentsReg);
+  __ Push(kFunctionTypeArgumentsReg);
+  __ PushObject(Object::null_object());
+  __ Push(kSubtypeTestCacheReg);
+  __ PushObject(Smi::ZoneHandle(Smi::New(mode)));
+  __ CallRuntime(kTypeCheckRuntimeEntry, 7);
+  __ Drop(1);  // mode
+  __ Pop(kSubtypeTestCacheReg);
+  __ Drop(1);  // dst_name
+  __ Pop(kFunctionTypeArgumentsReg);
+  __ Pop(kInstantiatorTypeArgumentsReg);
+  __ Pop(kDstTypeReg);
+  __ Pop(kInstanceReg);
+  __ Drop(1);  // Discard return value.
+}
+
+void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+  const Register kInstanceReg = R0;
+  Label done;
+
+  __ CompareObject(kInstanceReg, Object::null_object());
+  __ BranchIf(EQUAL, &done);
+
+  __ ldr(CODE_REG,
+         Address(THR, Thread::lazy_specialize_type_test_stub_offset()));
+  __ EnterStubFrame();
+  InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromLazySpecializeStub);
+  __ LeaveStubFrame();
+
+  __ Bind(&done);
+  __ Ret();
+}
+
 void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
   Label done, call_runtime;
 
   const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
   const Register kFunctionTypeArgumentsReg = R1;
   const Register kDstTypeReg = R8;
   const Register kSubtypeTestCacheReg = R3;
@@ -2031,21 +2074,8 @@
   __ CompareObject(kDstTypeReg, Type::Handle(Type::ObjectType()));
   __ BranchIf(EQUAL, &done);
 
-  __ PushObject(Object::null_object());  // Make room for result.
-  __ Push(kInstanceReg);
-  __ Push(kDstTypeReg);
-  __ Push(kInstantiatorTypeArgumentsReg);
-  __ Push(kFunctionTypeArgumentsReg);
-  __ PushObject(Object::null_object());
-  __ Push(kSubtypeTestCacheReg);
-  __ CallRuntime(kTypeCheckRuntimeEntry, 6);
-  __ Pop(kSubtypeTestCacheReg);
-  __ Drop(1);  // dst_name
-  __ Pop(kFunctionTypeArgumentsReg);
-  __ Pop(kInstantiatorTypeArgumentsReg);
-  __ Pop(kDstTypeReg);
-  __ Pop(kInstanceReg);
-  __ Drop(1);  // Discard return value.
+  InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromSlowStub);
+
   __ Bind(&done);
   __ LeaveStubFrame();
   __ Ret();
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index df85dd5..5d07eb1 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -2007,12 +2007,56 @@
       kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
 }
 
+static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
+                                            TypeCheckMode mode) {
+  const Register kInstanceReg = R0;
+  const Register kInstantiatorTypeArgumentsReg = R1;
+  const Register kFunctionTypeArgumentsReg = R2;
+
+  const Register kSubtypeTestCacheReg = R3;
+  const Register kDstTypeReg = R8;
+
+  __ PushObject(Object::null_object());  // Make room for result.
+  __ Push(kInstanceReg);
+  __ Push(kDstTypeReg);
+  __ Push(kInstantiatorTypeArgumentsReg);
+  __ Push(kFunctionTypeArgumentsReg);
+  __ PushObject(Object::null_object());
+  __ Push(kSubtypeTestCacheReg);
+  __ PushObject(Smi::ZoneHandle(Smi::New(mode)));
+  __ CallRuntime(kTypeCheckRuntimeEntry, 7);
+  __ Drop(1);  // mode
+  __ Pop(kSubtypeTestCacheReg);
+  __ Drop(1);  // dst_name
+  __ Pop(kFunctionTypeArgumentsReg);
+  __ Pop(kInstantiatorTypeArgumentsReg);
+  __ Pop(kDstTypeReg);
+  __ Pop(kInstanceReg);
+  __ Drop(1);  // Discard return value.
+}
+
+void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+  const Register kInstanceReg = R0;
+  Label done;
+
+  __ CompareObject(kInstanceReg, Object::null_object());
+  __ BranchIf(EQUAL, &done);
+
+  __ ldr(CODE_REG,
+         Address(THR, Thread::lazy_specialize_type_test_stub_offset()));
+  __ EnterStubFrame();
+  InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromLazySpecializeStub);
+  __ LeaveStubFrame();
+
+  __ Bind(&done);
+  __ Ret();
+}
+
 void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
   Label done, call_runtime;
 
   const Register kInstanceReg = R0;
   const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
 
   const Register kSubtypeTestCacheReg = R3;
   const Register kDstTypeReg = R8;
@@ -2083,21 +2127,8 @@
   __ CompareObject(kDstTypeReg, Type::Handle(Type::ObjectType()));
   __ BranchIf(EQUAL, &done);
 
-  __ PushObject(Object::null_object());  // Make room for result.
-  __ Push(kInstanceReg);
-  __ Push(kDstTypeReg);
-  __ Push(kInstantiatorTypeArgumentsReg);
-  __ Push(kFunctionTypeArgumentsReg);
-  __ PushObject(Object::null_object());
-  __ Push(kSubtypeTestCacheReg);
-  __ CallRuntime(kTypeCheckRuntimeEntry, 6);
-  __ Pop(kSubtypeTestCacheReg);
-  __ Drop(1);  // dst_name
-  __ Pop(kFunctionTypeArgumentsReg);
-  __ Pop(kInstantiatorTypeArgumentsReg);
-  __ Pop(kDstTypeReg);
-  __ Pop(kInstanceReg);
-  __ Drop(1);  // Discard return value.
+  InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromSlowStub);
+
   __ Bind(&done);
   __ LeaveStubFrame();
   __ Ret();
diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc
index f78a5d1..130e4f8 100644
--- a/runtime/vm/stub_code_dbc.cc
+++ b/runtime/vm/stub_code_dbc.cc
@@ -104,6 +104,11 @@
 }
 
 // TODO(kustermann): Don't generate this stub.
+void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
 void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
   __ Trap();
 }
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index feb5068..ae5b070 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1788,27 +1788,32 @@
 }
 
 void StubCode::GenerateDefaultTypeTestStub(Assembler* assembler) {
-  // Only used in AOT and therefore not on ia32.
+  // Not implemented on ia32.
   __ Breakpoint();
 }
 
 void StubCode::GenerateTopTypeTypeTestStub(Assembler* assembler) {
-  // Only used in AOT and therefore not on ia32.
+  // Not implemented on ia32.
   __ Breakpoint();
 }
 
 void StubCode::GenerateTypeRefTypeTestStub(Assembler* assembler) {
-  // Only used in AOT and therefore not on ia32.
+  // Not implemented on ia32.
   __ Breakpoint();
 }
 
 void StubCode::GenerateUnreachableTypeTestStub(Assembler* assembler) {
-  // Only used in AOT and therefore not on ia32.
+  // Not implemented on ia32.
+  __ Breakpoint();
+}
+
+void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+  // Not implemented on ia32.
   __ Breakpoint();
 }
 
 void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
-  // Only used in AOT and therefore not on ia32.
+  // Not implemented on ia32.
   __ Breakpoint();
 }
 
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index d87f045..c5d5151 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -2121,12 +2121,56 @@
       kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
 }
 
+static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
+                                            TypeCheckMode mode) {
+  const Register kInstanceReg = RAX;
+  const Register kInstantiatorTypeArgumentsReg = RDX;
+  const Register kFunctionTypeArgumentsReg = RCX;
+  const Register kDstTypeReg = RBX;
+  const Register kSubtypeTestCacheReg = R9;
+
+  __ PushObject(Object::null_object());  // Make room for result.
+  __ pushq(kInstanceReg);
+  __ pushq(kDstTypeReg);
+  __ pushq(kInstantiatorTypeArgumentsReg);
+  __ pushq(kFunctionTypeArgumentsReg);
+  __ PushObject(Object::null_object());
+  __ pushq(kSubtypeTestCacheReg);
+  __ PushObject(Smi::ZoneHandle(Smi::New(mode)));
+  __ CallRuntime(kTypeCheckRuntimeEntry, 7);
+  __ Drop(1);
+  __ popq(kSubtypeTestCacheReg);
+  __ Drop(1);
+  __ popq(kFunctionTypeArgumentsReg);
+  __ popq(kInstantiatorTypeArgumentsReg);
+  __ popq(kDstTypeReg);
+  __ popq(kInstanceReg);
+  __ Drop(1);  // Discard return value.
+}
+
+void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+  const Register kInstanceReg = RAX;
+
+  Label done;
+
+  // Fast case for 'null'.
+  __ CompareObject(kInstanceReg, Object::null_object());
+  __ BranchIf(EQUAL, &done);
+
+  __ movq(CODE_REG,
+          Address(THR, Thread::lazy_specialize_type_test_stub_offset()));
+  __ EnterStubFrame();
+  InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromLazySpecializeStub);
+  __ LeaveStubFrame();
+
+  __ Bind(&done);
+  __ Ret();
+}
+
 void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
   Label done, call_runtime;
 
   const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
   const Register kDstTypeReg = RBX;
   const Register kSubtypeTestCacheReg = R9;
 
@@ -2191,21 +2235,8 @@
   __ CompareObject(kDstTypeReg, Type::Handle(Type::ObjectType()));
   __ BranchIf(EQUAL, &done);
 
-  __ PushObject(Object::null_object());  // Make room for result.
-  __ pushq(kInstanceReg);
-  __ pushq(kDstTypeReg);
-  __ pushq(kInstantiatorTypeArgumentsReg);
-  __ pushq(kFunctionTypeArgumentsReg);
-  __ PushObject(Object::null_object());
-  __ pushq(kSubtypeTestCacheReg);
-  __ CallRuntime(kTypeCheckRuntimeEntry, 6);
-  __ popq(kSubtypeTestCacheReg);
-  __ Drop(1);
-  __ popq(kFunctionTypeArgumentsReg);
-  __ popq(kInstantiatorTypeArgumentsReg);
-  __ popq(kDstTypeReg);
-  __ popq(kInstanceReg);
-  __ Drop(1);  // Discard return value.
+  InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromSlowStub);
+
   __ Bind(&done);
   __ LeaveStubFrame();
   __ Ret();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index a68bce5..4613aff 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -170,6 +170,7 @@
   V(_MixinAppType, "_MixinAppType")                                            \
   V(TypeArguments, "TypeArguments")                                            \
   V(Patch, "patch")                                                            \
+  V(Pragma, "pragma")                                                          \
   V(PatchClass, "PatchClass")                                                  \
   V(Function, "Function")                                                      \
   V(_Closure, "_Closure")                                                      \
@@ -444,6 +445,7 @@
   V(DartLibraryMirrors, "dart.library.mirrors")                                \
   V(_name, "_name")                                                            \
   V(name, "name")                                                              \
+  V(options, "options")                                                        \
   V(_classRangeCheck, "_classRangeCheck")                                      \
   V(_classRangeCheckNegative, "_classRangeCheckNegative")                      \
   V(_classRangeAssert, "_classRangeAssert")                                    \
@@ -454,7 +456,9 @@
   V(DartDeveloperCausalAsyncStacks, "dart.developer.causal_async_stacks")      \
   V(_AsyncStarListenHelper, "_asyncStarListenHelper")                          \
   V(GrowRegExpStack, "_growRegExpStack")                                       \
-  V(DebugProcedureName, ":Eval")
+  V(DebugProcedureName, ":Eval")                                               \
+  V(DebugClassName, "#DebugClass")                                             \
+  V(vm_entry_point, "vm.entry_point")
 
 // Contains a list of frequently used strings in a canonicalized form. This
 // list is kept in the vm_isolate in order to share the copy across isolates
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 68b4a05..aec2bf7 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -152,6 +152,8 @@
   }
 }
 
+static const double double_nan_constant = NAN;
+
 static const struct ALIGN16 {
   uint64_t a;
   uint64_t b;
@@ -630,7 +632,7 @@
 }
 
 void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor,
-                                 bool validate_frames) {
+                                 ValidationPolicy validation_policy) {
   ASSERT(visitor != NULL);
 
   if (zone_ != NULL) {
@@ -666,10 +668,6 @@
   const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
       StackFrameIterator::kAllowCrossThreadIteration;
 
-  const StackFrameIterator::ValidationPolicy validation_policy =
-      validate_frames ? StackFrameIterator::kValidateFrames
-                      : StackFrameIterator::kDontValidateFrames;
-
   // Iterate over all the stack frames and visit objects on the stack.
   StackFrameIterator frames_iterator(top_exit_frame_info(), validation_policy,
                                      this, cross_thread_policy);
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 802233a..063c4ef 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -15,6 +15,7 @@
 #include "vm/os_thread.h"
 #include "vm/runtime_entry_list.h"
 #include "vm/store_buffer.h"
+
 namespace dart {
 
 class AbstractType;
@@ -102,7 +103,9 @@
   V(RawCode*, lazy_deopt_from_throw_stub_,                                     \
     StubCode::DeoptimizeLazyFromThrow_entry()->code(), NULL)                   \
   V(RawCode*, slow_type_test_stub_, StubCode::SlowTypeTest_entry()->code(),    \
-    NULL)
+    NULL)                                                                      \
+  V(RawCode*, lazy_specialize_type_test_stub_,                                 \
+    StubCode::LazySpecializeTypeTest_entry()->code(), NULL)
 
 #endif
 
@@ -146,6 +149,8 @@
     NativeEntry::AutoScopeNativeCallWrapperEntry(), 0)                         \
   V(RawString**, predefined_symbols_address_, Symbols::PredefinedAddress(),    \
     NULL)                                                                      \
+  V(uword, double_nan_address_, reinterpret_cast<uword>(&double_nan_constant), \
+    0)                                                                         \
   V(uword, double_negate_address_,                                             \
     reinterpret_cast<uword>(&double_negate_constant), 0)                       \
   V(uword, double_abs_address_, reinterpret_cast<uword>(&double_abs_constant), \
@@ -163,6 +168,11 @@
   CACHED_VM_OBJECTS_LIST(V)                                                    \
   CACHED_ADDRESSES_LIST(V)
 
+enum class ValidationPolicy {
+  kValidateFrames = 0,
+  kDontValidateFrames = 1,
+};
+
 // A VM thread; may be executing Dart code or performing helper tasks like
 // garbage collection or compilation. The Thread structure associated with
 // a thread is allocated by EnsureInit before entering an isolate, and destroyed
@@ -731,7 +741,8 @@
   Thread* next() const { return next_; }
 
   // Visit all object pointers.
-  void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
+  void VisitObjectPointers(ObjectPointerVisitor* visitor,
+                           ValidationPolicy validate_frames);
 
   bool IsValidHandle(Dart_Handle object) const;
   bool IsValidLocalHandle(Dart_Handle object) const;
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index c388840..c7883af 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -60,7 +60,7 @@
 }
 
 void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
-                                         bool validate_frames) {
+                                         ValidationPolicy validate_frames) {
   MonitorLocker ml(threads_lock());
   bool mutator_thread_visited = false;
   Thread* thread = active_list_;
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index cefcf05..f2426d5 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -29,7 +29,8 @@
         mutator_thread_(NULL) {}
   ~ThreadRegistry();
 
-  void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
+  void VisitObjectPointers(ObjectPointerVisitor* visitor,
+                           ValidationPolicy validate_frames);
   void PrepareForGC();
   Thread* mutator_thread() const { return mutator_thread_; }
 
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index b00cd0a..e033319 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -131,7 +131,7 @@
         ObjectCounter counter(isolate_, &smi);
         // Ensure that our particular zone is visited.
         iteration.IterateStackPointers(&counter,
-                                       StackFrameIterator::kValidateFrames);
+                                       ValidationPolicy::kValidateFrames);
         EXPECT_EQ(1, counter.count());
       }
       char* unique_chars = zone->PrintToString("unique_str_%" Pd, id_);
@@ -148,7 +148,7 @@
         ObjectCounter str_counter(isolate_, &unique_str);
         // Ensure that our particular zone is visited.
         iteration.IterateStackPointers(&str_counter,
-                                       StackFrameIterator::kValidateFrames);
+                                       ValidationPolicy::kValidateFrames);
         // We should visit the string object exactly once.
         EXPECT_EQ(1, str_counter.count());
       }
@@ -429,7 +429,7 @@
         ASSERT(thread->IsAtSafepoint());
         ObjectCounter counter(isolate_, &smi);
         iteration.IterateStackPointers(&counter,
-                                       StackFrameIterator::kValidateFrames);
+                                       ValidationPolicy::kValidateFrames);
         {
           MonitorLocker ml(monitor_);
           EXPECT_EQ(*expected_count_, counter.count());
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 2a3b85c..3ec5386 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -92,7 +92,8 @@
 }
 
 RawInstructions* TypeTestingStubGenerator::DefaultCodeForType(
-    const AbstractType& type) {
+    const AbstractType& type,
+    bool lazy_specialize /* = true */) {
   // During bootstrapping we have no access to stubs yet, so we'll just return
   // `null` and patch these later in `Object::FinishInitOnce()`.
   if (!StubCode::HasBeenInitialized()) {
@@ -112,13 +113,27 @@
   }
 
   if (type.IsType() || type.IsTypeParameter()) {
-    return Code::InstructionsOf(StubCode::DefaultTypeTest_entry()->code());
+    const bool should_specialize = !FLAG_precompiled_mode && lazy_specialize;
+    return Code::InstructionsOf(
+        should_specialize ? StubCode::LazySpecializeTypeTest_entry()->code()
+                          : StubCode::DefaultTypeTest_entry()->code());
   } else {
     ASSERT(type.IsBoundedType() || type.IsMixinAppType());
     return Code::InstructionsOf(StubCode::UnreachableTypeTest_entry()->code());
   }
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+void TypeTestingStubGenerator::SpecializeStubFor(Thread* thread,
+                                                 const AbstractType& type) {
+  HierarchyInfo hi(thread);
+  TypeTestingStubGenerator generator;
+  const Instructions& instr = Instructions::Handle(
+      thread->zone(), generator.OptimizedCodeForType(type));
+  type.SetTypeTestingStub(instr);
+}
+#endif
+
 TypeTestingStubGenerator::TypeTestingStubGenerator()
     : object_store_(Isolate::Current()->object_store()),
       array_(GrowableObjectArray::Handle()),
@@ -167,7 +182,7 @@
     }
   }
 #endif  // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
-  return TypeTestingStubGenerator::DefaultCodeForType(type);
+  return TypeTestingStubGenerator::DefaultCodeForType(type, false);
 }
 
 TypeTestingStubFinder::TypeTestingStubFinder()
@@ -189,6 +204,10 @@
   if (entry_point == code_.UncheckedEntryPoint()) {
     return code_.instructions();
   }
+  code_ = StubCode::LazySpecializeTypeTest_entry()->code();
+  if (entry_point == code_.UncheckedEntryPoint()) {
+    return code_.instructions();
+  }
   code_ = StubCode::TopTypeTypeTest_entry()->code();
   if (entry_point == code_.UncheckedEntryPoint()) {
     return code_.instructions();
@@ -213,6 +232,10 @@
   if (entry_point == code_.UncheckedEntryPoint()) {
     return "TypeTestingStub_Default";
   }
+  code_ = StubCode::LazySpecializeTypeTest_entry()->code();
+  if (entry_point == code_.UncheckedEntryPoint()) {
+    return "TypeTestingStub_LazySpecialize";
+  }
   code_ = StubCode::TopTypeTypeTest_entry()->code();
   if (entry_point == code_.UncheckedEntryPoint()) {
     return "TypeTestingStub_Top";
@@ -331,7 +354,7 @@
 #ifndef PRODUCT
   if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
     LogBlock lb;
-    THR_Print("Code for stub '%s': {\n", name);
+    THR_Print("Code for stub '%s' (type = %s): {\n", name, type.ToCString());
     DisassembleToStdout formatter;
     code.Disassemble(&formatter);
     THR_Print("}\n");
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index d03b48a..ce589c8 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -36,7 +36,12 @@
   // During bootstrapping it will return `null` for a whitelisted set of types,
   // otherwise it will return a default stub which tail-calls
   // subtypingtest/runtime code.
-  static RawInstructions* DefaultCodeForType(const AbstractType& type);
+  static RawInstructions* DefaultCodeForType(const AbstractType& type,
+                                             bool lazy_specialize = true);
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  static void SpecializeStubFor(Thread* thread, const AbstractType& type);
+#endif
 
   TypeTestingStubGenerator();
 
diff --git a/runtime/vm/verifier.cc b/runtime/vm/verifier.cc
index 83f00d2..65d854b 100644
--- a/runtime/vm/verifier.cc
+++ b/runtime/vm/verifier.cc
@@ -74,8 +74,7 @@
 
   VerifyPointersVisitor visitor(isolate, allocated_set);
   // Visit all strongly reachable objects.
-  iteration.IterateObjectPointers(&visitor,
-                                  StackFrameIterator::kValidateFrames);
+  iteration.IterateObjectPointers(&visitor, ValidationPolicy::kValidateFrames);
   VerifyWeakPointersVisitor weak_visitor(&visitor);
   // Visit weak handles and prologue weak handles.
   isolate->VisitWeakPersistentHandles(&weak_visitor);
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 62ea806..6f84167 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -564,7 +564,7 @@
   deps = [
     ":copy_libraries",
     "../utils/dartdevc:dartdevc_sdk",
-    "../utils/dartdevc:dartdevc_sdk_kernel_summary",
+    "../utils/dartdevc:dartdevk_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
@@ -651,9 +651,9 @@
 copy("copy_dev_compiler_js_amd_kernel") {
   visibility = [ ":copy_dev_compiler_js" ]
   deps = [
-    "../utils/dartdevc:dartdevc_sdk_kernel_summary",
+    "../utils/dartdevc:dartdevk_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk_kernel_summary",
+  gen_dir = get_label_info("../utils/dartdevc:dartdevk_sdk",
                            "target_gen_dir")
   sources = [
     "$gen_dir/kernel/amd/dart_sdk.js",
@@ -669,9 +669,9 @@
 copy("copy_dev_compiler_js_common_kernel") {
   visibility = [ ":copy_dev_compiler_js" ]
   deps = [
-    "../utils/dartdevc:dartdevc_sdk_kernel_summary",
+    "../utils/dartdevc:dartdevk_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk_kernel_summary",
+  gen_dir = get_label_info("../utils/dartdevc:dartdevk_sdk",
                            "target_gen_dir")
   sources = [
     "$gen_dir/kernel/common/dart_sdk.js",
@@ -687,9 +687,9 @@
 copy("copy_dev_compiler_js_es6_kernel") {
   visibility = [ ":copy_dev_compiler_js" ]
   deps = [
-    "../utils/dartdevc:dartdevc_sdk_kernel_summary",
+    "../utils/dartdevc:dartdevk_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk_kernel_summary",
+  gen_dir = get_label_info("../utils/dartdevc:dartdevk_sdk",
                            "target_gen_dir")
   sources = [
     "$gen_dir/kernel/es6/dart_sdk.js",
@@ -704,9 +704,9 @@
 copy("copy_dev_compiler_js_legacy_kernel") {
   visibility = [ ":copy_dev_compiler_js" ]
   deps = [
-    "../utils/dartdevc:dartdevc_sdk_kernel_summary",
+    "../utils/dartdevc:dartdevk_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk_kernel_summary",
+  gen_dir = get_label_info("../utils/dartdevc:dartdevk_sdk",
                            "target_gen_dir")
   sources = [
     "$gen_dir/kernel/legacy/dart_sdk.js",
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 124d295..9af877f 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -38,10 +38,10 @@
 
 case $0 in
   *_developer)
-    EXTRA_VM_OPTIONS+=('--checked')
+    EXTRA_VM_OPTIONS+=('--enable-asserts')
     ;;
 esac
-EXTRA_VM_OPTIONS+=('--no_limit_ints_to_64_bits')
+EXTRA_VM_OPTIONS+=('--preview-dart-2')
 
 # We allow extra vm options to be passed in through an environment variable.
 if [[ $DART_VM_OPTIONS ]]; then
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index 92058d5..3f3fd9d 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -20,10 +20,10 @@
 set DART=%BIN_DIR%\dart
 
 set EXTRA_OPTIONS=
-set EXTRA_VM_OPTIONS=--no_limit_ints_to_64_bits
+set EXTRA_VM_OPTIONS=--preview-dart-2
 
 if _%DART2JS_DEVELOPER_MODE%_ == _1_ (
-  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --checked
+  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --enable-asserts
 )
 
 rem We allow extra vm options to be passed in through an environment variable.
diff --git a/sdk/bin/dart2js_sdk b/sdk/bin/dart2js_sdk
index 89155dc..3896e71 100755
--- a/sdk/bin/dart2js_sdk
+++ b/sdk/bin/dart2js_sdk
@@ -45,10 +45,10 @@
 
 case $0 in
   *_developer)
-    EXTRA_VM_OPTIONS+=('--checked')
+    EXTRA_VM_OPTIONS+=('--enable-asserts')
     ;;
 esac
-EXTRA_VM_OPTIONS+=('--no_limit_ints_to_64_bits')
+EXTRA_VM_OPTIONS+=('--preview-dart-2')
 
 # We allow extra vm options to be passed in through an environment variable.
 if [[ $DART_VM_OPTIONS ]]; then
diff --git a/sdk/bin/dart2js_sdk.bat b/sdk/bin/dart2js_sdk.bat
index b581cb3..3b1aa66 100755
--- a/sdk/bin/dart2js_sdk.bat
+++ b/sdk/bin/dart2js_sdk.bat
@@ -21,10 +21,10 @@
 set SNAPSHOT=%BIN_DIR%\snapshots\dart2js.dart.snapshot
 
 set EXTRA_OPTIONS=
-set EXTRA_VM_OPTIONS=--no_limit_ints_to_64_bits
+set EXTRA_VM_OPTIONS=--preview-dart-2
 
 if _%DART2JS_DEVELOPER_MODE%_ == _1_ (
-  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --checked
+  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --enable-asserts
 )
 
 if exist "%SNAPSHOT%" (
diff --git a/sdk/bin/dartdoc b/sdk/bin/dartdoc
index caff494..73d81e0 100755
--- a/sdk/bin/dartdoc
+++ b/sdk/bin/dartdoc
@@ -26,4 +26,4 @@
 
 # We are running the snapshot in the built SDK.
 DART="$BIN_DIR/dart"
-exec "$DART" --packages="$BIN_DIR/snapshots/resources/dartdoc/.packages" "$SNAPSHOT" "$@"
+exec "$DART" "--preview-dart-2" --packages="$BIN_DIR/snapshots/resources/dartdoc/.packages" "$SNAPSHOT" "$@"
diff --git a/sdk/bin/dartdoc.bat b/sdk/bin/dartdoc.bat
index 37ed5f8..fdab3b5 100644
--- a/sdk/bin/dartdoc.bat
+++ b/sdk/bin/dartdoc.bat
@@ -14,7 +14,7 @@
 set DART=%BIN_DIR%\dart
 set SNAPSHOT=%BIN_DIR%\snapshots\dartdoc.dart.snapshot
 
-"%DART%" --packages="%BIN_DIR%/snapshots/resources/dartdoc/.packages" "%SNAPSHOT%" %*
+"%DART%" "--preview-dart-2" --packages="%BIN_DIR%/snapshots/resources/dartdoc/.packages" "%SNAPSHOT%" %*
 
 endlocal
 
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
index 7221968..0a2baed 100644
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
@@ -485,6 +485,7 @@
 
   String toString() {
     var dartClosure = JS('', '#.#', this, DART_CLOSURE_PROPERTY_NAME);
-    return dartClosure == null ? super.toString() : dartClosure.toString();
+    if (dartClosure == null) return super.toString();
+    return 'JavaScript function for ${dartClosure.toString()}';
   }
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 4896e9d..7ae0796 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3465,10 +3465,19 @@
 
 functionTypeTest(value, functionTypeRti) {
   if (value == null) return false;
+  if (JS('bool', 'typeof # == "function"', value)) {
+    // JavaScript functions do not have an attached type, but for convenient
+    // JS-interop, we pretend they can be any function type.
+    // TODO(sra): Tighten this up to disallow matching function types with
+    // features inaccessible from JavaScript, i.e.  optional named parameters
+    // and type parameters functions.
+    // TODO(sra): If the JavaScript function was the output of `dart:js`'s
+    // `allowInterop` then we have access to the wrapped function.
+    return true;
+  }
   var functionTypeObject = extractFunctionTypeObjectFrom(value);
-  return functionTypeObject == null
-      ? false
-      : isFunctionSubtype(functionTypeObject, functionTypeRti);
+  if (functionTypeObject == null) return false;
+  return isFunctionSubtype(functionTypeObject, functionTypeRti);
 }
 
 // Declared as 'var' to avoid assignment checks.
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index 09f2df3..5e2b7f4 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -829,25 +829,28 @@
 bool checkSubtypeOfRuntimeType(o, t) {
   if (o == null) return isSupertypeOfNull(t);
   if (isTopType(t)) return true;
-  if (JS_GET_FLAG('STRONG_MODE') &&
-      JS('bool', 'typeof # == "object"', t) &&
-      isDartFutureOrType(t)) {
-    // `o is FutureOr<T>` is equivalent to
-    //
-    //     o is T || o is Future<T>
-    //
-    // T might be a function type, requiring extracting the closure's signature,
-    // so do the `o is T` check here and let the `Future` interface type test
-    // fall through to the `isSubtype` check at the end of this function.
-    var tTypeArgument = getFutureOrArgument(t);
-    if (checkSubtypeOfRuntimeType(o, tTypeArgument)) return true;
+  if (JS('bool', 'typeof # == "object"', t)) {
+    if (JS_GET_FLAG('STRONG_MODE') && isDartFutureOrType(t)) {
+      // `o is FutureOr<T>` is equivalent to
+      //
+      //     o is T || o is Future<T>
+      //
+      // T might be a function type, requiring extracting the closure's
+      // signature, so do the `o is T` check here and let the `Future` interface
+      // type test fall through to the `isSubtype` check at the end of this
+      // function.
+      var tTypeArgument = getFutureOrArgument(t);
+      if (checkSubtypeOfRuntimeType(o, tTypeArgument)) return true;
+    }
+
+    if (isDartFunctionType(t)) {
+      return functionTypeTest(o, t);
+    }
   }
 
-  // Get the runtime type information from the object here, because we may
-  // overwrite o with the interceptor below.
+  var interceptor = getInterceptor(o);
+  var type = getRawRuntimeType(interceptor);
   var rti = getRuntimeTypeInfo(o);
-  o = getInterceptor(o);
-  var type = getRawRuntimeType(o);
   if (rti != null) {
     // If the type has type variables (that is, `rti != null`), make a copy of
     // the type arguments and insert [o] in the first position to create a
@@ -856,13 +859,6 @@
     JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0.
     type = rti;
   }
-  if (isDartFunctionType(t)) {
-    // Functions are treated specially and have their type information stored
-    // directly in the instance.
-    type = extractFunctionTypeObjectFromInternal(o);
-    if (type == null) return false;
-    return isFunctionSubtype(type, t);
-  }
   return isSubtype(type, t);
 }
 
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index 4be4e47..df6ad29 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.dart
@@ -13,12 +13,3 @@
     return unaryErrorHandler(error);
   }
 }
-
-Function _registerErrorHandler<R>(Function errorHandler, Zone zone) {
-  if (errorHandler is ZoneBinaryCallback<dynamic, Null, Null>) {
-    return zone
-        .registerBinaryCallback<FutureOr<R>, Object, StackTrace>(errorHandler);
-  } else {
-    return zone.registerUnaryCallback<FutureOr<R>, Object>(errorHandler);
-  }
-}
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index bcd1f22..3af2658 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -552,10 +552,14 @@
    *
    * If [onError] is provided, and this future completes with an error,
    * the `onError` callback is called with that error and its stack trace.
-   * The `onError` callback must accept either one argument or two arguments.
+   * The `onError` callback must accept either one argument or two arguments
+   * where the latter is a [StackTrace].
    * If `onError` accepts two arguments,
    * it is called with both the error and the stack trace,
    * otherwise it is called with just the error object.
+   * The `onError` callback must return a value or future that can be used
+   * to complete the returned future, so it must be something assignable to
+   * `FutureOr<R>`.
    *
    * Returns a new [Future]
    * which is completed with the result of the call to `onValue`
@@ -586,7 +590,7 @@
    * has completed with an error then the error is reported as unhandled error.
    * See the description on [Future].
    */
-  Future<S> then<S>(FutureOr<S> onValue(T value), {Function onError});
+  Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
 
   /**
    * Handles errors emitted by this [Future].
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 6eeaa08..077ccf6 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -137,12 +137,14 @@
   FutureOr<T> handleError(AsyncError asyncError) {
     assert(handlesError && hasErrorCallback);
     var errorCallback = this.errorCallback; // To enable promotion.
-    if (errorCallback is ZoneBinaryCallback<FutureOr<T>, Object, StackTrace>) {
-      return _zone.runBinary(
+    // If the errorCallback returns something which is not a FutureOr<T>,
+    // this return statement throws, and the caller handles the error.
+    if (errorCallback is dynamic Function(Object, StackTrace)) {
+      return _zone.runBinary<dynamic, Object, StackTrace>(
           errorCallback, asyncError.error, asyncError.stackTrace);
     } else {
-      return _zone.runUnary<FutureOr<T>, Object>(
-          errorCallback, asyncError.error);
+      assert(errorCallback is dynamic Function(Object));
+      return _zone.runUnary<dynamic, Object>(errorCallback, asyncError.error);
     }
   }
 
@@ -232,15 +234,18 @@
     _resultOrListeners = source;
   }
 
-  Future<E> then<E>(FutureOr<E> f(T value), {Function onError}) {
+  Future<R> then<R>(FutureOr<R> f(T value), {Function onError}) {
     Zone currentZone = Zone.current;
     if (!identical(currentZone, _rootZone)) {
-      f = currentZone.registerUnaryCallback<FutureOr<E>, T>(f);
+      f = currentZone.registerUnaryCallback<FutureOr<R>, T>(f);
       if (onError != null) {
-        onError = _registerErrorHandler<E>(onError, currentZone);
+        // In checked mode, this checks that onError is assignable to one of:
+        //   dynamic Function(Object)
+        //   dynamic Function(Object, StackTrace)
+        onError = _registerErrorHandler(onError, currentZone);
       }
     }
-    return _thenNoZoneRegistration<E>(f, onError);
+    return _thenNoZoneRegistration<R>(f, onError);
   }
 
   // This method is used by async/await.
@@ -254,7 +259,7 @@
   Future<T> catchError(Function onError, {bool test(error)}) {
     _Future<T> result = new _Future<T>();
     if (!identical(result._zone, _rootZone)) {
-      onError = _registerErrorHandler<T>(onError, result._zone);
+      onError = _registerErrorHandler(onError, result._zone);
       if (test != null) test = result._zone.registerUnaryCallback(test);
     }
     _addListener(new _FutureListener<T, T>.catchError(result, onError, test));
@@ -739,3 +744,29 @@
     return result;
   }
 }
+
+/// Registers errorHandler in zone if it has the correct type.
+///
+/// Checks that the function accepts either an [Object] and a [StackTrace]
+/// or just one [Object]. Does not check the return type.
+/// The actually returned value must be `FutureOr<R>` where `R` is the
+/// value type of the future that the call will complete (either returned
+/// by [Future.then] or [Future.catchError]). We check the returned value
+/// dynamically because the functions are passed as arguments in positions
+/// without inference, so a function expression won't infer the return type.
+///
+/// Throws if the type is not valid.
+Function _registerErrorHandler(Function errorHandler, Zone zone) {
+  if (errorHandler is dynamic Function(Object, StackTrace)) {
+    return zone
+        .registerBinaryCallback<dynamic, Object, StackTrace>(errorHandler);
+  }
+  if (errorHandler is dynamic Function(Object)) {
+    return zone.registerUnaryCallback<dynamic, Object>(errorHandler);
+  }
+  throw new ArgumentError.value(
+      errorHandler,
+      "onError",
+      "Error handler must accept one Object or one Object and a StackTrace"
+      " as arguments, and return a a valid result");
+}
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 5e8a742..310ec37 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -141,9 +141,15 @@
 
   void onError(Function handleError) {
     if (handleError == null) handleError = _nullErrorHandler;
-    // We are not allowed to use 'void' as type argument for the generic type,
-    // so we use 'dynamic' instead.
-    _onError = _registerErrorHandler<dynamic>(handleError, _zone);
+    if (handleError is void Function(Object, StackTrace)) {
+      _onError = _zone
+          .registerBinaryCallback<dynamic, Object, StackTrace>(handleError);
+    } else if (handleError is void Function(Object)) {
+      _onError = _zone.registerUnaryCallback<dynamic, Object>(handleError);
+    } else {
+      throw new ArgumentError("handleError callback must take either an Object "
+          "(the error), or both an Object (the error) and a StackTrace.");
+    }
   }
 
   void onDone(void handleDone()) {
@@ -344,11 +350,11 @@
       if (_isCanceled && !_waitsForCancel) return;
       _state |= _STATE_IN_CALLBACK;
       // TODO(floitsch): this dynamic should be 'void'.
-      if (_onError is ZoneBinaryCallback<dynamic, Object, StackTrace>) {
-        ZoneBinaryCallback<dynamic, Object, StackTrace> errorCallback =
-            _onError;
-        _zone.runBinaryGuarded(errorCallback, error, stackTrace);
+      var onError = _onError;
+      if (onError is void Function(Object, StackTrace)) {
+        _zone.runBinaryGuarded<Object, StackTrace>(onError, error, stackTrace);
       } else {
+        assert(_onError is void Function(Object));
         _zone.runUnaryGuarded<Object>(_onError, error);
       }
       _state &= ~_STATE_IN_CALLBACK;
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 951d027..f875f0c 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -1419,25 +1419,33 @@
 /**
  * Runs [body] in its own zone.
  *
- * Returns the result of invoking [body].
+ * Creates a new zone using [Zone.fork] based on [zoneSpecification] and
+ * [zoneValues], then runs [body] in that zone and returns the result.
  *
- * If [onError] is non-null the zone is considered an error zone. All uncaught
- * errors, synchronous or asynchronous, in the zone are caught and handled
- * by the callback. When the error is synchronous, throwing in the [onError]
- * handler, leads to a synchronous exception.
+ * If [onError] is provided, it must have one of the types
+ * * `void Function(Object)`
+ * * `void Function(Object, StackTrace)`
+ * and the [onError] handler is used *both* to handle asynchronous errors
+ * by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
+ * if any, *and* to handle errors thrown synchronously by the call to [body].
  *
- * Returns `null` when [body] threw, and a provided [onError] function completed
- * without throwing.
+ * If an error occurs synchronously in [body],
+ * then throwing in the [onError] handler
+ * makes the call to `runZone` throw that error,
+ * and otherwise the call to `runZoned` returns `null`.
  *
- * Errors may never cross error-zone boundaries. This is intuitive for leaving
- * a zone, but it also applies for errors that would enter an error-zone.
- * Errors that try to cross error-zone boundaries are considered uncaught.
+ * If the zone specification has a `handleUncaughtError` value or the [onError]
+ * parameter is provided, the zone becomes an error-zone.
+ *
+ * Errors will never cross error-zone boundaries by themselves.
+ * Errors that try to cross error-zone boundaries are considered uncaught in
+ * their originating error zone.
  *
  *     var future = new Future.value(499);
  *     runZoned(() {
- *       future = future.then((_) { throw "error in first error-zone"; });
+ *       var future2 = future.then((_) { throw "error in first error-zone"; });
  *       runZoned(() {
- *         future = future.catchError((e) { print("Never reached!"); });
+ *         var future3 = future2.catchError((e) { print("Never reached!"); });
  *       }, onError: (e) { print("unused error handler"); });
  *     }, onError: (e) { print("catches error of first error-zone."); });
  *
@@ -1446,58 +1454,65 @@
  *     runZoned(() {
  *       new Future(() { throw "asynchronous error"; });
  *     }, onError: print);  // Will print "asynchronous error".
+ *
+ * It is possible to manually pass an error from one error zone to another
+ * by re-throwing it in the new zone. If [onError] throws, that error will
+ * occur in the original zone where [runZoned] was called.
  */
 R runZoned<R>(R body(),
     {Map zoneValues, ZoneSpecification zoneSpecification, Function onError}) {
-  // TODO(floitsch): the return type should be `void` here.
-  if (onError != null &&
-      onError is! ZoneBinaryCallback<dynamic, Object, StackTrace> &&
-      onError is! ZoneUnaryCallback<dynamic, Object>) {
-    throw new ArgumentError("onError callback must take an Object (the error), "
-        "or an Object (the error) and a StackTrace");
+  if (onError == null) {
+    return _runZoned<R>(body, zoneValues, zoneSpecification);
   }
-  HandleUncaughtErrorHandler errorHandler;
-  if (onError != null) {
-    errorHandler = (Zone self, ZoneDelegate parent, Zone zone, error,
-        StackTrace stackTrace) {
-      try {
-        if (onError is void Function(Object, StackTrace)) {
-          self.parent.runBinary(onError, error, stackTrace);
-          return;
-        }
-        assert(onError is void Function(Object));
-        self.parent.runUnary(onError, error);
-      } catch (e, s) {
-        if (identical(e, error)) {
-          parent.handleUncaughtError(zone, error, stackTrace);
-        } else {
-          parent.handleUncaughtError(zone, e, s);
-        }
+  void Function(Object) unaryOnError;
+  void Function(Object, StackTrace) binaryOnError;
+  if (onError is void Function(Object)) {
+    unaryOnError = onError;
+  } else if (onError is void Function(Object, StackTrace)) {
+    binaryOnError = onError;
+  } else {
+    throw new ArgumentError("onError callback must take either an Object "
+        "(the error), or both an Object (the error) and a StackTrace.");
+  }
+  HandleUncaughtErrorHandler errorHandler = (Zone self, ZoneDelegate parent,
+      Zone zone, error, StackTrace stackTrace) {
+    try {
+      if (binaryOnError != null) {
+        self.parent.runBinary(binaryOnError, error, stackTrace);
+      } else {
+        assert(unaryOnError != null);
+        self.parent.runUnary(unaryOnError, error);
       }
-    };
-  }
+    } catch (e, s) {
+      if (identical(e, error)) {
+        parent.handleUncaughtError(zone, error, stackTrace);
+      } else {
+        parent.handleUncaughtError(zone, e, s);
+      }
+    }
+  };
   if (zoneSpecification == null) {
     zoneSpecification =
         new ZoneSpecification(handleUncaughtError: errorHandler);
-  } else if (errorHandler != null) {
+  } else {
     zoneSpecification = new ZoneSpecification.from(zoneSpecification,
         handleUncaughtError: errorHandler);
   }
-  Zone zone = Zone.current
-      .fork(specification: zoneSpecification, zoneValues: zoneValues);
-  if (onError != null) {
-    try {
-      return zone.run(body);
-    } catch (e, stackTrace) {
-      if (onError is ZoneBinaryCallback<R, Object, StackTrace>) {
-        zone.runBinary(onError, e, stackTrace);
-        return null;
-      }
-      assert(onError is ZoneUnaryCallback<R, Object>);
-      zone.runUnary(onError, e);
-      return null;
+  try {
+    return _runZoned<R>(body, zoneValues, zoneSpecification);
+  } catch (e, stackTrace) {
+    if (binaryOnError != null) {
+      binaryOnError(e, stackTrace);
+    } else {
+      assert(unaryOnError != null);
+      unaryOnError(e);
     }
-  } else {
-    return zone.run(body);
   }
+  return null;
 }
+
+/// Runs [body] in a new zone based on [zoneValues] and [specification].
+R _runZoned<R>(R body(), Map zoneValues, ZoneSpecification specification) =>
+    Zone.current
+        .fork(specification: specification, zoneValues: zoneValues)
+        .run<R>(body);
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 86247d3..afad926 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -396,7 +396,7 @@
    * Examples:
    *
    *     1.toStringAsPrecision(2);       // 1.0
-   *     1e15.toStringAsPrecision(3);    // 1.00+15
+   *     1e15.toStringAsPrecision(3);    // 1.00e+15
    *     1234567.toStringAsPrecision(3); // 1.23e+6
    *     1234567.toStringAsPrecision(9); // 1234567.00
    *     12345678901234567890.toStringAsPrecision(20); // 12345678901234567168
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index e0aedb9..5f39637 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -88,7 +88,11 @@
 
 import 'dart:_foreign_helper' show JS, JS_CONST, DART_CLOSURE_TO_JS;
 import 'dart:_interceptors'
-    show JavaScriptObject, UnknownJavaScriptObject, DART_CLOSURE_PROPERTY_NAME;
+    show
+        JavaScriptFunction,
+        JavaScriptObject,
+        UnknownJavaScriptObject,
+        DART_CLOSURE_PROPERTY_NAME;
 import 'dart:_js_helper'
     show Primitives, convertDartClosureToJS, getIsolateAffinityTag;
 import 'dart:_js' show isBrowserObject, convertFromBrowserObject;
@@ -99,7 +103,7 @@
 
 _convertDartFunction(Function f, {bool captureThis: false}) {
   return JS(
-      '',
+      'JavaScriptFunction',
       '''
         function(_call, f, captureThis) {
           return function() {
@@ -652,7 +656,7 @@
   var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME);
   if (existing != null) return existing;
   var ret = JS(
-      '',
+      'JavaScriptFunction',
       '''
         function(_call, f) {
           return function() {
@@ -671,7 +675,7 @@
   var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS);
   if (existing != null) return existing;
   var ret = JS(
-      '',
+      'JavaScriptFunction',
       '''
         function(_call, f) {
           return function() {
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index bbbb7b9..64f88a2 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -220,6 +220,23 @@
    *    reflected by [other].
    */
   bool operator ==(other);
+
+  /**
+   * Loads the library at the given uri into this isolate.
+   *
+   * WARNING: You are strongly encouraged to use Isolate.spawnUri instead when
+   * possible. IsolateMirror.loadUri should only be used when synchronous
+   * communication or shared state with dynamically loaded code is needed.
+   *
+   * If a library with the same canonicalized uri has already been loaded,
+   * the existing library will be returned. (The isolate will not load a new
+   * copy of the library.)
+   *
+   * This behavior is similar to the behavior of an import statement that
+   * appears in the root library, except that the import scope of the root
+   * library is not changed.
+   */
+  Future<LibraryMirror> loadUri(Uri uri);
 }
 
 /**
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 40e41df..a26dcc2 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -120,6 +120,9 @@
 LibTest/typed_data/Float32x4List/first_A01_t02: CompileTimeError # co19 issue 130 + type error
 LibTest/typed_data/Float32x4List/last_A01_t02: CompileTimeError # co19 issue 130 + type error
 
+[ $runtime != none && !$checked ]
+LibTest/async/Future/catchError_A03_t05: RuntimeError
+
 [ $runtime != none && !$strong ]
 LibTest/typed_data/Float32x4List/first_A01_t02: RuntimeError # co19 issue 130
 LibTest/typed_data/Float32x4List/last_A01_t02: RuntimeError # co19 issue 130
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 7f22c73..74c7866 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -7001,9 +7001,12 @@
 Language/Expressions/Assignment/no_such_method_t09: RuntimeError
 Language/Expressions/Constants/bitwise_operators_t05: MissingCompileTimeError
 Language/Expressions/Constants/depending_on_itself_t03: Crash
-Language/Expressions/Constants/exception_t01: MissingCompileTimeError
-Language/Expressions/Constants/exception_t02: MissingCompileTimeError
+Language/Expressions/Constants/exception_t01: MissingCompileTimeError # Larger than 64 bit int
+Language/Expressions/Constants/exception_t02: Pass
+Language/Expressions/Constants/literal_number_t01: CompileTimeError # Larger than 64 bit int
 Language/Expressions/Constants/logical_expression_t04: MissingCompileTimeError
+Language/Expressions/Constants/math_operators_t01: CompileTimeError # Larger than 64 bit int
+Language/Expressions/Constants/math_operators_t06: CompileTimeError # Larger than 64 bit int
 Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t04: Crash
 Language/Expressions/Instance_Creation/Const/exception_t01: MissingCompileTimeError
 Language/Expressions/Method_Invocation/Ordinary_Invocation/evaluation_t08: RuntimeError
@@ -7011,6 +7014,8 @@
 Language/Expressions/Method_Invocation/Super_Invocation/evaluation_t05: RuntimeError
 Language/Expressions/Method_Invocation/Super_Invocation/invocation_t02: Crash
 Language/Expressions/Null/instance_of_class_null_t01: RuntimeError
+Language/Expressions/Numbers/static_type_of_int_t01: CompileTimeError # Larger than 64 bit int
+Language/Expressions/Numbers/syntax_t10: CompileTimeError # Larger than 64 bit int
 Language/Expressions/This/placement_t04: Crash
 Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError
 Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
@@ -7047,6 +7052,30 @@
 LayoutTests/fast/canvas/gradient-addColorStop-with-invalid-color_t01: Pass, RuntimeError
 LayoutTests/fast/canvas/rgba-parsing_t01: Pass, RuntimeError
 LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError
+LibTest/core/double/isInfinite_A01_t03: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/abs_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/ceilToDouble_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/ceil_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/floorToDouble_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/floor_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/isInfinite_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/isNaN_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/isNegative_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_GE_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_LE_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_division_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_multiplication_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_remainder_A01_t02: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_subtraction_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_truncating_division_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/operator_unary_minus_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/parse_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/remainder_A01_t02: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/roundToDouble_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/round_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/toInt_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/truncateToDouble_A01_t01: CompileTimeError # Larger than 64 bit int
+LibTest/core/int/truncate_A01_t01: CompileTimeError # Larger than 64 bit int
 LibTest/html/Document/dispatchEvent_A01_t01: Crash
 LibTest/html/Document/on_A01_t01: Crash
 LibTest/html/Document/on_A01_t02: Crash
@@ -7076,6 +7105,7 @@
 LibTest/html/Window/requestFileSystem_A01_t01: Crash
 LibTest/html/Window/requestFileSystem_A01_t02: Crash
 LibTest/html/Window/requestFileSystem_A02_t01: Crash
+LibTest/math/pow_A10_t01: CompileTimeError # Larger than 64 bit int
 WebPlatformTest/html/semantics/embedded-content/the-audio-element/audio_constructor_t01: RuntimeError
 
 [ $compiler == dart2js && $fasta && $host_checked ]
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index dfd4e39..94f990f 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -57,6 +57,7 @@
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t02: MissingCompileTimeError
 Language/Classes/Constructors/Constant_Constructors/invalid_constant_initializer_t02: MissingCompileTimeError
+Language/Classes/Constructors/Generative_Constructors/static_type_t01: CompileTimeError
 Language/Classes/Instance_Methods/same_name_setter_t02: CompileTimeError # Issue 14736
 Language/Classes/Setters/name_t03: CompileTimeError
 Language/Classes/Setters/name_t04: CompileTimeError
diff --git a/tests/co19_2/co19_2-runtime.status b/tests/co19_2/co19_2-runtime.status
index 5a133f5..9b057d5 100644
--- a/tests/co19_2/co19_2-runtime.status
+++ b/tests/co19_2/co19_2-runtime.status
@@ -2,6 +2,9 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+[ $runtime != none && !$checked ]
+LibTest/async/Future/catchError_A03_t05: RuntimeError
+
 [ $runtime == dart_precompiled || $runtime == flutter || $runtime == vm ]
 LayoutTests/fast/*: SkipByDesign # DOM not supported on VM.
 LibTest/html/*: SkipByDesign # dart:html not supported on VM.
diff --git a/tests/compiler/dart2js/codegen/expect_annotations_test.dart b/tests/compiler/dart2js/codegen/expect_annotations_test.dart
index e5d0770f..2b0cbfb 100644
--- a/tests/compiler/dart2js/codegen/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/codegen/expect_annotations_test.dart
@@ -6,10 +6,10 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/js_backend/annotations.dart' as optimizerHints;
-import 'package:compiler/src/types/masks.dart';
 import 'package:compiler/src/types/types.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld;
+import 'package:compiler/src/world.dart' show JClosedWorld;
 import '../inference/type_mask_test_helper.dart';
 import '../memory_compiler.dart';
 
@@ -59,7 +59,7 @@
   CompilationResult result =
       await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
   Compiler compiler = result.compiler;
-  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   Expect.isFalse(compiler.compilationFailed, 'Unsuccessful compilation');
   Expect.isNotNull(closedWorld.commonElements.expectNoInlineClass,
       'NoInlineClass is unresolved.');
diff --git a/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart
index 591d3ad..98f7718 100644
--- a/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart
@@ -34,8 +34,7 @@
         memorySourceFiles: {'main.dart': TEST},
         outputProvider: outputCollector);
     Compiler compiler = result.compiler;
-    ClosedWorldBase closedWorld =
-        compiler.resolutionWorldBuilder.closedWorldForTesting;
+    ClosedWorldBase closedWorld = compiler.backendClosedWorldForTesting;
     var elementEnvironment = closedWorld.elementEnvironment;
 
     String generated = outputCollector.getOutput('', OutputType.js);
diff --git a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
index c6d31ac..2c2b74d 100644
--- a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
+++ b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
@@ -48,7 +48,7 @@
       memorySourceFiles: {'main.dart': source}, options: options);
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
-  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   MemberEntity jsArrayIndexOf =
       findClassMember(closedWorld, 'JSArray', 'indexOf');
   ProgramLookup programLookup = new ProgramLookup(result.compiler);
diff --git a/tests/compiler/dart2js/codegen/trust_type_annotations_test.dart b/tests/compiler/dart2js/codegen/trust_type_annotations_test.dart
index 615226b..076929c 100644
--- a/tests/compiler/dart2js/codegen/trust_type_annotations_test.dart
+++ b/tests/compiler/dart2js/codegen/trust_type_annotations_test.dart
@@ -6,7 +6,7 @@
 import "package:async_helper/async_helper.dart";
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import '../memory_compiler.dart';
 
 const String TEST = """
diff --git a/tests/compiler/dart2js/codegen/type_inference8_test.dart b/tests/compiler/dart2js/codegen/type_inference8_test.dart
index 7940d5e..1b14a0b 100644
--- a/tests/compiler/dart2js/codegen/type_inference8_test.dart
+++ b/tests/compiler/dart2js/codegen/type_inference8_test.dart
@@ -7,7 +7,7 @@
 import "package:async_helper/async_helper.dart";
 import "package:compiler/src/commandline_options.dart";
 import "package:compiler/src/constants/values.dart";
-import "package:compiler/src/types/masks.dart";
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import "package:expect/expect.dart";
 import '../memory_compiler.dart';
 
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 619871d..d0fabb9 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -80,7 +80,7 @@
       outputProvider: outputCollector);
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
-  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
   FunctionEntity element =
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index f12e914..5b10bee 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -112,7 +112,7 @@
             useNewSourceInfo: compiler.options.useNewSourceInfo);
 
   @override
-  WorldImpact codegen(CodegenWorkItem work, ClosedWorld closedWorld) {
+  WorldImpact codegen(CodegenWorkItem work, JClosedWorld closedWorld) {
     compiler.test('Compiler.codegen');
     return super.codegen(work, closedWorld);
   }
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 58f7e1d..ee303c1 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -11,7 +11,6 @@
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import 'package:sourcemap_testing/src/annotated_code_helper.dart';
 
@@ -163,7 +162,7 @@
     Expect.isTrue(result.isSuccess, "Unexpected compilation error.");
   }
   Compiler compiler = result.compiler;
-  ClosedWorld closedWorld = testFrontend
+  dynamic closedWorld = testFrontend
       ? compiler.resolutionWorldBuilder.closedWorldForTesting
       : compiler.backendClosedWorldForTesting;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
@@ -692,7 +691,7 @@
               'UNEXPECTED $mode DATA for ${id.descriptor}: '
               'Object: ${actualData.objectText}\n '
               'expected: ${colorizeExpected('$expected')}\n '
-              'actual: ${colorizeActual('$actual')}');
+              'actual  : ${colorizeActual('$actual')}');
           if (filterActualData == null ||
               filterActualData(expected, actualData)) {
             hasLocalFailure = true;
diff --git a/tests/compiler/dart2js/generic_methods/generic_method_test.dart b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
index cbe8247..e907015 100644
--- a/tests/compiler/dart2js/generic_methods/generic_method_test.dart
+++ b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
@@ -182,7 +182,7 @@
       Flags.strongMode,
       Flags.disableRtiOptimization,
     ], expectedOutput: OUTPUT, printJs: args.contains('-v'));
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
     void checkMethod(String methodName,
diff --git a/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart b/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
index 6d2478b..4933012 100644
--- a/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
+++ b/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
@@ -69,7 +69,7 @@
         options: [Flags.strongMode, Flags.omitImplicitChecks]);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ProgramLookup programLookup = new ProgramLookup(compiler);
 
     void checkStubs(ClassEntity element, List<String> expectedStubs) {
diff --git a/tests/compiler/dart2js/helpers/element_lookup.dart b/tests/compiler/dart2js/helpers/element_lookup.dart
index 4ebe13a..6d24abe 100644
--- a/tests/compiler/dart2js/helpers/element_lookup.dart
+++ b/tests/compiler/dart2js/helpers/element_lookup.dart
@@ -5,9 +5,9 @@
 import 'package:compiler/src/common_elements.dart' show ElementEnvironment;
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/elements/types.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld;
+import 'package:compiler/src/world.dart' show JClosedWorld;
 
-ClassEntity findClass(ClosedWorld closedWorld, String name) {
+ClassEntity findClass(JClosedWorld closedWorld, String name) {
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   ClassEntity cls =
       elementEnvironment.lookupClass(elementEnvironment.mainLibrary, name);
@@ -22,7 +22,7 @@
 }
 
 MemberEntity findClassMember(
-    ClosedWorld closedWorld, String className, String memberName) {
+    JClosedWorld closedWorld, String className, String memberName) {
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   ClassEntity cls = findClass(closedWorld, className);
   assert(cls != null, "Class '$className' not found.");
@@ -31,7 +31,7 @@
   return member;
 }
 
-MemberEntity findMember(ClosedWorld closedWorld, String name) {
+MemberEntity findMember(JClosedWorld closedWorld, String name) {
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   MemberEntity member = elementEnvironment.lookupLibraryMember(
       elementEnvironment.mainLibrary, name);
@@ -41,12 +41,12 @@
   return member;
 }
 
-FunctionType findFunctionType(ClosedWorld closedWorld, String name) {
+FunctionType findFunctionType(JClosedWorld closedWorld, String name) {
   FunctionEntity function = findMember(closedWorld, name);
   return closedWorld.elementEnvironment.getFunctionType(function);
 }
 
-DartType findFieldType(ClosedWorld closedWorld, String name) {
+DartType findFieldType(JClosedWorld closedWorld, String name) {
   FieldEntity field = findMember(closedWorld, name);
   return closedWorld.elementEnvironment.getFieldType(field);
 }
diff --git a/tests/compiler/dart2js/inference/data/field_type.dart b/tests/compiler/dart2js/inference/data/field_type.dart
index 44168f3..51b672d 100644
--- a/tests/compiler/dart2js/inference/data/field_type.dart
+++ b/tests/compiler/dart2js/inference/data/field_type.dart
@@ -202,8 +202,7 @@
 
   /*element: A9.:[exact=A9]*/
   A9(/*[exact=JSBool]*/ x) {
-    if (x) {
-    } else {
+    if (x) {} else {
       /*update: [exact=A9]*/ f9 = "1";
     }
   }
@@ -728,8 +727,7 @@
   /*element: A29.:[exact=A29]*/
   A29(/*[exact=JSUInt31]*/ x) {
     this. /*update: [exact=A29]*/ f29a = x;
-    if (x /*invoke: [exact=JSUInt31]*/ == 0) {
-    } else {
+    if (x /*invoke: [exact=JSUInt31]*/ == 0) {} else {
       return;
     }
     this. /*update: [exact=A29]*/ f29b = x;
diff --git a/tests/compiler/dart2js/inference/data/general.dart b/tests/compiler/dart2js/inference/data/general.dart
index 1b2d806..ea317d5 100644
--- a/tests/compiler/dart2js/inference/data/general.dart
+++ b/tests/compiler/dart2js/inference/data/general.dart
@@ -306,8 +306,7 @@
 
 /*element: testIsCheck26:[subclass=JSInt]*/
 testIsCheck26(/*[null|subclass=Object]*/ a) {
-  if (a is int) {
-  } else {
+  if (a is int) {} else {
     throw 42;
   }
   return a;
@@ -315,8 +314,7 @@
 
 /*element: testIsCheck27:[subclass=JSInt]*/
 testIsCheck27(/*[null|subclass=Object]*/ a) {
-  if (a is int) {
-  } else {
+  if (a is int) {} else {
     return 42;
   }
   return a;
@@ -324,8 +322,7 @@
 
 /*element: testIsCheck28:[null|subclass=Object]*/
 testIsCheck28(/*[null|subclass=Object]*/ a) {
-  if (a is int) {
-  } else {}
+  if (a is int) {} else {}
   return a;
 }
 
@@ -347,8 +344,7 @@
 /*element: testIf2:[null|exact=JSUInt31]*/
 testIf2(/*[null|subclass=Object]*/ a) {
   var c = null;
-  if (a) {
-  } else {
+  if (a) {} else {
     c = 10;
   }
   return c;
diff --git a/tests/compiler/dart2js/inference/inference_test_helper.dart b/tests/compiler/dart2js/inference/inference_test_helper.dart
index 4094778..94d458e 100644
--- a/tests/compiler/dart2js/inference/inference_test_helper.dart
+++ b/tests/compiler/dart2js/inference/inference_test_helper.dart
@@ -9,7 +9,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/types/types.dart';
 import 'package:compiler/src/js_model/locals.dart';
 import 'package:compiler/src/kernel/element_map.dart';
diff --git a/tests/compiler/dart2js/inference/list_tracer_test.dart b/tests/compiler/dart2js/inference/list_tracer_test.dart
index e7713ce..8ee4567 100644
--- a/tests/compiler/dart2js/inference/list_tracer_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/types/masks.dart' show ContainerTypeMask, TypeMask;
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:expect/expect.dart';
 
 import 'type_mask_test_helper.dart';
diff --git a/tests/compiler/dart2js/inference/load_deferred_library_test.dart b/tests/compiler/dart2js/inference/load_deferred_library_test.dart
index 62d1b4a..0db1d83 100644
--- a/tests/compiler/dart2js/inference/load_deferred_library_test.dart
+++ b/tests/compiler/dart2js/inference/load_deferred_library_test.dart
@@ -8,10 +8,10 @@
 import 'package:compiler/src/common/names.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/kernel/element_map.dart';
 import 'package:compiler/src/types/abstract_value_domain.dart';
-import 'package:compiler/src/types/masks.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart' as ir;
@@ -45,7 +45,7 @@
       memorySourceFiles: {'main.dart': source}, options: options);
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
-  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   LibraryEntity helperLibrary =
diff --git a/tests/compiler/dart2js/inference/map_tracer_test.dart b/tests/compiler/dart2js/inference/map_tracer_test.dart
index 4336589..e383eab 100644
--- a/tests/compiler/dart2js/inference/map_tracer_test.dart
+++ b/tests/compiler/dart2js/inference/map_tracer_test.dart
@@ -6,8 +6,8 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/types/abstract_value_domain.dart';
-import 'package:compiler/src/types/masks.dart' show MapTypeMask, TypeMask;
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 
@@ -233,7 +233,7 @@
   TypeMask keyType, valueType;
   TypeGraphInferrer typesInferrer =
       compiler.globalInference.typesInferrerInternal;
-  ClosedWorld closedWorld = typesInferrer.closedWorld;
+  JClosedWorld closedWorld = typesInferrer.closedWorld;
   AbstractValueDomain commonMasks = closedWorld.abstractValueDomain;
   TypeMask emptyType = new TypeMask.nonNullEmpty();
   MemberEntity aKey = findMember(closedWorld, 'aKey');
diff --git a/tests/compiler/dart2js/inference/side_effects_test.dart b/tests/compiler/dart2js/inference/side_effects_test.dart
index e60006d..05f713e 100644
--- a/tests/compiler/dart2js/inference/side_effects_test.dart
+++ b/tests/compiler/dart2js/inference/side_effects_test.dart
@@ -28,7 +28,7 @@
 }
 
 abstract class ComputeValueMixin<T> {
-  ClosedWorld get closedWorld;
+  JClosedWorld get closedWorld;
 
   String getMemberValue(MemberEntity member) {
     if (member is FunctionEntity) {
@@ -59,7 +59,7 @@
 /// AST visitor for computing side effects data for a member.
 class SideEffectsIrComputer extends IrDataExtractor
     with ComputeValueMixin<ir.Node> {
-  final ClosedWorld closedWorld;
+  final JClosedWorld closedWorld;
   final KernelToElementMapForBuilding _elementMap;
   final ClosureDataLookup<ir.Node> _closureDataLookup;
 
diff --git a/tests/compiler/dart2js/inference/type_combination_test.dart b/tests/compiler/dart2js/inference/type_combination_test.dart
index 64216dc..23702fd 100644
--- a/tests/compiler/dart2js/inference/type_combination_test.dart
+++ b/tests/compiler/dart2js/inference/type_combination_test.dart
@@ -7,7 +7,7 @@
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/world.dart';
 import 'type_mask_test_helper.dart';
 import '../memory_compiler.dart';
@@ -104,7 +104,7 @@
   }
 }
 
-void testUnion(ClosedWorld closedWorld) {
+void testUnion(JClosedWorld closedWorld) {
   RuleSet ruleSet = new RuleSet(
       'union', (t1, t2) => simplify(t1.union(t2, closedWorld), closedWorld));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
@@ -415,7 +415,7 @@
   ruleSet.validateCoverage();
 }
 
-void testIntersection(ClosedWorld closedWorld) {
+void testIntersection(JClosedWorld closedWorld) {
   RuleSet ruleSet =
       new RuleSet('intersection', (t1, t2) => t1.intersection(t2, closedWorld));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
@@ -730,7 +730,7 @@
   ruleSet.validateCoverage();
 }
 
-void testRegressions(ClosedWorld closedWorld) {
+void testRegressions(JClosedWorld closedWorld) {
   TypeMask nonNullPotentialString =
       new TypeMask.nonNullSubtype(patternClass, closedWorld);
   Expect.equals(potentialString,
@@ -758,7 +758,7 @@
   }, beforeRun: (compiler) => compiler.stopAfterTypeInference = true);
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
-  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   CommonElements commonElements = closedWorld.commonElements;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
diff --git a/tests/compiler/dart2js/inference/type_mask2_test.dart b/tests/compiler/dart2js/inference/type_mask2_test.dart
index c5e075a..200f245 100644
--- a/tests/compiler/dart2js/inference/type_mask2_test.dart
+++ b/tests/compiler/dart2js/inference/type_mask2_test.dart
@@ -8,8 +8,8 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/types/masks.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld;
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import 'package:compiler/src/world.dart' show JClosedWorld;
 import '../type_test_helper.dart';
 
 isCheckedMode() {
@@ -35,7 +35,7 @@
   });
 }
 
-checkMasks(ClosedWorld closedWorld, List<ClassEntity> allClasses,
+checkMasks(JClosedWorld closedWorld, List<ClassEntity> allClasses,
     List<FlatTypeMask> masks,
     {FlatTypeMask result,
     List<FlatTypeMask> disjointMasks,
@@ -105,9 +105,9 @@
         new D();
         new E();
       }
-      """);
+      """, testBackendWorld: true);
 
-  ClosedWorld closedWorld = env.closedWorld;
+  JClosedWorld closedWorld = env.jClosedWorld;
 
   ClassEntity Object_ = env.getElement("Object");
   ClassEntity A = env.getElement("A");
@@ -209,12 +209,14 @@
 }
 
 Future testStringSubtypes() async {
-  TypeEnvironment env = await TypeEnvironment.create('', mainSource: r"""
+  TypeEnvironment env = await TypeEnvironment.create('',
+      mainSource: r"""
       main() {
         '' is String;
       }
-      """);
-  ClosedWorld closedWorld = env.closedWorld;
+      """,
+      testBackendWorld: true);
+  JClosedWorld closedWorld = env.jClosedWorld;
 
   ClassEntity Object_ = env.getElement("Object");
   ClassEntity String_ = env.getElement("String");
diff --git a/tests/compiler/dart2js/inference/type_mask_disjoint_test.dart b/tests/compiler/dart2js/inference/type_mask_disjoint_test.dart
index a680f5b..c3dd1a9 100644
--- a/tests/compiler/dart2js/inference/type_mask_disjoint_test.dart
+++ b/tests/compiler/dart2js/inference/type_mask_disjoint_test.dart
@@ -7,7 +7,7 @@
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/world.dart';
 
 import '../memory_compiler.dart';
@@ -44,7 +44,7 @@
         await runCompiler(memorySourceFiles: {'main.dart': CODE});
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld world = compiler.backendClosedWorldForTesting;
+    JClosedWorld world = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = world.elementEnvironment;
 
     /// Checks the expectation of `isDisjoint` for two mask. Also checks that
diff --git a/tests/compiler/dart2js/inference/type_mask_test.dart b/tests/compiler/dart2js/inference/type_mask_test.dart
index 4561962..c22d721 100644
--- a/tests/compiler/dart2js/inference/type_mask_test.dart
+++ b/tests/compiler/dart2js/inference/type_mask_test.dart
@@ -4,7 +4,7 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart';
@@ -27,7 +27,7 @@
         await runCompiler(memorySourceFiles: {'main.dart': CODE});
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
     dynamic classA =
diff --git a/tests/compiler/dart2js/inference/type_mask_test_helper.dart b/tests/compiler/dart2js/inference/type_mask_test_helper.dart
index f979741..025d218 100644
--- a/tests/compiler/dart2js/inference/type_mask_test_helper.dart
+++ b/tests/compiler/dart2js/inference/type_mask_test_helper.dart
@@ -4,12 +4,12 @@
 
 library type_mask_test_helper;
 
-import 'package:compiler/src/types/masks.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld;
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import 'package:compiler/src/world.dart' show JClosedWorld;
 
 export 'package:compiler/src/types/types.dart';
 
-TypeMask simplify(TypeMask mask, ClosedWorld closedWorld) {
+TypeMask simplify(TypeMask mask, JClosedWorld closedWorld) {
   if (mask is ForwardingTypeMask) {
     return simplify(mask.forwardTo, closedWorld);
   } else if (mask is UnionTypeMask) {
@@ -19,7 +19,7 @@
   }
 }
 
-TypeMask interceptorOrComparable(ClosedWorld closedWorld,
+TypeMask interceptorOrComparable(JClosedWorld closedWorld,
     {bool nullable: false}) {
   // TODO(johnniwinther): The mock libraries are missing 'Comparable' and
   // therefore consider the union of for instance 'String' and 'num' to be
diff --git a/tests/compiler/dart2js/inference/union_type_test.dart b/tests/compiler/dart2js/inference/union_type_test.dart
index 37f4e29..a34dceb 100644
--- a/tests/compiler/dart2js/inference/union_type_test.dart
+++ b/tests/compiler/dart2js/inference/union_type_test.dart
@@ -4,7 +4,7 @@
 
 import "package:async_helper/async_helper.dart";
 import "package:expect/expect.dart";
-import "package:compiler/src/types/masks.dart";
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import "package:compiler/src/world.dart";
 import '../type_test_helper.dart';
 
@@ -18,8 +18,8 @@
         new A();
         new B();
       }
-      """);
-    ClosedWorld world = env.closedWorld;
+      """, testBackendWorld: true);
+    JClosedWorld world = env.jClosedWorld;
     FlatTypeMask mask1 = new FlatTypeMask.exact(env.getClass('A'));
     FlatTypeMask mask2 = new FlatTypeMask.exact(env.getClass('B'));
     UnionTypeMask union1 = mask1.nonNullable().union(mask2, world);
diff --git a/tests/compiler/dart2js/inlining/meta_annotations_test.dart b/tests/compiler/dart2js/inlining/meta_annotations_test.dart
index e8aa7c3..9ee5314 100644
--- a/tests/compiler/dart2js/inlining/meta_annotations_test.dart
+++ b/tests/compiler/dart2js/inlining/meta_annotations_test.dart
@@ -8,7 +8,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/annotations.dart' as optimizerHints;
-import 'package:compiler/src/world.dart' show ClosedWorld;
+import 'package:compiler/src/world.dart' show KClosedWorld;
 import '../memory_compiler.dart';
 
 const Map MEMORY_SOURCE_FILES = const {
@@ -37,7 +37,7 @@
     CompilationResult result =
         await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld =
+    KClosedWorld closedWorld =
         compiler.resolutionWorldBuilder.closedWorldForTesting;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     Expect.isFalse(compiler.compilationFailed, 'Unsuccessful compilation');
diff --git a/tests/compiler/dart2js/js/js_parser_test.dart b/tests/compiler/dart2js/js/js_parser_test.dart
index ac5c6a0..8c82b34 100644
--- a/tests/compiler/dart2js/js/js_parser_test.dart
+++ b/tests/compiler/dart2js/js/js_parser_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions= --no_limit_ints_to_64_bits
 import 'package:expect/expect.dart';
 import 'package:compiler/src/js/js.dart' as jsAst;
 import 'package:compiler/src/js/js.dart' show js;
@@ -107,7 +106,7 @@
   // Good hex constants.
   testExpression('var x = 0xff');
   testExpression('var x = 0xff + 0xff');
-  testExpression('var x = 0xaF + 0x0123456789abcdefABCDEF');
+  testExpression('var x = 0xaF + 0x0123456789abcdefA');
   // All sorts of keywords are allowed as property names in ES5.
   testExpression('x.new = 0');
   testExpression('x.delete = 0');
diff --git a/tests/compiler/dart2js/jsinterop/world_test.dart b/tests/compiler/dart2js/jsinterop/world_test.dart
index a691e29..c47be24 100644
--- a/tests/compiler/dart2js/jsinterop/world_test.dart
+++ b/tests/compiler/dart2js/jsinterop/world_test.dart
@@ -94,7 +94,7 @@
       return cls;
     }
 
-    ClosedWorld world = compiler.backendClosedWorldForTesting;
+    JClosedWorld world = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = world.elementEnvironment;
     ClassEntity Object_ = registerClass(world.commonElements.objectClass);
     ClassEntity Interceptor =
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index 401c441..af328ef 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -56,7 +56,7 @@
         new G();
       }
       """);
-  ClosedWorld world = env.closedWorld;
+  KClosedWorld world = env.kClosedWorld;
 
   ClassEntity A = env.getClass("A");
   ClassEntity B = env.getClass("B");
@@ -386,7 +386,7 @@
         new I();
       }
       """);
-  ClosedWorld world = env.closedWorld;
+  KClosedWorld world = env.kClosedWorld;
 
   ClassEntity A = env.getClass("A");
   ClassEntity B = env.getClass("B");
@@ -603,7 +603,7 @@
       """,
       options: strongMode ? [Flags.strongMode] : [],
       testBackendWorld: true);
-  ClosedWorld world = env.closedWorld;
+  JClosedWorld world = env.jClosedWorld;
 
   ClassEntity functionClass = world.commonElements.functionClass;
   ClassEntity closureClass = world.commonElements.closureClass;
diff --git a/tests/compiler/dart2js/model/enqueuer_test.dart b/tests/compiler/dart2js/model/enqueuer_test.dart
index 1912168..6407ea4 100644
--- a/tests/compiler/dart2js/model/enqueuer_test.dart
+++ b/tests/compiler/dart2js/model/enqueuer_test.dart
@@ -13,7 +13,7 @@
 import 'package:compiler/src/elements/names.dart';
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/enqueue.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/universe/call_structure.dart';
 import 'package:compiler/src/universe/selector.dart';
 import 'package:compiler/src/universe/world_impact.dart';
@@ -188,7 +188,7 @@
       ElementEnvironment elementEnvironment,
       String className,
       String methodName,
-      ReceiverConstraint Function(ClassEntity cls) createConstraint) {
+      Object Function(ClassEntity cls) createConstraint) {
     ClassEntity cls = elementEnvironment.lookupClass(
         elementEnvironment.mainLibrary, className);
     Selector selector = new Selector.call(
@@ -200,11 +200,8 @@
     enqueuer.applyImpact(impact);
   }
 
-  void applyImpact(
-      Enqueuer enqueuer,
-      ElementEnvironment elementEnvironment,
-      Impact impact,
-      ReceiverConstraint Function(ClassEntity cls) createConstraint) {
+  void applyImpact(Enqueuer enqueuer, ElementEnvironment elementEnvironment,
+      Impact impact, Object Function(ClassEntity cls) createConstraint) {
     switch (impact.kind) {
       case ImpactKind.instantiate:
         instantiate(enqueuer, elementEnvironment, impact.clsName);
@@ -253,7 +250,7 @@
         compiler.frontendStrategy.elementEnvironment;
     checkInvariant(enqueuer, elementEnvironment);
 
-    ReceiverConstraint createConstraint(ClassEntity cls) {
+    Object createConstraint(ClassEntity cls) {
       return new StrongModeConstraint(cls);
     }
 
@@ -263,12 +260,12 @@
   };
   compiler.onCodegenQueueEmptyForTesting = () {
     Enqueuer enqueuer = compiler.enqueuer.codegenEnqueuerForTesting;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment =
         compiler.backendClosedWorldForTesting.elementEnvironment;
     checkInvariant(enqueuer, elementEnvironment);
 
-    ReceiverConstraint createConstraint(ClassEntity cls) {
+    Object createConstraint(ClassEntity cls) {
       return new TypeMask.subtype(cls, closedWorld);
     }
 
diff --git a/tests/compiler/dart2js/model/forwarding_stub_test.dart b/tests/compiler/dart2js/model/forwarding_stub_test.dart
index ed86ed3..234f97b 100644
--- a/tests/compiler/dart2js/model/forwarding_stub_test.dart
+++ b/tests/compiler/dart2js/model/forwarding_stub_test.dart
@@ -30,7 +30,7 @@
         memorySourceFiles: {'main.dart': source}, options: [Flags.strongMode]));
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     ClassEntity cls =
         elementEnvironment.lookupClass(elementEnvironment.mainLibrary, 'Class');
diff --git a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
index 16a33bd..59a8afd7 100644
--- a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
@@ -171,7 +171,7 @@
     'Q': ['method3'],
   };
 
-  ClosedWorld closedWorld =
+  KClosedWorld closedWorld =
       compiler.resolutionWorldBuilder.closedWorldForTesting;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
diff --git a/tests/compiler/dart2js/model/strong_mode_impact_test.dart b/tests/compiler/dart2js/model/strong_mode_impact_test.dart
index 907a0cc..10400b8 100644
--- a/tests/compiler/dart2js/model/strong_mode_impact_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_impact_test.dart
@@ -97,7 +97,7 @@
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
 
-  ClosedWorld closedWorld =
+  KClosedWorld closedWorld =
       compiler.resolutionWorldBuilder.closedWorldForTesting;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
diff --git a/tests/compiler/dart2js/model/subtypeset_test.dart b/tests/compiler/dart2js/model/subtypeset_test.dart
index af5d652..c48b5bb 100644
--- a/tests/compiler/dart2js/model/subtypeset_test.dart
+++ b/tests/compiler/dart2js/model/subtypeset_test.dart
@@ -52,7 +52,7 @@
         new G();
       }
       """, options: strongMode ? [Flags.strongMode] : []);
-  ClosedWorld world = env.closedWorld;
+  KClosedWorld world = env.kClosedWorld;
 
   ClassEntity A = env.getElement("A");
   ClassEntity B = env.getElement("B");
diff --git a/tests/compiler/dart2js/model/world_test.dart b/tests/compiler/dart2js/model/world_test.dart
index e56ce30..3abdd5d 100644
--- a/tests/compiler/dart2js/model/world_test.dart
+++ b/tests/compiler/dart2js/model/world_test.dart
@@ -10,7 +10,7 @@
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/universe/class_set.dart';
-import 'package:compiler/src/world.dart' show ClassQuery, ClosedWorld;
+import 'package:compiler/src/world.dart' show ClassQuery, JClosedWorld;
 import '../type_test_helper.dart';
 
 void main() {
@@ -51,8 +51,8 @@
         html.window;
         new html.Worker('');
       }
-      """);
-  ClosedWorld closedWorld = env.closedWorld;
+      """, testBackendWorld: true);
+  JClosedWorld closedWorld = env.jClosedWorld;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
   ClassEntity Object_ = env.getElement("Object");
@@ -242,8 +242,8 @@
         new G3();
         new H4();
       }
-      """);
-  ClosedWorld closedWorld = env.closedWorld;
+      """, testBackendWorld: true);
+  JClosedWorld closedWorld = env.jClosedWorld;
 
   check(String name, {bool hasStrictSubtype, bool hasOnlySubclasses}) {
     ClassEntity cls = env.getElement(name);
@@ -309,7 +309,8 @@
 }
 
 testNativeClasses() async {
-  var env = await TypeEnvironment.create('', mainSource: r"""
+  var env = await TypeEnvironment.create('',
+      mainSource: r"""
       import 'dart:html' as html;
       main() {
         html.window; // Creates 'Window'.
@@ -317,8 +318,9 @@
         new html.CanvasElement() // Creates CanvasElement
             ..getContext(''); // Creates CanvasRenderingContext2D
       }
-      """);
-  ClosedWorld closedWorld = env.closedWorld;
+      """,
+      testBackendWorld: true);
+  JClosedWorld closedWorld = env.jClosedWorld;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   LibraryEntity dart_html = elementEnvironment.lookupLibrary(Uris.dart_html);
 
@@ -517,7 +519,8 @@
 }
 
 testCommonSubclasses() async {
-  var env = await TypeEnvironment.create('', mainSource: r"""
+  var env = await TypeEnvironment.create('',
+      mainSource: r"""
       class A {}
       class B {}
       class C extends A {}
@@ -540,8 +543,9 @@
         new I();
         new J();
       }
-      """);
-  ClosedWorld closedWorld = env.closedWorld;
+      """,
+      testBackendWorld: true);
+  JClosedWorld closedWorld = env.jClosedWorld;
 
   ClassEntity A = env.getElement("A");
   ClassEntity B = env.getElement("B");
diff --git a/tests/compiler/dart2js/needs_no_such_method_test.dart b/tests/compiler/dart2js/needs_no_such_method_test.dart
index e216047..68c216b 100644
--- a/tests/compiler/dart2js/needs_no_such_method_test.dart
+++ b/tests/compiler/dart2js/needs_no_such_method_test.dart
@@ -9,7 +9,7 @@
 import 'package:compiler/src/elements/names.dart';
 import 'package:compiler/src/universe/call_structure.dart';
 import 'package:compiler/src/universe/selector.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld, ClassQuery;
+import 'package:compiler/src/world.dart' show JClosedWorld, ClassQuery;
 import 'type_test_helper.dart';
 
 void main() {
@@ -33,7 +33,7 @@
 
 testClassSets() async {
   Selector foo, bar, baz;
-  ClosedWorld closedWorld;
+  JClosedWorld closedWorld;
   ClassEntity superclass, subclass, subtype;
   String testMode;
 
@@ -46,13 +46,13 @@
     main.write('}');
     testMode = '$instantiated';
 
-    var env =
-        await TypeEnvironment.create(CLASSES, mainSource: main.toString());
+    var env = await TypeEnvironment.create(CLASSES,
+        mainSource: main.toString(), testBackendWorld: true);
     foo = new Selector.call(const PublicName('foo'), CallStructure.NO_ARGS);
     bar = new Selector.call(const PublicName('bar'), CallStructure.NO_ARGS);
     baz = new Selector.call(const PublicName('baz'), CallStructure.NO_ARGS);
 
-    closedWorld = env.closedWorld;
+    closedWorld = env.jClosedWorld;
     superclass = env.getElement('Superclass');
     subclass = env.getElement('Subclass');
     subtype = env.getElement('Subtype');
diff --git a/tests/compiler/dart2js/no_such_method_enabled_test.dart b/tests/compiler/dart2js/no_such_method_enabled_test.dart
index 1142b92..f16b55b 100644
--- a/tests/compiler/dart2js/no_such_method_enabled_test.dart
+++ b/tests/compiler/dart2js/no_such_method_enabled_test.dart
@@ -229,7 +229,7 @@
   NoSuchMethodResolver resolver = registry.internalResolverForTesting;
   FunctionEntity ObjectNSM = frontendEnvironment.lookupClassMember(
       compiler.frontendStrategy.commonElements.objectClass, 'noSuchMethod');
-  ClosedWorld backendClosedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld backendClosedWorld = compiler.backendClosedWorldForTesting;
   ElementEnvironment backendEnvironment = backendClosedWorld.elementEnvironment;
   NoSuchMethodDataImpl data = backendClosedWorld.noSuchMethodData;
 
diff --git a/tests/compiler/dart2js/receiver_type_test.dart b/tests/compiler/dart2js/receiver_type_test.dart
index ac1c71f..50b8fc3 100644
--- a/tests/compiler/dart2js/receiver_type_test.dart
+++ b/tests/compiler/dart2js/receiver_type_test.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/universe/selector.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
@@ -44,7 +44,7 @@
     'C': '[exact=C]',
   };
 
-  ClosedWorld closedWorld = env.closedWorld;
+  JClosedWorld closedWorld = env.jClosedWorld;
   int closureCount = 0;
   Selector callSelector = new Selector.callClosure(0);
   closedWorld.forEachStrictSubclassOf(closedWorld.commonElements.objectClass,
diff --git a/tests/compiler/dart2js/rti/backend_type_helper_test.dart b/tests/compiler/dart2js/rti/backend_type_helper_test.dart
index 2549436..6bccaa8 100644
--- a/tests/compiler/dart2js/rti/backend_type_helper_test.dart
+++ b/tests/compiler/dart2js/rti/backend_type_helper_test.dart
@@ -19,7 +19,7 @@
         entryPoint: Platform.script.resolve('data/subtype_named_args.dart'));
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ProgramLookup programLookup = new ProgramLookup(compiler);
 
     List<ClassEntity> found = <ClassEntity>[];
diff --git a/tests/compiler/dart2js/rti/data/function_subtype_local5.dart b/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
index 6fb64c6..7119670 100644
--- a/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
+++ b/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
@@ -14,7 +14,7 @@
 typedef int Boz<T>(T a);
 typedef int Biz<T>(T a, int b);
 
-/*class: C:explicit=[int Function(C.T),int Function(C.T,[String]),int Function(C.T,int),int Function(C.T,{,b:String})],needsArgs*/
+/*class: C:direct,explicit=[int Function(C.T),int Function(C.T,[String]),int Function(C.T,int),int Function(C.T,{,b:String})],needsArgs*/
 class C<T> {
   void test(String nameOfT, bool expectedResult) {
     // TODO(johnniwinther): Optimize local function type signature need.
diff --git a/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05_strong.dart b/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05_strong.dart
index 6208ec6..f438d3f 100644
--- a/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05_strong.dart
+++ b/tests/compiler/dart2js/rti/data/generic_methods_dynamic_05_strong.dart
@@ -20,7 +20,7 @@
 
 class C {
   /*!strong.element: C.bar:needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
-  /*strong.element: C.bar:explicit=[Iterable<bar.T>],implicit=[bar.T],indirect,needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
+  /*strong.element: C.bar:direct,explicit=[Iterable<bar.T>],implicit=[bar.T],needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
   List<T> bar<T>(Iterable<T> t) => <T>[t.first];
 }
 
diff --git a/tests/compiler/dart2js/rti/data/indirect_through_static.dart b/tests/compiler/dart2js/rti/data/indirect_through_static.dart
new file mode 100644
index 0000000..6359003
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/indirect_through_static.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, 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.
+
+/*kernel.class: A:*/
+/*!kernel.class: A:implicit=[A]*/
+abstract class A {}
+
+class B implements A {}
+
+/*kernel.class: C:
+ deps=[lookup],
+ explicit=[C<lookup.T>]
+*/
+/*strong.class: C:
+  deps=[lookup],
+  explicit=[C<lookup.T>,Map<String,C>],
+  implicit=[C],
+  needsArgs
+*/
+/*omit.class: C:
+ deps=[lookup],explicit=[C<lookup.T>],
+ needsArgs
+*/
+class C<T> {}
+
+final Map<String, C> map = {};
+
+void setup() {
+  map['x'] = new C<B>();
+}
+
+/*kernel.element: lookup:direct,explicit=[C<lookup.T>]*/
+/*!kernel.element: lookup:direct,explicit=[C<lookup.T>],needsArgs*/
+C<T> lookup<T>(String key) {
+  final value = map[key];
+  if (value != null && value is C<T>) {
+    return value;
+  }
+  throw 'Invalid C value for $key: ${value}';
+}
+
+void lookupA() {
+  lookup<A>('x');
+}
+
+main() {
+  setup();
+  lookupA();
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart b/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart
index 30702fe..ebdd352 100644
--- a/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart
+++ b/tests/compiler/dart2js/rti/data/local_function_map_literal_strong.dart
@@ -4,7 +4,7 @@
 
 import 'package:expect/expect.dart';
 
-/*strong.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*strong.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 /*omit.class: global#LinkedHashMap:deps=[Map],needsArgs*/
 
 /*strong.element: method:implicit=[method.T],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/map_literal.dart b/tests/compiler/dart2js/rti/data/map_literal.dart
index 2f04d3b..8376333 100644
--- a/tests/compiler/dart2js/rti/data/map_literal.dart
+++ b/tests/compiler/dart2js/rti/data/map_literal.dart
@@ -6,7 +6,7 @@
 /*strong.class: global#Map:explicit=[Map],indirect,needsArgs*/
 
 /*!strong.class: global#LinkedHashMap:deps=[Map]*/
-/*strong.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*strong.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 
 /*!strong.class: global#JsLinkedHashMap:deps=[LinkedHashMap]*/
 /*strong.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/map_literal_checked.dart b/tests/compiler/dart2js/rti/data/map_literal_checked.dart
index 9c6733f..d48447a 100644
--- a/tests/compiler/dart2js/rti/data/map_literal_checked.dart
+++ b/tests/compiler/dart2js/rti/data/map_literal_checked.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*class: global#Map:explicit=[Map],indirect,needsArgs*/
-/*class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 /*class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[Iterable<JsLinkedHashMap.K>,JsLinkedHashMap.K,JsLinkedHashMap.V,JsLinkedHashMap<JsLinkedHashMap.K,JsLinkedHashMap.V>,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
 /*class: global#double:explicit=[double],implicit=[double]*/
 /*class: global#JSDouble:*/
diff --git a/tests/compiler/dart2js/rti/data/map_literal_strong.dart b/tests/compiler/dart2js/rti/data/map_literal_strong.dart
index 4c0bf5f..92bb292 100644
--- a/tests/compiler/dart2js/rti/data/map_literal_strong.dart
+++ b/tests/compiler/dart2js/rti/data/map_literal_strong.dart
@@ -5,7 +5,7 @@
 /*strong.class: global#Map:explicit=[Map],indirect,needsArgs*/
 /*omit.class: global#Map:*/
 
-/*strong.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*strong.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 /*omit.class: global#LinkedHashMap:deps=[Map]*/
 
 /*strong.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/map_to_set.dart b/tests/compiler/dart2js/rti/data/map_to_set.dart
index 06d337a..073f358 100644
--- a/tests/compiler/dart2js/rti/data/map_to_set.dart
+++ b/tests/compiler/dart2js/rti/data/map_to_set.dart
@@ -6,7 +6,7 @@
 /*strong.class: global#Map:deps=[Class,JsLinkedHashMap,MapMixin],explicit=[Map,Map<JsLinkedHashMap.K,JsLinkedHashMap.V>,Map<MapMixin.K,MapMixin.V>],indirect,needsArgs*/
 
 /*!strong.class: global#LinkedHashMap:deps=[Map],needsArgs*/
-/*strong.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*strong.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 
 /*!strong.class: global#JsLinkedHashMap:deps=[LinkedHashMap],implicit=[JsLinkedHashMap.K],needsArgs*/
 /*strong.class: global#JsLinkedHashMap:deps=[LinkedHashMap],explicit=[JsLinkedHashMap.K,JsLinkedHashMap.V,Map<JsLinkedHashMap.K,JsLinkedHashMap.V>,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/map_to_set_strong.dart b/tests/compiler/dart2js/rti/data/map_to_set_strong.dart
index 641baca..89dfbbe 100644
--- a/tests/compiler/dart2js/rti/data/map_to_set_strong.dart
+++ b/tests/compiler/dart2js/rti/data/map_to_set_strong.dart
@@ -5,7 +5,7 @@
 /*strong.class: global#Map:deps=[Class,JsLinkedHashMap,MapMixin],explicit=[Map,Map<JsLinkedHashMap.K,JsLinkedHashMap.V>,Map<MapMixin.K,MapMixin.V>],indirect,needsArgs*/
 /*omit.class: global#Map:deps=[Class],needsArgs*/
 
-/*strong.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*strong.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 /*omit.class: global#LinkedHashMap:deps=[Map],needsArgs*/
 
 /*strong.class: global#JsLinkedHashMap:deps=[LinkedHashMap],explicit=[JsLinkedHashMap.K,JsLinkedHashMap.V,Map<JsLinkedHashMap.K,JsLinkedHashMap.V>,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/type_variable_function_type.dart b/tests/compiler/dart2js/rti/data/type_variable_function_type.dart
index 53e53f3..b4a7f70 100644
--- a/tests/compiler/dart2js/rti/data/type_variable_function_type.dart
+++ b/tests/compiler/dart2js/rti/data/type_variable_function_type.dart
@@ -8,7 +8,7 @@
 
 typedef T Func<T>();
 
-/*class: Foo:explicit=[Foo.S Function()],needsArgs*/
+/*class: Foo:direct,explicit=[Foo.S Function()],needsArgs*/
 class Foo<S> {
   m(x) => x is Func<S>;
 }
diff --git a/tests/compiler/dart2js/rti/disable_rti_test.dart b/tests/compiler/dart2js/rti/disable_rti_test.dart
index c420f57..a199849 100644
--- a/tests/compiler/dart2js/rti/disable_rti_test.dart
+++ b/tests/compiler/dart2js/rti/disable_rti_test.dart
@@ -62,7 +62,7 @@
         options: [Flags.disableRtiOptimization, Flags.disableInlining]);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
     ProgramLookup programLookup = new ProgramLookup(compiler);
diff --git a/tests/compiler/dart2js/rti/emission/indirect_through_static.dart b/tests/compiler/dart2js/rti/emission/indirect_through_static.dart
new file mode 100644
index 0000000..a80da25
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/indirect_through_static.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2018, 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.
+
+/*kernel.class: A:*/
+/*!kernel.class: A:checkedInstance,checks=[],typeArgument*/
+abstract class A {}
+
+/*kernel.class: B:checks=[],typeArgument*/
+/*!kernel.class: B:checks=[$isA],typeArgument*/
+class B implements A {}
+
+/*kernel.class: C:checks=[],instance*/
+/*!kernel.class: C:checkedInstance,checks=[],instance,typeArgument*/
+class C<T> {}
+
+final Map<String, C> map = {};
+
+void setup() {
+  map['x'] = new C<B>();
+}
+
+C<T> lookup<T>(String key) {
+  final value = map[key];
+  if (value != null && value is C<T>) {
+    return value;
+  }
+  throw 'Invalid C value for $key: ${value}';
+}
+
+void lookupA() {
+  lookup<A>('x');
+}
+
+main() {
+  setup();
+  lookupA();
+}
diff --git a/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart b/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart
new file mode 100644
index 0000000..de9bc8b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2018, 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.
+
+// dart2jsOptions=--strong
+
+@JS()
+library foo;
+
+/*class: global#JavaScriptObject:checks=[$asA,$isA]*/
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+/*kernel.class: A:checkedTypeArgument,checks=[],typeArgument*/
+/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+@JS()
+@anonymous
+class A<T> {
+  external factory A();
+}
+
+/*class: Class1:checks=[],instance*/
+class Class1<T> {
+  method() {
+    // This caused and assertion failure in codegen.
+    test1(new List<A<T>>.from([]));
+  }
+}
+
+/*class: Class2:checks=[],instance*/
+class Class2<T> {
+  method() {
+    // This caused and assertion failure in codegen.
+    test2(new List<A<T> Function()>.from([]));
+  }
+}
+
+main() {
+  new Class1<int>().method();
+  new Class1<String>().method();
+  new Class2<int>().method();
+  new Class2<String>().method();
+}
+
+test1(o) {
+  Expect.isTrue(o is List<A<int>>, "Expected $o to be List<A<int>>");
+  Expect.isTrue(o is List<A<String>>, "Expected $o to be List<A<String>>");
+}
+
+test2(o) {
+  Expect.isTrue(o is List<A<int> Function()>,
+      "Expected $o to be List<A<int> Function()>");
+  Expect.isTrue(o is List<A<String> Function()>,
+      "Expected $o to be List<A<String> Function()>");
+}
diff --git a/tests/compiler/dart2js/rti/factory_call_test.dart b/tests/compiler/dart2js/rti/factory_call_test.dart
index 9d3f08f..5c0628e 100644
--- a/tests/compiler/dart2js/rti/factory_call_test.dart
+++ b/tests/compiler/dart2js/rti/factory_call_test.dart
@@ -43,7 +43,7 @@
         memorySourceFiles: {'main.dart': code}, options: [Flags.strongMode]);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     ProgramLookup programLookup = new ProgramLookup(compiler);
diff --git a/tests/compiler/dart2js/rti/instance_call_test.dart b/tests/compiler/dart2js/rti/instance_call_test.dart
index 337bae0..9d220f9 100644
--- a/tests/compiler/dart2js/rti/instance_call_test.dart
+++ b/tests/compiler/dart2js/rti/instance_call_test.dart
@@ -103,7 +103,7 @@
         options: [Flags.strongMode, Flags.omitImplicitChecks]);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     ProgramLookup programLookup = new ProgramLookup(compiler);
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index d7a44f5..7386d6a 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -113,10 +113,10 @@
         .contains(frontendClass)) {
       features.add(Tags.typeLiteral);
     }
-    if (rtiNeedBuilder.typeVariableTestsForTesting.directClassTests
+    if (rtiNeedBuilder.typeVariableTestsForTesting.directClassTestsForTesting
         .contains(frontendClass)) {
       features.add(Tags.directTypeArgumentTest);
-    } else if (rtiNeedBuilder.typeVariableTestsForTesting.classTests
+    } else if (rtiNeedBuilder.typeVariableTestsForTesting.classTestsForTesting
         .contains(frontendClass)) {
       features.add(Tags.indirectTypeArgumentTest);
     }
@@ -143,10 +143,12 @@
 
       void addFrontendData(Entity entity) {
         findDependencies(features, entity);
-        if (rtiNeedBuilder.typeVariableTestsForTesting.directMethodTests
+        if (rtiNeedBuilder
+            .typeVariableTestsForTesting.directMethodTestsForTesting
             .contains(entity)) {
           features.add(Tags.directTypeArgumentTest);
-        } else if (rtiNeedBuilder.typeVariableTestsForTesting.methodTests
+        } else if (rtiNeedBuilder
+            .typeVariableTestsForTesting.methodTestsForTesting
             .contains(entity)) {
           features.add(Tags.indirectTypeArgumentTest);
         }
diff --git a/tests/compiler/dart2js/rti/type_representation_test.dart b/tests/compiler/dart2js/rti/type_representation_test.dart
index 167ab47..ffb6fbd 100644
--- a/tests/compiler/dart2js/rti/type_representation_test.dart
+++ b/tests/compiler/dart2js/rti/type_representation_test.dart
@@ -109,7 +109,7 @@
     return stringify(name);
   }
 
-  ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+  JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
   String func = backend.namer.functionTypeTag;
   String ret = backend.namer.functionTypeReturnTypeTag;
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index 51e1680..1aed7af 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -13,7 +13,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/frontend_strategy.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld;
+import 'package:compiler/src/world.dart' show JClosedWorld, KClosedWorld;
 import 'memory_compiler.dart' as memory;
 
 DartType instantiate(ClassEntity element, List<DartType> arguments) {
@@ -193,12 +193,14 @@
     return types.isPotentialSubtype(T, S);
   }
 
-  ClosedWorld get closedWorld {
-    if (testBackendWorld) {
-      return compiler.backendClosedWorldForTesting;
-    } else {
-      return compiler.resolutionWorldBuilder.closedWorldForTesting;
-    }
+  JClosedWorld get jClosedWorld {
+    assert(testBackendWorld);
+    return compiler.backendClosedWorldForTesting;
+  }
+
+  KClosedWorld get kClosedWorld {
+    assert(!testBackendWorld);
+    return compiler.resolutionWorldBuilder.closedWorldForTesting;
   }
 }
 
diff --git a/tests/compiler/dart2js_extra/33296_test.dart b/tests/compiler/dart2js_extra/33296_test.dart
new file mode 100644
index 0000000..7d06619
--- /dev/null
+++ b/tests/compiler/dart2js_extra/33296_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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:html'; // TODO(33316): Remove.
+import "package:expect/expect.dart";
+
+main() {
+  var f = () => [];
+  Expect.isTrue(f is List Function());
+  Expect.isFalse(f is int Function(int));
+
+  var g = allowInterop(f);
+  // g is inferred to have the same type as f.
+  Expect.isTrue(g is List Function());
+  // The JavaScriptFunction matches any function type.
+  Expect.isTrue(g is int Function(int));
+
+  if (false) new DivElement(); // TODO(33316): Remove.
+}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index f60ebac..0040688 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -128,7 +128,9 @@
 closure_capture2_test: RuntimeError
 closure_type_reflection2_test: RuntimeError
 closure_type_reflection_test: RuntimeError
-constant_javascript_semantics_test/01: MissingCompileTimeError
+constant_javascript_semantics_test/03: CompileTimeError
+constant_javascript_semantics_test/04: CompileTimeError
+constant_javascript_semantics_test/none: CompileTimeError
 deferred/deferred_mirrors1_test: SkipByDesign
 deferred/deferred_mirrors2_test: RuntimeError
 deferred/reflect_multiple_annotations_test: RuntimeError
@@ -164,6 +166,7 @@
 private_symbol_literal_test/06: MissingCompileTimeError
 reflect_native_types_test: RuntimeError
 regress/4562_test/none: CompileTimeError
+round_constant_folding_test: CompileTimeError
 type_constant_switch_test/01: MissingCompileTimeError
 
 [ $compiler == dart2js && $fasta && $minified ]
diff --git a/tests/compiler/dart2js_extra/deferred_function_types7_test.dart b/tests/compiler/dart2js_extra/deferred_function_types7_test.dart
index c3e8de0..fe7c49e 100644
--- a/tests/compiler/dart2js_extra/deferred_function_types7_test.dart
+++ b/tests/compiler/dart2js_extra/deferred_function_types7_test.dart
@@ -14,9 +14,11 @@
   Expect.isFalse(lib1.method1() is String Function(String));
   Expect.isTrue(lib1.method5 is Object Function(Null, String, int));
   Expect.isFalse(lib1.method5 is Object Function(Null, int, String));
+  Expect.isTrue(lib1.test5(lib1.method5));
   await lib2.loadLibrary();
   Expect.isFalse(lib2.method2() is int Function(int));
   Expect.isTrue(lib2.method2() is String Function(String));
   Expect.isFalse(lib2.method6 is Object Function(Null, String, int));
   Expect.isTrue(lib2.method6 is Object Function(Null, int, String));
+  Expect.isTrue(lib2.test6(lib2.method6));
 }
diff --git a/tests/compiler/dart2js_extra/deferred_function_types8_test.dart b/tests/compiler/dart2js_extra/deferred_function_types8_test.dart
index eaa89ca..7222ef5 100644
--- a/tests/compiler/dart2js_extra/deferred_function_types8_test.dart
+++ b/tests/compiler/dart2js_extra/deferred_function_types8_test.dart
@@ -14,9 +14,11 @@
   Expect.isTrue(lib2.method2() is String Function(String));
   Expect.isFalse(lib2.method6 is Object Function(Null, String, int));
   Expect.isTrue(lib2.method6 is Object Function(Null, int, String));
+  Expect.isTrue(lib2.test6(lib2.method6));
   await lib1.loadLibrary();
   Expect.isTrue(lib1.method1() is int Function(int));
   Expect.isFalse(lib1.method1() is String Function(String));
   Expect.isTrue(lib1.method5 is Object Function(Null, String, int));
   Expect.isFalse(lib1.method5 is Object Function(Null, int, String));
+  Expect.isTrue(lib1.test5(lib1.method5));
 }
diff --git a/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart b/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart
index 4bacb61..8a3a06f 100644
--- a/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart
+++ b/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart
@@ -15,3 +15,5 @@
 test3(o) => o is Class1 Function(Class1);
 
 method5(Class1 c, String s, int i) {}
+
+test5(o) => o is Function(Class1, String, int);
diff --git a/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart b/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart
index a8abb54..a209dac 100644
--- a/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart
+++ b/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart
@@ -15,3 +15,5 @@
 test4(o) => o is Class2 Function(Class2, Class2);
 
 method6(Class2 c, int i, String s) {}
+
+test6(o) => o is Function(Class2, int, String);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 327e76e..1cb40c4 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -109,6 +109,25 @@
 package_resource_test: RuntimeError # Issue 26842
 
 [ $compiler == dart2js && $checked && $fasta ]
+big_integer_arith_vm_test/add: CompileTimeError
+big_integer_arith_vm_test/div: CompileTimeError
+big_integer_arith_vm_test/gcd: CompileTimeError
+big_integer_arith_vm_test/mod: CompileTimeError
+big_integer_arith_vm_test/modInv: CompileTimeError
+big_integer_arith_vm_test/modPow: CompileTimeError
+big_integer_arith_vm_test/mul: CompileTimeError
+big_integer_arith_vm_test/negate: CompileTimeError
+big_integer_arith_vm_test/none: CompileTimeError
+big_integer_arith_vm_test/overflow: CompileTimeError
+big_integer_arith_vm_test/shift: CompileTimeError
+big_integer_arith_vm_test/sub: CompileTimeError
+big_integer_arith_vm_test/trunDiv: CompileTimeError
+bit_twiddling_bigint_test: CompileTimeError
+bit_twiddling_test: CompileTimeError
+double_ceil_test: CompileTimeError
+double_floor_test: CompileTimeError
+double_round_test: CompileTimeError
+double_truncate_test: CompileTimeError
 from_environment_const_type_test/02: MissingCompileTimeError
 from_environment_const_type_test/03: MissingCompileTimeError
 from_environment_const_type_test/04: MissingCompileTimeError
@@ -127,60 +146,166 @@
 from_environment_const_type_undefined_test/06: MissingCompileTimeError
 from_environment_const_type_undefined_test/07: MissingCompileTimeError
 from_environment_const_type_undefined_test/08: MissingCompileTimeError
+int_ceil_test: CompileTimeError
+int_ceil_to_double_test: CompileTimeError
+int_floor_test: CompileTimeError
+int_floor_to_double_test: CompileTimeError
+int_from_environment_test: CompileTimeError
+int_modulo_arith_test/bignum: CompileTimeError
+int_modulo_arith_test/modPow: CompileTimeError
+int_modulo_arith_test/none: CompileTimeError
+int_parse_radix_test/02: CompileTimeError
+int_round_test: CompileTimeError
+int_round_to_double_test: CompileTimeError
+int_to_int_test: CompileTimeError
+int_truncate_test: CompileTimeError
+int_truncate_to_double_test: CompileTimeError
+integer_to_radix_string_test: CompileTimeError
+integer_to_string_test/01: CompileTimeError
+num_parse_test/01: CompileTimeError
+num_parse_test/none: CompileTimeError
+num_sign_test: CompileTimeError
+regress_r21715_test: CompileTimeError
 
 [ $compiler == dart2js && $fast_startup ]
 apply3_test: Fail # mirrors not supported
 
 [ $compiler == dart2js && $fasta ]
 apply3_test: RuntimeError # mirrors not supported
-big_integer_arith_vm_test/add: RuntimeError
-big_integer_arith_vm_test/div: RuntimeError
-big_integer_arith_vm_test/gcd: RuntimeError
-big_integer_arith_vm_test/mod: RuntimeError
-big_integer_arith_vm_test/modInv: RuntimeError
-big_integer_arith_vm_test/modPow: RuntimeError
-big_integer_arith_vm_test/mul: RuntimeError
-big_integer_arith_vm_test/negate: RuntimeError
-big_integer_arith_vm_test/none: RuntimeError
-big_integer_arith_vm_test/overflow: RuntimeError
-big_integer_arith_vm_test/shift: RuntimeError
-big_integer_arith_vm_test/sub: RuntimeError
-big_integer_arith_vm_test/trunDiv: RuntimeError
+big_integer_arith_vm_test/add: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/div: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/gcd: CompileTimeError # Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/mod: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/modInv: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/modPow: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/mul: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/negate: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/none: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/overflow: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/shift: CompileTimeError # Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/sub: CompileTimeError #Large integer literal. Not representable in JS.
+big_integer_arith_vm_test/trunDiv: CompileTimeError #Large integer literal. Not representable in JS.
 big_integer_parsed_arith_vm_test: RuntimeError
 big_integer_parsed_div_rem_vm_test: RuntimeError
 big_integer_parsed_mul_div_vm_test: RuntimeError
-bit_twiddling_bigint_test: RuntimeError
+bit_twiddling_bigint_test: CompileTimeError #Large integer literal. Not representable in JS.
+bit_twiddling_test: CompileTimeError # Large integer literal. Not representable in JS.
 compare_to2_test: RuntimeError
-double_ceil_test: RuntimeError # Large integer literal. Not representable in JS.
-double_floor_test: RuntimeError # Large integer literal. Not representable in JS.
+double_ceil_test: CompileTimeError # Large integer literal. Not representable in JS.
+double_floor_test: CompileTimeError # Large integer literal. Not representable in JS.
 double_parse_test/01: RuntimeError
-double_round_test: RuntimeError # Large integer literal. Not representable in JS.
-double_truncate_test: RuntimeError # Large integer literal. Not representable in JS.
+double_round_test: CompileTimeError # Large integer literal. Not representable in JS.
+double_truncate_test: CompileTimeError # Large integer literal. Not representable in JS.
 hash_set_test/01: RuntimeError
-int_ceil_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
-int_floor_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
-int_from_environment_test: RuntimeError # Large integer literal. Not representable in JS.
-int_modulo_arith_test/bignum: RuntimeError
-int_modulo_arith_test/modPow: RuntimeError
+int_ceil_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_ceil_to_double_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_floor_test: CompileTimeError #Large integer literal. Not representable in JS.
+int_floor_to_double_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_from_environment_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_modulo_arith_test/bignum: CompileTimeError # Large integer literal. Not representable in JS.
+int_modulo_arith_test/modPow: CompileTimeError # Large integer literal. Not representable in JS.
+int_modulo_arith_test/none: CompileTimeError # Large integer literal. Not representable in JS.
 int_parse_radix_test/01: RuntimeError
-int_parse_radix_test/02: RuntimeError
-int_round_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
-int_truncate_to_double_test: RuntimeError # Large integer literal. Not representable in JS.
-integer_to_radix_string_test: RuntimeError
-integer_to_string_test/01: RuntimeError
+int_parse_radix_test/02: CompileTimeError
+int_round_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_round_to_double_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_to_int_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_truncate_test: CompileTimeError # Large integer literal. Not representable in JS.
+int_truncate_to_double_test: CompileTimeError # Large integer literal. Not representable in JS.
+integer_to_radix_string_test: CompileTimeError # Large integer literal. Not representable in JS.
+integer_to_string_test/01: CompileTimeError # Large integer literal. Not representable in JS.
 iterable_return_type_test/02: RuntimeError
 nan_infinity_test/01: RuntimeError
-num_parse_test/01: RuntimeError # Large integer literal. Not representable in JS.
-num_parse_test/none: RuntimeError # Large integer literal. Not representable in JS.
-regress_r21715_test: RuntimeError
+num_parse_test/01: CompileTimeError # Large integer literal. Not representable in JS.
+num_parse_test/none: CompileTimeError # Large integer literal. Not representable in JS.
+num_sign_test: CompileTimeError # Large integer literal. Not representable in JS.
+regress_r21715_test: CompileTimeError # Large integer literal. Not representable in JS.
 string_base_vm_test: RuntimeError
 symbol_reserved_word_test/03: RuntimeError
 
 [ $compiler == dart2js && $fasta && $host_checked ]
 apply3_test: RuntimeError
+big_integer_arith_vm_test/add: CompileTimeError
+big_integer_arith_vm_test/div: CompileTimeError
+big_integer_arith_vm_test/gcd: CompileTimeError
+big_integer_arith_vm_test/mod: CompileTimeError
+big_integer_arith_vm_test/modInv: CompileTimeError
+big_integer_arith_vm_test/modPow: CompileTimeError
+big_integer_arith_vm_test/mul: CompileTimeError
+big_integer_arith_vm_test/negate: CompileTimeError
+big_integer_arith_vm_test/none: CompileTimeError
+big_integer_arith_vm_test/overflow: CompileTimeError
+big_integer_arith_vm_test/shift: CompileTimeError
+big_integer_arith_vm_test/sub: CompileTimeError
+big_integer_arith_vm_test/trunDiv: CompileTimeError
+bit_twiddling_bigint_test: CompileTimeError
+bit_twiddling_test: CompileTimeError
+double_ceil_test: CompileTimeError
+double_floor_test: CompileTimeError
+double_round_test: CompileTimeError
+double_truncate_test: CompileTimeError
+int_ceil_test: CompileTimeError
+int_ceil_to_double_test: CompileTimeError
+int_floor_test: CompileTimeError
+int_floor_to_double_test: CompileTimeError
+int_from_environment_test: CompileTimeError
+int_modulo_arith_test/bignum: CompileTimeError
+int_modulo_arith_test/modPow: CompileTimeError
+int_modulo_arith_test/none: CompileTimeError
+int_parse_radix_test/02: CompileTimeError
+int_round_test: CompileTimeError
+int_round_to_double_test: CompileTimeError
+int_to_int_test: CompileTimeError
+int_truncate_test: CompileTimeError
+int_truncate_to_double_test: CompileTimeError
+integer_to_radix_string_test: CompileTimeError
+integer_to_string_test/01: CompileTimeError
+num_parse_test/01: CompileTimeError
+num_parse_test/none: CompileTimeError
+num_sign_test: CompileTimeError
+regress_r21715_test: CompileTimeError
 
 [ $compiler == dart2js && $fasta && $minified ]
 apply3_test: RuntimeError
+big_integer_arith_vm_test/add: CompileTimeError
+big_integer_arith_vm_test/div: CompileTimeError
+big_integer_arith_vm_test/gcd: CompileTimeError
+big_integer_arith_vm_test/mod: CompileTimeError
+big_integer_arith_vm_test/modInv: CompileTimeError
+big_integer_arith_vm_test/modPow: CompileTimeError
+big_integer_arith_vm_test/mul: CompileTimeError
+big_integer_arith_vm_test/negate: CompileTimeError
+big_integer_arith_vm_test/none: CompileTimeError
+big_integer_arith_vm_test/overflow: CompileTimeError
+big_integer_arith_vm_test/shift: CompileTimeError
+big_integer_arith_vm_test/sub: CompileTimeError
+big_integer_arith_vm_test/trunDiv: CompileTimeError
+bit_twiddling_bigint_test: CompileTimeError
+bit_twiddling_test: CompileTimeError
+double_ceil_test: CompileTimeError
+double_floor_test: CompileTimeError
+double_round_test: CompileTimeError
+double_truncate_test: CompileTimeError
+int_ceil_test: CompileTimeError
+int_ceil_to_double_test: CompileTimeError
+int_floor_test: CompileTimeError
+int_floor_to_double_test: CompileTimeError
+int_from_environment_test: CompileTimeError
+int_modulo_arith_test/bignum: CompileTimeError
+int_modulo_arith_test/modPow: CompileTimeError
+int_modulo_arith_test/none: CompileTimeError
+int_parse_radix_test/02: CompileTimeError
+int_round_test: CompileTimeError
+int_round_to_double_test: CompileTimeError
+int_to_int_test: CompileTimeError
+int_truncate_test: CompileTimeError
+int_truncate_to_double_test: CompileTimeError
+integer_to_radix_string_test: CompileTimeError
+integer_to_string_test/01: CompileTimeError
+num_parse_test/01: CompileTimeError
+num_parse_test/none: CompileTimeError
+num_sign_test: CompileTimeError
+regress_r21715_test: CompileTimeError
 symbol_operator_test/03: RuntimeError # Issue 27394
 symbol_operator_test/none: RuntimeError
 
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index d996c09..c89576d 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -34,7 +34,6 @@
 bool_from_environment2_test/03: Crash
 int_modulo_arith_test/modPow: RuntimeError
 int_modulo_arith_test/none: RuntimeError
-null_test: RuntimeError # Issue 32194
 string_from_environment3_test/03: Crash
 
 [ $compiler == precompiler ]
@@ -305,6 +304,12 @@
 string_replace_static_test: MissingCompileTimeError
 string_static_test: MissingCompileTimeError
 
+[ $compiler == dartk && $mode == debug && $hot_reload ]
+map_test: Crash
+
+[ $compiler == dartk && $mode == release && $hot_reload ]
+bigint_parse_radix_test: Crash
+
 # ===== dartk + vm status lines =====
 [ $compiler == dartk && $runtime == vm && $strong ]
 iterable_fold_test/02: RuntimeError
@@ -394,13 +399,13 @@
 double_truncate_test/int64: RuntimeError, OK # Requires fixed-size int64 support.
 hash_set_test/01: RuntimeError # non JS number semantics - Issue 11551
 int_modulo_arith_test/modPow: RuntimeError # Issue 29921
-int_parse_with_limited_ints_test: Skip # dart2js and dartdevc don't know about --limit-ints-to-64-bits
+int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 integer_arith_vm_test/modPow: RuntimeError # Issues 10245, 30170
 integer_parsed_arith_vm_test: RuntimeError # Issues 10245, 29921
 integer_parsed_div_rem_vm_test: RuntimeError # Issue 29921
 integer_parsed_mul_div_vm_test: RuntimeError # Issue 29921
 regress_r21715_test: RuntimeError # Requires fixed-size int64 support.
-typed_data_with_limited_ints_test: Skip # dart2js and dartdevc don't know about --limit-ints-to-64-bits
+typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 
 [ $runtime != none && ($compiler == dartdevc || $compiler == dartdevk) ]
 bigint_test: Pass, Slow
@@ -411,7 +416,7 @@
 int_modulo_arith_test/none: RuntimeError # Issue 29921
 int_parse_radix_test/01: RuntimeError # Issue 29921
 int_parse_radix_test/02: RuntimeError # Issue 29921
-int_parse_with_limited_ints_test: Skip # dartdevc doesn't know about --limit-ints-to-64-bits
+int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 integer_arith_vm_test/modPow: RuntimeError # Issue 30170
 integer_parsed_arith_vm_test: RuntimeError # Issue 29921
 integer_to_radix_string_test: RuntimeError # Issue 29921
@@ -467,7 +472,7 @@
 symbol_reserved_word_test/09: RuntimeError # Issue 29921
 symbol_reserved_word_test/12: RuntimeError # Issue 29921
 symbol_test/none: RuntimeError # Issue 29921
-typed_data_with_limited_ints_test: Skip # dartdevc doesn't know about --limit-ints-to-64-bits
+typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 
 [ $runtime == vm && !$strong ]
 collection_of_test: RuntimeError
diff --git a/tests/corelib_2/int_parse_with_limited_ints_test.dart b/tests/corelib_2/int_parse_with_limited_ints_test.dart
index 0007cec..19198b2 100644
--- a/tests/corelib_2/int_parse_with_limited_ints_test.dart
+++ b/tests/corelib_2/int_parse_with_limited_ints_test.dart
@@ -1,10 +1,8 @@
 // Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// VMOptions=--limit-ints-to-64-bits
 
-// Test for int.parse in --limit-ints-to-64-bits mode (with limited 64-bit
-// integers).
+// Test for int.parse with limited 64-bit integers.
 
 import "package:expect/expect.dart";
 
diff --git a/tests/corelib_2/typed_data_with_limited_ints_test.dart b/tests/corelib_2/typed_data_with_limited_ints_test.dart
index 934e246..58c56d5 100644
--- a/tests/corelib_2/typed_data_with_limited_ints_test.dart
+++ b/tests/corelib_2/typed_data_with_limited_ints_test.dart
@@ -1,10 +1,10 @@
 // Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// VMOptions=--limit-ints-to-64-bits --optimization_counter_threshold=10 --no-background-compilation
+// VMOptions=--optimization_counter_threshold=10 --no-background-compilation
 
 // Test for dart:typed_data (in particular, ByteData.get/setUint64 and
-// UInt64List) in --limit-ints-to-64-bits mode (with limited 64-bit integers).
+// UInt64List) with limited 64-bit integers.
 
 import 'dart:typed_data';
 import "package:expect/expect.dart";
diff --git a/tests/html/html.status b/tests/html/html.status
index 972a95a..9fe79e4 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -505,8 +505,8 @@
 mirrors_js_typed_interop_test: SkipByDesign
 
 [ $compiler == dart2js && $fasta && $host_checked ]
-fontface_loaded_test: Crash
-streams_test: Crash
+fontface_loaded_test: RuntimeError
+streams_test: RuntimeError
 
 [ $compiler == dart2js && $minified ]
 canvas_pixel_array_type_alias_test/types2_runtimeTypeName: Fail, OK # Issue 12605
diff --git a/tests/language/bit_shift_test.dart b/tests/language/bit_shift_test.dart
index 1ec143b..4c4e8f6 100644
--- a/tests/language/bit_shift_test.dart
+++ b/tests/language/bit_shift_test.dart
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-// Note: in --limit-ints-to-64-bits mode all integers are 64-bit already.
+// Note: in Dart 2 mode all integers are 64-bit already.
 // Still, it is harmless to apply _uint64Mask because (1 << 64) is 0 (all bits
 // are shifted out), so _uint64Mask is -1 (its bit pattern is 0xffffffffffffffff).
 const _uint64Mask = (1 << 64) - 1;
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 76720a4..ac10795 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -87,6 +87,7 @@
 config_import_corelib_test: RuntimeError, OK # all dart:* are supported when using '--categories=all'.
 
 [ $compiler == dart2js && $checked && $fasta ]
+arithmetic_test: CompileTimeError
 assertion_initializer_const_function_test/01: RuntimeError
 assertion_initializer_test: RuntimeError
 assign_static_type_test/01: Fail
@@ -137,6 +138,7 @@
 deferred_constraints_type_annotation_test/type_annotation1: Fail # Missing dynamic type error
 deferred_constraints_type_annotation_test/type_annotation_generic1: Fail # Missing dynamic type error
 deferred_constraints_type_annotation_test/type_annotation_generic4: Fail # Missing dynamic type error
+deopt_inlined_function_lazy_test: CompileTimeError
 factory_redirection_test/08: Fail
 factory_redirection_test/09: Fail
 factory_redirection_test/10: Fail
@@ -146,6 +148,8 @@
 generalized_void_syntax_test: RuntimeError
 generic_functions_test: RuntimeError
 generic_methods_test: RuntimeError
+guess_cid_test: CompileTimeError
+int2_test: CompileTimeError
 internal_library_test/02: Crash # NoSuchMethodError: Class 'DillLibraryBuilder' has no instance getter 'mixinApplicationClasses'.
 list_literal1_test/01: MissingCompileTimeError
 malbounded_instantiation_test/01: RuntimeError # Issue 12702
@@ -160,6 +164,8 @@
 malformed2_test/00: RuntimeError
 malformed2_test/01: MissingCompileTimeError
 map_literal1_test/01: MissingCompileTimeError
+mint_compares_test: CompileTimeError
+number_identity_test: CompileTimeError
 redirecting_factory_infinite_steps_test/01: Fail
 redirecting_factory_malbounded_test/01: Fail
 regress_26133_test: RuntimeError # Issue 26429
@@ -280,6 +286,7 @@
 vm/reflect_core_vm_test: Fail # mirrors not supported
 
 [ $compiler == dart2js && $fasta ]
+arithmetic_test: CompileTimeError # Int larger than 64 bits
 async_star_cancel_while_paused_test: RuntimeError
 bad_override_test/03: MissingCompileTimeError
 bad_override_test/04: MissingCompileTimeError
@@ -327,6 +334,7 @@
 deferred_load_library_wrong_args_test/01: MissingRuntimeError
 deferred_not_loaded_check_test: RuntimeError
 deferred_redirecting_factory_test: RuntimeError
+deopt_inlined_function_lazy_test: CompileTimeError # Int larger than 64 bits.
 double_int_to_string_test: RuntimeError
 duplicate_export_negative_test: Fail
 duplicate_implements_test/01: MissingCompileTimeError
@@ -361,10 +369,13 @@
 getter_override_test/00: MissingCompileTimeError
 getter_override_test/01: MissingCompileTimeError
 getter_override_test/02: MissingCompileTimeError
+guess_cid_test: CompileTimeError # Int larger than 64 bits
 identical_closure2_test: RuntimeError
 if_null_assignment_behavior_test/14: RuntimeError
 infinity_test: RuntimeError
 instance_creation_in_function_annotation_test: RuntimeError
+int2_test: CompileTimeError # Int larger than 64 bits
+int_round_test: CompileTimeError # Int larger than 64 bits
 integer_division_by_zero_test: RuntimeError
 internal_library_test/02: Crash # type 'DillLibraryBuilder' is not a subtype of type 'SourceLibraryBuilder<KernelTypeBuilder, Library>' of 'value' where
 invocation_mirror2_test: RuntimeError # mirrors not supported
@@ -385,6 +396,7 @@
 method_override8_test/00: MissingCompileTimeError
 method_override8_test/01: MissingCompileTimeError
 mint_arithmetic_test: RuntimeError
+mint_compares_test: CompileTimeError # Int larger than 64 bits
 mixin_forwarding_constructor4_test/01: MissingCompileTimeError
 mixin_forwarding_constructor4_test/02: MissingCompileTimeError
 mixin_forwarding_constructor4_test/03: MissingCompileTimeError
@@ -498,6 +510,7 @@
 no_such_method_test: RuntimeError
 null_test/none: RuntimeError
 number_identity2_test: RuntimeError
+number_identity_test: CompileTimeError # Int larger than 64 bits
 numbers_test: RuntimeError
 overridden_no_such_method_test: RuntimeError
 override_field_method1_negative_test: Fail
@@ -553,21 +566,33 @@
 type_variable_conflict2_test/02: MissingCompileTimeError
 
 [ $compiler == dart2js && $fasta && $host_checked ]
+arithmetic_test: CompileTimeError
 async_test/setter1: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
 closure_self_reference_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/nodes.dart': Failed assertion: line 641 pos 12: 'isClosed()': is not true.
+deopt_inlined_function_lazy_test: CompileTimeError
 generic_methods_type_expression_test/01: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
 generic_methods_type_expression_test/03: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
 generic_methods_type_expression_test/none: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
+guess_cid_test: CompileTimeError
+int2_test: CompileTimeError
 invocation_mirror_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 3014 pos 14: 'arguments.named.isEmpty': is not true.
+mint_compares_test: CompileTimeError
+number_identity_test: CompileTimeError
 sync_generator2_test/41: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
 sync_generator2_test/52: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
 syntax_test/21: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 syntax_test/22: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 
 [ $compiler == dart2js && $fasta && $minified ]
+arithmetic_test: CompileTimeError
 deferred_load_library_wrong_args_test/01: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
 deferred_redirecting_factory_test: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
+deopt_inlined_function_lazy_test: CompileTimeError
+guess_cid_test: CompileTimeError
+int2_test: CompileTimeError
 internal_library_test/02: Crash # NoSuchMethodError: Class 'DillLibraryBuilder' has no instance getter 'mixinApplicationClasses'.
+mint_compares_test: CompileTimeError
+number_identity_test: CompileTimeError
 stacktrace_rethrow_error_test/none: RuntimeError # Issue 12698
 stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
 stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
diff --git a/tests/language_2/bit_shift_test.dart b/tests/language_2/bit_shift_test.dart
index 1ec143b..1f00423 100644
--- a/tests/language_2/bit_shift_test.dart
+++ b/tests/language_2/bit_shift_test.dart
@@ -5,16 +5,11 @@
 
 import "package:expect/expect.dart";
 
-// Note: in --limit-ints-to-64-bits mode all integers are 64-bit already.
-// Still, it is harmless to apply _uint64Mask because (1 << 64) is 0 (all bits
-// are shifted out), so _uint64Mask is -1 (its bit pattern is 0xffffffffffffffff).
-const _uint64Mask = (1 << 64) - 1;
-
 constants() {
   Expect.equals(0, 499 >> 33);
   Expect.equals(0, (499 << 33) & 0xFFFFFFFF);
   Expect.equals(0, (499 << 32) >> 65);
-  Expect.equals(0, ((499 << 32) << 65) & _uint64Mask);
+  Expect.equals(0, (499 << 32) << 65);
 }
 
 foo(i) {
@@ -38,7 +33,7 @@
   Expect.equals(0, id(499) >> 33);
   Expect.equals(0, (id(499) << 33) & 0xFFFFFFFF);
   Expect.equals(0, id(499 << 32) >> 65);
-  Expect.equals(0, (id(499 << 32) << 65) & _uint64Mask);
+  Expect.equals(0, id(499 << 32) << 65);
 }
 
 speculative() {
@@ -48,7 +43,7 @@
     Expect.equals(0, a >> 33);
     Expect.equals(0, (a << 33) & 0xFFFFFFFF);
     Expect.equals(0, b >> 65);
-    Expect.equals(0, (b << 65) & _uint64Mask);
+    Expect.equals(0, b << 65);
   }
 }
 
diff --git a/tests/language_2/constructor_with_type_parameters_test.dart b/tests/language_2/constructor_with_type_parameters_test.dart
new file mode 100644
index 0000000..203e2ce
--- /dev/null
+++ b/tests/language_2/constructor_with_type_parameters_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Bar<T> {
+  Bar() {} //# 01: ok
+  Bar.boo() {} //# 02: ok
+  Bar<E>() {} //# 03: compile-time error
+  Bar<E>.boo() {} //# 04: compile-time error
+  Bar.boo<E>() {} //# 05: compile-time error
+  Bar.boo<E>.baz() {} //# 06: compile-time error
+
+  Bar(); //# 07: ok
+  Bar.boo(); //# 08: ok
+  Bar<E>(); //# 09: compile-time error
+  Bar<E>.boo(); //# 10: compile-time error
+  Bar.boo<E>(); //# 11: compile-time error
+  Bar.boo<E>.baz(); //# 12: compile-time error
+
+  const Bar(); //# 13: ok
+  const Bar.boo(); //# 14: ok
+  const Bar<E>(); //# 15: compile-time error
+  const Bar<E>.boo(); //# 16: compile-time error
+  const Bar.boo<E>(); //# 17: compile-time error
+  const Bar.boo<E>.baz(); //# 18: compile-time error
+}
+
+main() {}
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index fdfc105..71dfbfc 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -17,7 +17,8 @@
 const_cast2_test/none: CompileTimeError
 const_for_in_variable_test/01: MissingCompileTimeError # Issue 25161
 constructor_call_wrong_argument_count_negative_test: Fail # Issue 11585
-constructor_type_parameter_test/00: MissingCompileTimeError # Issue 33110
+constructor_type_parameter_test/00: MissingCompileTimeError
+constructor_with_type_parameters_test/03: MissingCompileTimeError
 deep_nesting1_negative_test: CompileTimeError # Issue 25558
 deep_nesting2_negative_test: CompileTimeError # Issue 25558
 duplicate_export_negative_test: CompileTimeError
@@ -1152,7 +1153,6 @@
 override_inheritance_generic_test/02: CompileTimeError
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
-parameter_initializer_test: CompileTimeError
 parser_quirks_test: CompileTimeError
 regress_22976_test/01: CompileTimeError
 regress_22976_test/02: CompileTimeError
@@ -1342,6 +1342,8 @@
 constructor13_test/02: MissingCompileTimeError
 constructor_call_as_function_test: StaticWarning
 constructor_duplicate_final_test/03: MissingCompileTimeError
+constructor_with_type_parameters_test/09: MissingCompileTimeError
+constructor_with_type_parameters_test/15: MissingCompileTimeError
 create_unresolved_type_test/01: MissingCompileTimeError
 fuzzy_arrows_test/01: MissingCompileTimeError
 generic_constructor_mixin2_test/01: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 830d006..59f8197 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -8,7 +8,6 @@
 bit_operations_test: RuntimeError, OK # non JS number semantics
 config_import_corelib_test: CompileTimeError # we need a special platform.dill file for categories=all. Once we fix that, all dart:* are supported when using '--categories=all' so this will become a RuntimeError, OK.
 config_import_test: RuntimeError # Test flag is not passed to the compiler.
-constructor_type_parameter_test/00: Crash # Issue 33110
 double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
 issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
 library_env_test/has_mirror_support: RuntimeError, OK
@@ -573,6 +572,7 @@
 constructor_redirect1_negative_test/01: Crash # Stack Overflow
 constructor_redirect2_negative_test: Crash # Stack Overflow
 constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
+covariance_type_parameter_test/02: RuntimeError
 covariant_override/tear_off_type_test: RuntimeError
 covariant_subtyping_test: Crash # Unsupported operation: Unsupported type parameter type node E.
 cyclic_constructor_test/01: Crash # Stack Overflow
@@ -657,12 +657,10 @@
 instantiate_tearoff_of_call_test: CompileTimeError
 int64_literal_test/01: RuntimeError
 int64_literal_test/02: RuntimeError
-int64_literal_test/03: MissingCompileTimeError
 int64_literal_test/04: RuntimeError
 int64_literal_test/05: RuntimeError
 int64_literal_test/10: RuntimeError
 int64_literal_test/20: RuntimeError
-int64_literal_test/30: MissingCompileTimeError
 int64_literal_test/40: RuntimeError
 int64_literal_test/none: RuntimeError
 integer_division_by_zero_test: RuntimeError # Issue 8301
@@ -920,8 +918,6 @@
 compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 compile_time_constant_static5_test/11: CompileTimeError
 compile_time_constant_static5_test/16: CompileTimeError
 compile_time_constant_static5_test/21: CompileTimeError
@@ -1049,18 +1045,14 @@
 identical_const_test/04: MissingCompileTimeError
 if_null_precedence_test/none: RuntimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instance_creation_in_function_annotation_test: RuntimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 int64_literal_test/01: RuntimeError
 int64_literal_test/02: RuntimeError
-int64_literal_test/03: MissingCompileTimeError
 int64_literal_test/04: RuntimeError
 int64_literal_test/05: RuntimeError
 int64_literal_test/10: RuntimeError
 int64_literal_test/20: RuntimeError
-int64_literal_test/30: MissingCompileTimeError
 int64_literal_test/40: RuntimeError
 int64_literal_test/none: RuntimeError
 integer_division_by_zero_test: RuntimeError # Issue 8301
@@ -1222,7 +1214,6 @@
 null_no_such_method_test: CompileTimeError
 number_identity2_test: RuntimeError
 numbers_test: RuntimeError, OK # non JS number semantics
-operator2_negative_test: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 override_field_test/01: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
 override_field_test/03: MissingCompileTimeError
@@ -1294,28 +1285,8 @@
 switch_case_test/02: MissingCompileTimeError
 sync_generator2_test/41: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
 sync_generator2_test/52: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
-syntax_test/04: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/05: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/06: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/07: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/08: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/09: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/10: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/11: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/13: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/14: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/15: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/16: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/17: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/18: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/19: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/20: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 syntax_test/21: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 syntax_test/22: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/23: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/24: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/25: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/26: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
 syntax_test/28: MissingCompileTimeError # Issue 29763
 syntax_test/29: MissingCompileTimeError # Issue 29763
 syntax_test/30: MissingCompileTimeError # Issue 29763
@@ -1462,8 +1433,6 @@
 compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 compile_time_constant_static5_test/11: CompileTimeError
 compile_time_constant_static5_test/16: CompileTimeError
 compile_time_constant_static5_test/21: CompileTimeError
@@ -1585,18 +1554,14 @@
 identical_const_test/04: MissingCompileTimeError
 if_null_precedence_test/none: RuntimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instance_creation_in_function_annotation_test: RuntimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 int64_literal_test/01: RuntimeError
 int64_literal_test/02: RuntimeError
-int64_literal_test/03: MissingCompileTimeError
 int64_literal_test/04: RuntimeError
 int64_literal_test/05: RuntimeError
 int64_literal_test/10: RuntimeError
 int64_literal_test/20: RuntimeError
-int64_literal_test/30: MissingCompileTimeError
 int64_literal_test/40: RuntimeError
 int64_literal_test/none: RuntimeError
 integer_division_by_zero_test: RuntimeError # Issue 8301
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 11456f2..d534e75 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -39,7 +39,8 @@
 const_types_test/14: MissingCompileTimeError
 const_types_test/15: MissingCompileTimeError
 constant_type_literal_test/01: MissingCompileTimeError # DDC allows type parameter type literals in const expressions.
-constructor_type_parameter_test/00: MissingCompileTimeError # Issue 33110
+constructor_type_parameter_test/00: MissingCompileTimeError
+constructor_with_type_parameters_test/03: MissingCompileTimeError
 covariance_field_test/03: RuntimeError
 covariant_override/tear_off_type_test: RuntimeError # Issue 28395
 default_implementation2_test: CompileTimeError # Issue 30855
@@ -141,7 +142,6 @@
 override_inheritance_generic_test/02: CompileTimeError
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
-parameter_initializer_test: CompileTimeError
 part_refers_to_core_library_test/01: Crash
 prefix_shadow_test/01: MissingCompileTimeError # Issue 33005
 regress_23089_test: MissingCompileTimeError
@@ -298,11 +298,9 @@
 bad_override_test/01: MissingCompileTimeError
 bad_override_test/02: MissingCompileTimeError
 bad_override_test/03: MissingCompileTimeError
-built_in_identifier_type_annotation_test/dynamic: RuntimeError # Issue 32194
 built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 32194
 built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 32194
 built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 32194
-built_in_identifier_type_annotation_test/none: RuntimeError # Issue 32194
 call_method_as_cast_test/06: RuntimeError # Kernel allows classes to subtype `Function` so DDK elides the explicit cast.
 call_method_implicit_tear_off_implements_function_test/05: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`
 call_method_implicit_tear_off_implements_function_test/06: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`
@@ -310,7 +308,6 @@
 call_method_must_not_be_getter_test/06: RuntimeError # Kernel does not distinguish `d()` from `d.call()`
 call_non_method_field_test/01: MissingCompileTimeError
 call_non_method_field_test/02: MissingCompileTimeError
-cast_test/none: RuntimeError # Issue 32194
 check_member_static_test/01: MissingCompileTimeError
 check_member_static_test/02: MissingCompileTimeError
 class_cycle_test/02: MissingCompileTimeError
@@ -321,8 +318,6 @@
 compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 compile_time_constant_static4_test/02: MissingCompileTimeError
 compile_time_constant_static4_test/03: MissingCompileTimeError
 compile_time_constant_static5_test/11: CompileTimeError # Issue 31537
@@ -344,7 +339,6 @@
 const_syntax_test/05: MissingCompileTimeError
 const_types_test/34: MissingCompileTimeError
 const_types_test/39: MissingCompileTimeError
-constant_string_interpolation2_test: RuntimeError # Issue 32194
 constants_test/05: MissingCompileTimeError
 constructor_redirect1_negative_test/01: MissingCompileTimeError
 constructor_redirect2_negative_test: MissingCompileTimeError
@@ -414,8 +408,6 @@
 implicit_creation/implicit_const_not_default_values_test/e30: Pass
 implicit_creation/implicit_const_not_default_values_test/e6: Pass
 implicit_creation/implicit_const_not_default_values_test/e9: Pass
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 issue18628_2_test/01: MissingCompileTimeError
 issue31596_override_test/07: MissingCompileTimeError
@@ -528,11 +520,7 @@
 named_constructor_test/01: MissingCompileTimeError
 named_parameters_default_eq_test/02: MissingCompileTimeError
 no_such_method_mock_test: RuntimeError # Issue 31426 - Kernel does not introduce nSM for implemented fields.
-null2_test: RuntimeError # Issue 32194
-null_method_test: RuntimeError # Issue 32194
 null_no_such_method_test: CompileTimeError # Issue 31533
-null_test/none: RuntimeError # Issue 32194
-null_to_string_test: RuntimeError # Issue 32194
 override_field_test/01: MissingCompileTimeError
 override_field_test/02: MissingCompileTimeError
 override_inheritance_field_test/04: CompileTimeError # Issue 31616
@@ -568,7 +556,6 @@
 setter_override_test/02: MissingCompileTimeError
 setter_override_test/03: MissingCompileTimeError
 string_interpolate_test: CompileTimeError # Issue 31533
-string_optimizations_test: RuntimeError # Issue 32194
 string_split_test: CompileTimeError # Issue 31616
 string_supertype_checked_test: CompileTimeError # Issue 31616
 super_bound_closure_test/none: CompileTimeError # Issue 31533
@@ -587,7 +574,6 @@
 switch_case_test/01: MissingCompileTimeError
 switch_case_test/02: MissingCompileTimeError
 syncstar_yield_test/copyParameters: RuntimeError # Expect.equals(expected: <2>, actual: <3>) fails.
-tearoff_dynamic_test: RuntimeError # Issue 32194
 try_catch_test/01: MissingCompileTimeError
 type_alias_equality_test/02: RuntimeError # Issue 32785
 type_literal_test: RuntimeError # Expect.equals(expected: <Func>, actual: <(bool) => int>) fails.
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index e923ac4..92bc089 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -248,7 +248,6 @@
 constructor_redirect1_negative_test/01: MissingCompileTimeError # Issue 30856
 constructor_redirect2_negative_test: MissingCompileTimeError # Issue 30856
 constructor_redirect_test/01: MissingCompileTimeError # Fasta bug: Initializer refers to this.
-constructor_type_parameter_test/00: MissingCompileTimeError # Issue 33110
 cyclic_constructor_test/01: MissingCompileTimeError # Issue 30856 (cyclic constructor redirection)
 cyclic_type_variable_test/01: MissingCompileTimeError # Issue 32989 (missing cycle check in bounds)
 cyclic_type_variable_test/02: MissingCompileTimeError # Issue 32989 (missing cycle check in bounds)
@@ -631,6 +630,16 @@
 mixin_supertype_subclass_test/02: MissingCompileTimeError
 mixin_supertype_subclass_test/05: MissingCompileTimeError
 
+[ $compiler == dartk && $mode == debug && $hot_reload ]
+async_star_test/01: Crash
+async_star_test/05: Crash
+
+[ $compiler == dartk && $mode == debug && $hot_reload_rollback ]
+enum_test: Crash
+
+[ $compiler == dartk && $mode == debug && ($hot_reload || $hot_reload_rollback) ]
+enum_duplicate_test/01: Crash
+
 [ $compiler == dartk && $mode == product && $runtime == vm ]
 deferred_load_constants_test/02: Fail
 deferred_load_constants_test/03: Fail
@@ -699,8 +708,6 @@
 type_variable_bounds4_test/01: RuntimeError
 
 [ $compiler == dartk && $runtime == vm && !$checked && $strong ]
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
 type_error_test: RuntimeError # Issue 31402 (Variable declaration)
 
@@ -772,8 +779,6 @@
 generic_tearoff_test: CompileTimeError
 generic_tearoff_test: RuntimeError
 if_null_evaluation_order_test: Pass
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 issue18628_2_test/01: MissingCompileTimeError
 issue31596_super_test/01: CompileTimeError
@@ -868,6 +873,10 @@
 [ $compiler == dartk && $system == windows && $strong ]
 ct_const2_test: Fail
 
+[ $compiler == dartk && $hot_reload ]
+vm/causal_async_exception_stack2_test: Crash
+vm/causal_async_exception_stack_test: Crash
+
 [ $compiler == dartk && $strong ]
 assertion_initializer_const_error2_test/cc01: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc02: MissingCompileTimeError # Not reporting failed assert() at compile time.
@@ -889,6 +898,14 @@
 [ $compiler == dartk && $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
 least_upper_bound_expansive_test/none: RuntimeError # Please triage.
 
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+async_star_test/01: Skip # Timeout
+async_star_test/02: Skip # Timeout
+async_star_test/03: Skip # Timeout
+async_star_test/04: Skip # Timeout
+async_star_test/05: Skip # Timeout
+async_star_test/none: Skip # Timeout
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
 const_instance_field_test/01: Crash # Issue 32326.
 external_test/13: Crash
@@ -984,8 +1001,6 @@
 [ $compiler == dartkp && $runtime == dart_precompiled && !$checked && $strong ]
 assertion_initializer_const_error_test/01: MissingCompileTimeError
 assertion_initializer_const_function_error_test/01: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
 implicit_downcast_during_combiner_test: RuntimeError
 implicit_downcast_during_compound_assignment_test: RuntimeError
@@ -1115,8 +1130,6 @@
 implicit_downcast_during_while_statement_test: Pass # Correctly passes.
 implicit_downcast_during_yield_star_test: Pass # Correctly passes.
 implicit_downcast_during_yield_test: Pass # Correctly passes.
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instance_creation_in_function_annotation_test: SkipByDesign
 instantiate_tearoff_of_call_test: CompileTimeError
 invocation_mirror2_test: SkipByDesign
@@ -1483,10 +1496,6 @@
 deopt_inlined_function_lazy_test: Skip
 
 [ $fasta && $strong ]
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 issue18628_2_test/01: MissingCompileTimeError
 map_literal3_test/03: MissingCompileTimeError
 redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
diff --git a/tests/language_2/parameter_initializer_test.dart b/tests/language_2/parameter_initializer_test.dart
index e1d5855..1696703 100644
--- a/tests/language_2/parameter_initializer_test.dart
+++ b/tests/language_2/parameter_initializer_test.dart
@@ -9,9 +9,6 @@
     var obj = new Foo.untyped(1);
     Expect.equals(1, obj.x);
 
-    obj = new Foo.supertype(9);
-    Expect.equals(9, obj.x);
-
     obj = new Foo.subtype(7);
     Expect.equals(7, obj.x);
 
@@ -40,7 +37,6 @@
   }
 
   Foo.untyped(this.x) {}
-  Foo.supertype(Object this.x) {}
   Foo.subtype(int this.x) {}
   Foo.optional([this.x = 5]) {}
 
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index d316685..116c44e 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -19,7 +19,7 @@
 async/schedule_microtask6_test: RuntimeError # global error handling is not supported. Issue 5958
 convert/base64_test/01: Fail, OK # Uses bit-wise operations to detect invalid values. Some large invalid values accepted by dart2js.
 convert/chunked_conversion_utf88_test: Slow, Pass
-convert/utf82_test: RuntimeError # Large integer literal. Not valid in dart2.
+convert/utf82_test: CompileTimeError # Large integer literal. Not valid in dart2.
 convert/utf85_test: Slow, Pass
 developer/timeline_test: Skip # Not supported
 math/double_pow_test: RuntimeError
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 35184e0..7b0f031 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -115,6 +115,7 @@
 [ $hot_reload ]
 async/stream_periodic4_test: Pass, RuntimeError # Issue 30904
 async/timer_regress22626_test: Pass, RuntimeError # Timing dependent.
+mirrors/dynamic_load_test: RuntimeError # Issue 26869 - Reload fails to preserve library identity
 
 [ $jscl ]
 isolate/spawn_uri_multi_test/none: RuntimeError # Issue 13544
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 785d1a3..e3b55be 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -491,9 +491,6 @@
 [ $compiler == dart2js && $checked && $fasta ]
 async/stream_listen_zone_test: RuntimeError
 
-[ $compiler == dart2js && !$checked ]
-async/async_await_sync_completer_test: RuntimeError
-
 [ $compiler == dart2js && $csp && $fasta && $minified ]
 collection/list_test: RuntimeError
 
@@ -689,10 +686,9 @@
 html/js_typed_interop_test: RuntimeError
 
 [ $compiler == dart2js && $fasta && $host_checked ]
-async/stream_controller_async_test: Crash
 html/custom/mirrors_2_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
 html/custom/mirrors_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-html/fontface_loaded_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
+html/fontface_loaded_test: RuntimeError # TypeError: Cannot read property 'createFragment$3$treeSanitizer$validator' of undefined
 html/indexeddb_3_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
 html/indexeddb_5_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
 html/js_array_test: CompileTimeError
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index d1abdeb..9cdf0ea 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -36,7 +36,6 @@
 html/xhr_test: Skip # Times out. Issue 21527
 
 [ $compiler == dartdevc || $compiler == dartdevk ]
-async/async_await_sync_completer_test: RuntimeError # Issue 29922
 async/async_await_zones_test: RuntimeError # Issue 29922
 async/future_or_bad_type_test/implements: RuntimeError # Issue 29922
 async/future_or_bad_type_test/none: RuntimeError # Issue 29922
@@ -45,7 +44,6 @@
 async/stream_controller_async_test: RuntimeError
 async/stream_distinct_test: RuntimeError # Issue 29922
 async/stream_join_test: RuntimeError
-async/stream_subscription_as_future_test: RuntimeError
 async/timer_not_available_test: RuntimeError
 convert/base64_test/01: Fail, OK # Uses bit-wise operations to detect invalid values. Some large invalid values accepted by DDC/dart2js.
 convert/chunked_conversion_utf88_test: Slow, Pass
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index da72614..ffc9c90 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -11,14 +11,12 @@
 # to add them.
 
 [ $compiler == app_jitk ]
-async/async_await_sync_completer_test: RuntimeError
 async/future_test/01: RuntimeError
 async/future_test/none: RuntimeError
 async/slow_consumer2_test: RuntimeError
 async/stream_controller_async_test: RuntimeError
 async/stream_distinct_test: RuntimeError
 async/stream_join_test: RuntimeError
-async/stream_subscription_as_future_test: RuntimeError
 async/timer_not_available_test: RuntimeError
 isolate/issue_21398_parent_isolate1_test: RuntimeError
 isolate/issue_22778_test: Crash
@@ -26,7 +24,7 @@
 isolate/message_test: RuntimeError
 isolate/mint_maker_test: RuntimeError
 isolate/ping_pause_test: Skip # Timeout
-isolate/static_function_test: RuntimeError
+isolate/spawn_function_custom_class_test: Skip # Timeout
 
 [ $compiler == fasta ]
 html/*: Skip # TODO(ahe): Make dart:html available.
@@ -76,6 +74,9 @@
 [ $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
 mirrors/other_declarations_location_test: Crash # assertion error, TypeParameter not having position.
 
+[ $compiler == dartk && $mode == debug && $hot_reload_rollback ]
+isolate/message3_test/constList_identical: Skip # Timeout
+
 [ $compiler == dartk && $mode == debug && $strong ]
 mirrors/instance_members_unimplemented_interface_test: Crash
 mirrors/library_import_deferred_loading_test: Crash # Deferred loading kernel issue 28335.
@@ -94,11 +95,9 @@
 
 # ===== dartk + vm status lines =====
 [ $compiler == dartk && $runtime == vm && $strong ]
-async/async_await_sync_completer_test: RuntimeError
 async/slow_consumer2_test: CompileTimeError # Issue 31402 (Invocation arguments)
 async/stream_controller_async_test: CompileTimeError # Issue 31402 (Invocation arguments)
 async/stream_join_test: CompileTimeError # Issue 31402 (Invocation arguments)
-async/stream_subscription_as_future_test: CompileTimeError # Issue 31402 (Invocation arguments)
 async/timer_not_available_test: RuntimeError
 convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
 html/*: SkipByDesign # dart:html not supported on VM.
@@ -212,6 +211,18 @@
 [ $compiler == dartk && $system == windows ]
 isolate/ping_pause_test: Skip # Issues 32137 and 32138
 
+[ $compiler == dartk && $hot_reload ]
+async/stream_state_nonzero_timer_test: Crash
+async/stream_subscription_as_future_test: Crash
+async/stream_subscription_cancel_test: Crash
+isolate/message4_test: Crash
+isolate/spawn_uri_multi_test/01: Crash
+isolate/spawn_uri_multi_test/none: Crash
+
+[ $compiler == dartk && $hot_reload_rollback ]
+isolate/illegal_msg_function_test: Skip # Timeout
+isolate/pause_test: Skip # Timeout
+
 [ $compiler == dartk && $strong ]
 async/future_test/01: RuntimeError
 async/future_test/none: RuntimeError
@@ -219,7 +230,6 @@
 async/stream_controller_async_test: RuntimeError
 async/stream_distinct_test: RuntimeError
 async/stream_join_test: RuntimeError
-async/stream_subscription_as_future_test: RuntimeError
 isolate/issue_22778_test: Crash
 isolate/kill_self_synchronously_test: RuntimeError
 isolate/message_test: RuntimeError
@@ -274,19 +284,55 @@
 [ $compiler == dartk && !$strong ]
 *: SkipByDesign
 
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+async/stream_from_iterable_test: Skip # Timeout
+async/stream_iterator_test: Skip # Timeout
+async/stream_periodic2_test: Skip # Timeout
+async/stream_periodic3_test: Skip # Timeout
+async/stream_periodic4_test: Skip # Timeout
+async/stream_periodic5_test: Skip # Timeout
+async/stream_periodic6_test: Skip # Timeout
+async/stream_periodic_test: Skip # Timeout
+async/stream_single_test: Skip # Timeout
+async/stream_single_to_multi_subscriber_test: Skip # Timeout
+async/stream_state_test: Skip # Timeout
+async/stream_timeout_test: Skip # Timeout
+async/stream_transform_test: Skip # Timeout
+async/stream_transformation_broadcast_test: Skip # Timeout
+async/timer_cancel1_test: Skip # Timeout
+async/timer_isActive_test: Skip # Timeout
+async/timer_test: Skip # Timeout
+isolate/count_test: Skip # Timeout
+isolate/cross_isolate_message_test: Skip # Timeout
+isolate/isolate_complex_messages_test: Skip # Timeout
+isolate/isolate_import_test/none: Skip # Timeout
+isolate/issue_21398_parent_isolate1_test: Skip # Timeout
+isolate/mandel_isolate_test: Skip # Timeout
+isolate/message2_test: Skip # Timeout
+isolate/nested_spawn2_test: Skip # Timeout
+isolate/nested_spawn_test: Skip # Timeout
+isolate/raw_port_test: Skip # Timeout
+isolate/spawn_function_test: Skip # Timeout
+isolate/spawn_uri_test: Skip # Timeout
+isolate/spawn_uri_vm_test: Skip # Timeout
+isolate/timer_isolate_test: Skip # Timeout
+isolate/timer_multiple_isolates_test: Skip # Timeout
+isolate/unresolved_ports_test: Skip # Timeout
+mirrors/dynamic_load_test: Crash
+mirrors/library_uri_io_test: Skip # Timeout
+mirrors/library_uri_package_test: Skip # Timeout
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
 isolate/static_function_test: Skip # Flaky (https://github.com/dart-lang/sdk/issues/30063).
 
 # ===== dartkp + dart_precompiled status lines =====
 [ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
-async/async_await_sync_completer_test: RuntimeError
 async/future_test/01: RuntimeError
 async/future_test/none: RuntimeError
 async/slow_consumer2_test: RuntimeError # Issue 31402 (Invocation arguments)
 async/stream_controller_async_test: RuntimeError
 async/stream_distinct_test: RuntimeError
 async/stream_join_test: RuntimeError
-async/stream_subscription_as_future_test: RuntimeError
 async/timer_not_available_test: RuntimeError
 html/*: SkipByDesign # dart:html not supported on VM.
 isolate/compile_time_error_test/01: Crash
diff --git a/tests/lib_2/mirrors/dynamic_load_error.dart b/tests/lib_2/mirrors/dynamic_load_error.dart
new file mode 100644
index 0000000..f75aaf9
--- /dev/null
+++ b/tests/lib_2/mirrors/dynamic_load_error.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2018, 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.
+
+// A top-level parse error:
+import import import import
diff --git a/tests/lib_2/mirrors/dynamic_load_success.dart b/tests/lib_2/mirrors/dynamic_load_success.dart
new file mode 100644
index 0000000..1645a92
--- /dev/null
+++ b/tests/lib_2/mirrors/dynamic_load_success.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2018, 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 dynamic_load_success;
+
+int _counter = 0;
+
+advanceCounter() => ++_counter;
diff --git a/tests/lib_2/mirrors/dynamic_load_test.dart b/tests/lib_2/mirrors/dynamic_load_test.dart
new file mode 100644
index 0000000..2cc7c3a
--- /dev/null
+++ b/tests/lib_2/mirrors/dynamic_load_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+main() async {
+  IsolateMirror isolate = currentMirrorSystem().isolate;
+  print(isolate);
+
+  LibraryMirror success =
+      await isolate.loadUri(Uri.parse("dynamic_load_success.dart"));
+  print(success);
+  InstanceMirror result = success.invoke(#advanceCounter, []);
+  print(result);
+  Expect.equals(1, result.reflectee);
+  result = success.invoke(#advanceCounter, []);
+  print(result);
+  Expect.equals(2, result.reflectee);
+
+  LibraryMirror success2 =
+      await isolate.loadUri(Uri.parse("dynamic_load_success.dart"));
+  print(success2);
+  Expect.equals(success, success2);
+  result = success2.invoke(#advanceCounter, []);
+  print(result);
+  Expect.equals(3, result.reflectee); // Same library, same state.
+
+  LibraryMirror math = await isolate.loadUri(Uri.parse("dart:math"));
+  result = math.invoke(#max, [3, 4]);
+  print(result);
+  Expect.equals(4, result.reflectee);
+
+  Future<LibraryMirror> bad_load = isolate.loadUri(Uri.parse("DOES_NOT_EXIST"));
+  var error;
+  try {
+    await bad_load;
+  } catch (e) {
+    error = e;
+  }
+  print(error);
+  Expect.isTrue(error.toString().contains("Cannot open file") ||
+      error.toString().contains("No such file or directory"));
+  Expect.isTrue(error.toString().contains("DOES_NOT_EXIST"));
+
+  Future<LibraryMirror> bad_load2 = isolate.loadUri(Uri.parse("dart:_builtin"));
+  var error2;
+  try {
+    await bad_load2;
+  } catch (e) {
+    error2 = e;
+  }
+  print(error2);
+  Expect.isTrue(error2.toString().contains("Cannot load"));
+  Expect.isTrue(error2.toString().contains("dart:_builtin"));
+
+  // Check error is not sticky.
+  LibraryMirror success3 =
+      await isolate.loadUri(Uri.parse("dynamic_load_success.dart"));
+  print(success3);
+  Expect.equals(success, success3);
+  result = success3.invoke(#advanceCounter, []);
+  print(result);
+  Expect.equals(4, result.reflectee); // Same library, same state.
+
+  Future<LibraryMirror> bad_load3 =
+      isolate.loadUri(Uri.parse("dynamic_load_error.dart"));
+  var error3;
+  try {
+    await bad_load3;
+  } catch (e) {
+    error3 = e;
+  }
+  print(error3);
+  Expect.isTrue(error3.toString().contains("library url expected") ||
+      error3.toString().contains("Error: Expected a String"));
+  Expect.isTrue(error3.toString().contains("dynamic_load_error.dart"));
+}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 66193af..caa9d9b 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -73,6 +73,10 @@
 io/socket_info_ipv6_test: Pass, Crash
 io/socket_port_test: Pass, Crash
 
+[ $compiler == dartk && $mode == debug && $hot_reload ]
+io/http_basic_test: Crash
+io/web_socket_ping_test: Crash, Pass
+
 # ===== dartk + vm status lines =====
 [ $compiler == dartk && $runtime == vm && $strong ]
 io/http_client_request_test: Pass, Timeout
@@ -99,6 +103,13 @@
 io/regress_7679_test: RuntimeError # Issue 31904
 map_insert_remove_oom_test: Skip # Heap limit too low.
 
+[ $compiler == dartk && $hot_reload ]
+io/http_no_reason_phrase_test: Pass, Crash
+io/http_outgoing_size_test: Pass, Crash
+
+[ $compiler == dartk && $hot_reload_rollback ]
+io/directory_chdir_test: Skip # Timeout
+
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
@@ -120,6 +131,24 @@
 [ $compiler == dartk && !$strong ]
 *: SkipByDesign
 
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+io/addlatexhash_test: Skip # Timeout
+io/http_advanced_test: Skip # Timeout
+io/http_auth_digest_test: Crash
+io/http_auth_test: Skip # Timeout
+io/http_proxy_advanced_test: Skip # Timeout
+io/http_read_test: Skip # Timeout
+io/non_utf8_directory_test: Crash
+io/non_utf8_file_test: Crash
+io/non_utf8_link_test: Crash
+io/pipe_server_test: Skip # Timeout
+io/socket_close_test: Skip # Timeout
+io/socket_many_connections_test: Skip # Timeout
+io/test_extension_fail_test: RuntimeError
+io/test_extension_test: RuntimeError
+io/web_socket_compression_test: Skip # Timeout
+io/web_socket_test: Skip # Timeout
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
 io/compile_all_test: Crash # Issue 32373
 io/raw_socket_test: Crash
diff --git a/tools/VERSION b/tools/VERSION
index 1d4965d..0f5e991 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 0
 PATCH 0
-PRERELEASE 59
+PRERELEASE 60
 PRERELEASE_PATCH 0
diff --git a/tools/addlatexhash.dart b/tools/addlatexhash.dart
index c48fa6b..cbdc349 100755
--- a/tools/addlatexhash.dart
+++ b/tools/addlatexhash.dart
@@ -25,7 +25,6 @@
 // source file receieved as input; it will not work with other styles.
 
 import 'dart:io';
-import 'dart:convert';
 
 import 'package:crypto/crypto.dart';
 import 'package:convert/convert.dart';
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index ce55a8e..6302dd7 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -737,6 +737,28 @@
     },
     {
       "builders": [
+        "vm-kernel-reload-linux-debug-x64",
+        "vm-kernel-reload-linux-release-x64",
+        "vm-kernel-reload-mac-debug-simdbc64",
+        "vm-kernel-reload-mac-release-simdbc64"
+      ],
+      "meta": {
+        "description": "This is the configuration for the kernel hot reload builders."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": ["runtime_kernel"]
+        },
+        {
+          "name": "vm tests",
+          "arguments": ["--compiler=dartk", "--hot-reload", "--strong"]
+        }
+      ]
+    },
+    {
+      "builders": [
         "vm-reload-rollback-linux-debug-x64",
         "vm-reload-rollback-linux-release-x64"
       ],
@@ -761,6 +783,26 @@
     },
     {
       "builders": [
+        "vm-kernel-reload-rollback-linux-debug-x64",
+        "vm-kernel-reload-rollback-linux-release-x64"
+      ],
+      "meta": {
+        "description": "This is the configuration for kernel reload rollback builders."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": ["runtime_kernel"]
+        },
+        {
+          "name": "vm tests",
+          "arguments": ["--compiler=dartk", "--hot-reload-rollback", "--strong"]
+        }
+      ]
+    },
+    {
+      "builders": [
         "dart2js-hostchecked-linux-ia32-d8"
       ],
       "meta": {
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 2206a5c..9661adc 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -187,6 +187,7 @@
         args.add('--no-background-compilation');
       }
     } else {
+      args.add('--no-preview-dart-2');
       if (_isStrong) {
         args.add('--strong');
       }
@@ -772,6 +773,7 @@
       args.add('--preview-dart-2');
       args.addAll(_replaceDartFiles(arguments, tempKernelFile(tempDir)));
     } else {
+      args.add('--no-preview-dart-2');
       args.addAll(arguments);
     }
 
@@ -943,6 +945,8 @@
     var args = ["--snapshot=$snapshot", "--snapshot-kind=app-jit"];
     if (useDfe) {
       args.add("--preview-dart-2");
+    } else {
+      args.add("--no-preview-dart-2");
     }
     args.addAll(arguments);
 
@@ -978,6 +982,8 @@
     }
     if (useDfe) {
       args.add('--preview-dart-2');
+    } else {
+      args.add("--no-preview-dart-2");
     }
     args
       ..addAll(vmOptions)
@@ -1126,11 +1132,6 @@
       args.add('--enable_asserts');
     }
 
-    // Pass environment variable to the gen_kernel script as
-    // arguments are not passed if gen_kernel runs in batch mode.
-    environmentOverrides = new Map.from(environmentOverrides);
-    environmentOverrides['DART_VM_FLAGS'] = '--limit-ints-to-64-bits';
-
     return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
         genKernel, args, environmentOverrides);
   }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 52974f7..d7beed3 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -862,12 +862,9 @@
       // TODO(rnystrom): Hack. When running the 2.0 tests, always implicitly
       // turn on reified generics in the VM.
       // Note that VMOptions=--no-reify-generic-functions in test is ignored.
-      // Also, enable Dart 2.0 fixed-size integers with --limit-ints-to-64-bits.
       // Dart 2 VM wrapper (pkg/vm/tool/dart2) already passes correct arguments.
       if (suiteName.endsWith("_2") && !configuration.usingDart2VMWrapper) {
-        allVmOptions = allVmOptions.toList()
-          ..add("--reify-generic-functions")
-          ..add("--limit-ints-to-64-bits");
+        allVmOptions = allVmOptions.toList()..add("--reify-generic-functions");
       }
 
       var commands =
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index 6b8d88f..fbc9258 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -52,6 +52,8 @@
 }
 
 application_snapshot("dart2js") {
+  dart_version = 2
+
   deps = [
     ":compile_dart2js_platform",
     ":compile_dart2js_platform_strong",
@@ -63,7 +65,7 @@
     "$root_out_dir/dart2js_platform_strong.dill",
     "$root_out_dir/dart2js_outline_strong.dill",
   ]
-  vm_args = [ "--no_limit_ints_to_64_bits" ]
+  vm_args = []
   main_dart = "$target_gen_dir/dart2js.dart"
   training_args = [
     "--packages=" + rebase_path("../../.packages"),
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 888f89d..d6fcbaa 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -49,7 +49,7 @@
 
   deps = [
     ":dartdevc_sdk",
-    ":dartdevc_sdk_kernel_summary",
+    ":dartdevk_sdk",
   ]
 
   inputs = [ sdk_dill ]
@@ -229,13 +229,24 @@
   deps = [
     ":dartdevc",
     ":dartdevc_sdk",
-    ":dartdevc_sdk_kernel_summary",
+    ":dartdevk_sdk",
     ":dartdevc_test_pkg",
     ":dartdevk",
     "../../sdk:create_sdk",
   ]
 }
 
+# Builds everything needed to run dartdevc and dartdevk tests locally using
+# test.dart without --use-sdk. This is the same as dartdevc_test, but skips
+# things rely on building the Dart VM and create_sdk.
+group("dartdevc_test_local") {
+  deps = [
+    ":dartdevc_sdk",
+    ":dartdevk_sdk",
+    ":dartdevc_test_pkg",
+  ]
+}
+
 create_timestamp_file("dartdevc_files_stamp") {
   path = rebase_path("../../pkg/dev_compiler/lib")
   output = "$target_gen_dir/dartdevc_files.stamp"
@@ -243,11 +254,11 @@
 
 # Compiles the packages used by the tests to JS with dartdevc so that they are
 # available for loading by the tests.
-dart_action("dartdevc_test_pkg") {
+prebuilt_dart_action("dartdevc_test_pkg") {
   deps = [
     ":dartdevc_files_stamp",
     ":dartdevc_sdk",
-    ":dartdevc_sdk_kernel_summary",
+    ":dartdevk_sdk",
     "../../pkg:pkg_files_stamp",
   ]
 
@@ -304,7 +315,7 @@
 }
 
 # Compiles the DDC SDK's kernel summary and JS code.
-dart_action("dartdevc_sdk_kernel_summary") {
+prebuilt_dart_action("dartdevk_sdk") {
   deps = [
     ":dartdevc_files_stamp",
   ]
diff --git a/utils/dartdoc/BUILD.gn b/utils/dartdoc/BUILD.gn
index 0ba4fe2..688a76b 100644
--- a/utils/dartdoc/BUILD.gn
+++ b/utils/dartdoc/BUILD.gn
@@ -5,6 +5,7 @@
 import("../application_snapshot.gni")
 
 application_snapshot("dartdoc") {
+  dart_version = 2
   main_dart = "../../third_party/pkg/dartdoc/bin/dartdoc.dart"
   training_args = [ "--help" ]
 }