Merge commit '5d7786948cca6b292f6d26313f745e786a910761' into analyzer-0.33
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 928d788..bf899ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,18 @@
 
 #### Pub
 
+#### Linter
+
+The linter was bumped to `0.1.73` which introduces the following new lints to the SDK:
+
+* `unnecessary_await_in_return`
+* `use_function_type_syntax_for_parameters`
+* `avoid_returning_null_for_future`
+* `avoid_shadowing_type_parameters`
+
+In addition, `prefer_bool_in_asserts` has been deprecated as its semantics are
+redundant with Dart 2 checks.
+
 #### Other Tools
 
 ## 2.2.0-dev.0.0
@@ -24,6 +36,11 @@
   for testing and it is no longer supported. `--categories=Server` continues to
   work at this time but it is deprecated, please use `--server-mode` instead.
 
+* The `--library-root` flag was replaced by `--libraries-spec`. This flag is
+  rarely used by developers invoking dart2js directly. It's important for
+  integrating dart2js with build systems. See `--help` for more details on the
+  new flag.
+
 ## 2.1.0 - 2018-11-15
 
 This is a minor version release. The team's focus was mostly on improving
diff --git a/DEPS b/DEPS
index 965d284..bccc28f 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   "chromium_git": "https://chromium.googlesource.com",
   "fuchsia_git": "https://fuchsia.googlesource.com",
 
-  "co19_2_rev": "740cb9e9b3fc8e1da2f55e10554ffeac90461b73",
+  "co19_2_rev": "92eb86a60b26089eaffc4fa9703895f71a251a76",
 
   # As Flutter does, we pull buildtools, including the clang toolchain, from
   # Fuchsia. This revision should be kept up to date with the revision pulled
@@ -63,7 +63,7 @@
   "convert_tag": "2.0.2",
   "crypto_tag" : "2.0.6",
   "csslib_tag" : "0.14.4+1",
-  "dart2js_info_tag" : "0.5.13",
+  "dart2js_info_tag" : "0.5.15",
 
   # Note: updates to dart_style have to be coordinated carefully with
   # the infrastructure-team so that the internal formatter in
@@ -95,7 +95,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.71",
+  "linter_tag": "0.1.73",
   "logging_tag": "0.11.3+2",
   "markdown_tag": "2.0.2",
   "matcher_tag": "0.12.3",
diff --git a/WATCHLISTS b/WATCHLISTS
index aefd0f2..598f0ab 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -66,7 +66,7 @@
       'filepath': '^runtime/',
     },
     'vm_compiler': {
-      'filepath': '^runtime/compiler/',
+      'filepath': '^runtime/(vm|docs)/compiler/',
     },
   },
 
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 8025521..4bdcda6 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -261,12 +261,12 @@
     cflags += [ "-fcolor-diagnostics" ]
   }
 
-  # C++14 compiler flags setup.
+  # C++11 compiler flags setup.
   # ---------------------------
   if (is_win) {
-    cc_std = [ "/std:c++14" ]
+    cc_std = [ "/std:c++11" ]
   } else {
-    cc_std = [ "-std=c++14" ]
+    cc_std = [ "-std=c++11" ]
   }
   cflags_cc += cc_std
   cflags_objcc += cc_std
diff --git a/docs/language/dart.sty b/docs/language/dart.sty
index 0aede6b..90fcab4 100644
--- a/docs/language/dart.sty
+++ b/docs/language/dart.sty
@@ -84,11 +84,20 @@
 \newcommand{\argumentList}[1]{\metavar{{#1}s}}
 \newcommand{\parameterList}[1]{\metavar{{#1}s}}
 
-\newenvironment{Q}[1]{{\bf #1}}{}
-\newenvironment{rationale}[1]{{\it #1}}{}
-\newenvironment{commentary}[1]{{\sf #1}}{}
+% Colors used for for different kinds of text.
+\definecolor{normativeColor}{rgb}{0,0,0}
+\definecolor{commentaryColor}{rgb}{0.6,0.6,0.6}
+\definecolor{rationaleColor}{rgb}{0.6,0.6,0.6}
 
+% Environments for different kinds of text.
+\newenvironment{Q}[1]{{\bf #1}}{}
+\newenvironment{rationale}[1]{{\color{rationaleColor}\it{#1}}}{}
+\newenvironment{commentary}[1]{{\color{commentaryColor}\sf{#1}}}{}
+
+% Auxiliary functions.
 \newcommand{\flatten}[1]{\ensuremath{\mbox{\it flatten}({#1})}}
+\newcommand{\overrides}[1]{\ensuremath{\mbox{\it overrides}({#1})}}
+\newcommand{\inherited}[1]{\ensuremath{\mbox{\it inherited}({#1})}}
 
 % Used as a mini-section marker, indicating visibly that a range of
 % text (usually just a couple of paragraphs) are concerned with one
@@ -100,9 +109,17 @@
   \def\@programcr{\@addfield\strut}%
   \let\\=\@programcr%
   \relax\@vobeyspaces\obeylines%
-  \ttfamily%
+  \ttfamily\color{commentaryColor}%
   \vspace{1em}
-}{\vspace{1em}}
+}{\normalcolor\vspace{1em}}
+
+\newenvironment{normativeDartCode}[1][!ht] {
+  \def\@programcr{\@addfield\strut}%
+  \let\\=\@programcr%
+  \relax\@vobeyspaces\obeylines%
+  \ttfamily\color{normativeColor}%
+  \vspace{1em}
+}{\normalcolor\vspace{1em}}
 
 % Used for comments in a code context.
 \def\comment#1{\textsf{#1}}
@@ -121,6 +138,103 @@
 \newcommand{\NoIndex}[1]{
   \leavevmode\marginpar{\ensuremath{\diamond}}\emph{#1}}
 
+% Used to specify comma separated lists of similar symbols.
+\newcommand{\List}[3]{\ensuremath{{#1}_{#2},\,\ldots,\ {#1}_{#3}}}
+
+% Used to specify comma separated lists of pairs of similar symbols,
+% as needed, e.g., for declarations of formal parameters.
+% Parameters: Name of first part of pair, name of second part,
+% index at start, index at end.
+\newcommand{\PairList}[4]{\ensuremath{%
+  {#1}_{#3}\ {#2}_{#3},\,\ldots,\ {#1}_{#4}\ {#2}_{#4}}}
+
+% Used to specify comma separated lists of triples of similar symbols,
+% as needed, e.g., for declarations of formal parameters with defaults.
+% Parameters: Name of first part of triple, name of second part,
+% name of third part, index at start, index at end.
+\newcommand{\TripleList}[5]{\ensuremath{%
+  {#1}_{#4}\ {#2}_{#4}\ {#3}_{#4},\,\ldots,\ {#1}_{#5}\ {#2}_{#5}\ {#3}_{#5}}}
+
+% Used to abbreviate \EXTENDS{} in function types.
+\newcommand{\FunctionTypeExtends}{\ensuremath{\triangleleft}}
+
+% Used to specify comma separated lists of pairs of symbols
+% separated by \EXTENDS{}, as needed for type parameter declarations.
+% Parameters: Type parameter name, bound name, number of type parameters.
+\newcommand{\TypeParameters}[3]{\ensuremath{%
+  {#1}_1\,\EXTENDS\,{#2}_1,\,\ldots,\ %
+  {#1}_{#3}\,\EXTENDS\,{#2}_{#3}}}
+
+% For consistency, we may as well use this whenever possible.
+\newcommand{\TypeParametersStd}{\TypeParameters{X}{B}{s}}
+
+% Used to specify comma separated lists of pairs of symbols
+% separated by \EXTENDS{}, as needed for type parameter declarations.
+% Parameters: Type parameter name, bound name, number of type parameters.
+\newcommand{\FTTypeParameters}[3]{\ensuremath{%
+  {#1}_1\FunctionTypeExtends{#2}_1,\,\ldots,\ %
+  {#1}_{#3}\FunctionTypeExtends{#2}_{#3}}}
+
+% Used to specify function types: Same syntax as in source.
+% Arguments: Return type, formal parameter declarations.
+\newcommand{\FunctionTypeSimple}[2]{\code{\ensuremath{#1}\ \FUNCTION({#2})}}
+
+% Used to specify function types: Same syntax as in source.
+% Arguments: Return type, spacer, type parameter name, bound name,
+%   number of type parameters, formal parameter declarations.
+\newcommand{\FunctionType}[6]{\leavevmode\par\noindent\code{%
+  \ensuremath{#1}{#2}\FUNCTION<\FTTypeParameters{#3}{#4}{#5}>({#6})}}
+
+% Used to specify function types with positional optionals:
+% Arguments: Return type, spacer, type parameter name, bound name,
+%   number of type parameters, parameter type, number of required parameters,
+%   number of optional parameters.
+\newcommand{\FunctionTypePositional}[8]{%
+  \FunctionType{#1}{#2}{#3}{#4}{#5}{\List{#6}{1}{#7},\ %
+    [\List{#6}{{#7}+1}{{#7}+{#8}}]}}
+
+% Used to specify function types with named parameters:
+% Arguments: Return type, spacer, type parameter name, bound name,
+%   number of type parameters, parameter type, number of required parameters,
+%   name of optional parameters, number of optional parameters.
+\newcommand{\FunctionTypeNamed}[9]{%
+  \FunctionType{#1}{#2}{#3}{#4}{#5}{\List{#6}{1}{#7},\ %
+    \{\PairList{#6}{#8}{{#7}+1}{{#7}+{#9}}\}}}
+
+% Used to specify function types with no optional parameters:
+% Arguments: Return type, spacer, type parameter name, bound name,
+%   number of type parameters, parameter type,
+%   number of parameters (all required).
+\newcommand{\FunctionTypeAllRequired}[7]{%
+  \FunctionType{#1}{#2}{#3}{#4}{#5}{\List{#6}{1}{#7}}}
+
+\newcommand{\FunctionTypePositionalStd}[1]{%
+  \FunctionTypePositional{#1}{ }{X}{B}{s}{T}{n}{k}}
+
+\newcommand{\FunctionTypeNamedStd}[1]{%
+  \FunctionTypeNamed{#1}{ }{X}{B}{s}{T}{n}{x}{k}}
+
+\newcommand{\FunctionTypeAllRequiredStd}[1]{%
+  \FunctionTypeAllRequired{#1}{ }{X}{B}{s}{T}{n}}
+
+\newcommand{\FunctionTypePositionalStdCr}[1]{%
+  \FunctionTypePositional{#1}{\\}{X}{B}{s}{T}{n}{k}}
+
+\newcommand{\FunctionTypeNamedStdCr}[1]{%
+  \FunctionTypeNamed{#1}{\\}{X}{B}{s}{T}{n}{x}{k}}
+
+\newcommand{\FunctionTypeAllRequiredStdCr}[1]{%
+  \FunctionTypeAllRequired{#1}{\\}{X}{B}{s}{T}{n}}
+
+\newcommand{\MoreSignatureSpecificSymbol}{\ensuremath{\preceq}}
+\newcommand{\NotMoreSignatureSpecificSymbol}{\ensuremath{\not\preceq}}
+\newcommand{\LessSignatureSpecificSymbol}{\ensuremath{\succeq}}
+
+\newcommand{\MoreSignatureSpecific}[2]{%
+  \ensuremath{{#1}\MoreSignatureSpecificSymbol{#2}}}
+\newcommand{\NotMoreSignatureSpecific}[2]{%
+  \ensuremath{{#1}\NotMoreSignatureSpecificSymbol{#2}}}
+
 % ----------------------------------------------------------------------
 % Support for hash valued Location Markers
 
@@ -140,7 +254,8 @@
 
 % insert location marker showing hash value of following paragraph
 \newcommand{\LMHash}[1]{\leavevmode\marginpar{\quad%
-    \raisebox{0.5ex}{\miniscule{\color{LMdim}#1}}\vspace{-2\baselineskip}}}
+    \raisebox{0.5ex}{\miniscule{\color{LMdim}#1}}\vspace{-2\baselineskip}}%
+  \color{normativeColor}}
 
 % support convenient renewcommand
 \let\OriginalLMHash\LMHash
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index ecc249e..ffc6d8e 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -1,12 +1,13 @@
 \documentclass[makeidx]{article}
 \usepackage{xspace}
 \usepackage{epsfig}
-\usepackage{color}
+\usepackage{xcolor}
 \usepackage{syntax}
 \usepackage{dart}
 \usepackage{hyperref}
 \usepackage{lmodern}
 \usepackage[T1]{fontenc}
+\usepackage[fleqn]{amsmath}
 \usepackage{makeidx}
 \makeindex
 \title{Dart Programming Language Specification\\
@@ -73,6 +74,18 @@
 % - Specify that super-bounded generic type alias applications must trigger
 %   a well-boundedness check on all types occurring in the denoted type.
 % - Corrected corner case of rules for generation of noSuchMethod forwarders.
+% - Integrate feature specification on parameters that are
+%   covariant-by-declaration.
+% - Integrate feature specification on parameters that are
+%   covariant-by-class.
+% - Correct section 'Type of a function', allowing for adjustments needed
+%   for rules related to covariant parameters.
+% - Specified the dynamic type of function objects in several contexts, such
+%   that the special treatment of covariant parameters can be mentioned.
+% - Specified what it means for an override relation to be correct, thus
+%   adding the parts that are not captured by a function type subtype check.
+% - Introduced the notion of member signatures, specified that they are the
+%   kind of entity that a class interface contains.
 %
 % 2.0
 % - Don't allow functions as assert test values.
@@ -287,7 +300,7 @@
 An example would be:
 }
 
-\begin{grammar}
+\begin{grammar}\color{commentaryColor}
 <aProduction> ::= <anAlternative>
   \alt <anotherAlternative>
   \alt <oneThing> <after> <another>
@@ -710,7 +723,7 @@
 \begin{grammar}
 <variableDeclaration> ::= <declaredIdentifier> (`,' <identifier>)*
 
-<declaredIdentifier> ::= <metadata> <finalConstVarOrType> <identifier>
+<declaredIdentifier> ::= <metadata> \COVARIANT{}? <finalConstVarOrType> <identifier>
 
 <finalConstVarOrType> ::= \FINAL{} <type>?
   \alt \CONST{} <type>?
@@ -728,17 +741,14 @@
 \end{grammar}
 
 \LMHash{}%
-A variable declaration that contains one or more terms of the form
-\syntax{<identifier>}
-(\commentary{i.e., a declaration that declares two or more variables})
+A \synt{variableDeclaration} that declares two or more variables
 is equivalent to multiple variable declarations declaring
 the same set of variable names in the same order,
 with the same type and modifiers.
 
 \LMHash{}%
-An \syntax{<initializedVariableDeclaration>} that contains one or more terms of the form
-\syntax{<initializedIdentifier>}
-(\commentary{that is, a declaration that declares two or more initialized variables})
+An \synt{initializedVariableDeclaration}
+that declares two or more variables
 is equivalent to multiple variable declarations declaring
 the same set of variable names, in the same order,
 with the same initialization, type, and modifiers.
@@ -755,6 +765,14 @@
 }
 
 \LMHash{}%
+It is possible for a variable declaration to include the modifier \COVARIANT{}.
+The effect of doing this with an instance variable is described elsewhere
+(\ref{instanceVariables}).
+It is a compile-time error for the declaration of
+a variable which is not an instance variable
+to include the modifier \COVARIANT{}.
+
+\LMHash{}%
 In a variable declaration of one of the forms
 \code{$N$ $v$;}
 \code{$N$ $v$ = $e$;}
@@ -769,7 +787,7 @@
 \commentary{
 In an expression of the form \code{$e$.\id} it is possible that
 $e$ has static type \DYNAMIC{} and \id{} cannot be associated with
-any declaration named \id{} at compile-time,
+any specific declaration named \id{} at compile-time,
 but in this situation \id{} is still a referencing identifier.
 }
 
@@ -813,7 +831,8 @@
 %% then we treat `var x;` as if it had been `T x;`.
 
 \LMHash{}%
-The following rules apply to all static and instance variables.
+The following rules on implicitly induced getters and setters
+apply to all static and instance variables.
 
 \LMHash{}%
 A variable declaration of one of the forms
@@ -1259,8 +1278,8 @@
 <functionFormalParameter> ::= \gnewline{}
   <metadata> \COVARIANT{}? <returnType>? <identifier> <formalParameterPart>
 
-<simpleFormalParameter> ::= \gnewline{}
-  <metadata> \COVARIANT{}? <finalConstVarOrType>? <identifier>
+<simpleFormalParameter> ::= <declaredIdentifier>
+  \alt <metadata> \COVARIANT{}? <identifier>
 
 <fieldFormalParameter> ::= \gnewline{}
   <metadata> <finalConstVarOrType>? \THIS{} `.' <identifier> \gnewline{}
@@ -1268,12 +1287,15 @@
 \end{grammar}
 
 \LMHash{}%
-It is possible to include the modifier \COVARIANT{} in some forms of parameter declarations.
-This modifier has no effect.
+It is possible to include the modifier \COVARIANT{}
+in some forms of parameter declarations.
+The effect of doing this is described in a separate section
+(\ref{covariantParameters}).
 
-\rationale{
-The modifier \COVARIANT{} is used in strong mode.
-The modifier is allowed here even though it has no effect, such that source code can be used in both contexts.
+\commentary{
+Note that the non-terminal \synt{normalFormalParameter} is also used
+in the grammar rules for optional parameters,
+which means that such parameters can also be covariant.
 }
 
 \LMHash{}%
@@ -1314,72 +1336,281 @@
 }
 
 
+\subsubsection{Covariant Parameters}
+\LMLabel{covariantParameters}
+
+\LMHash{}%
+Dart allows formal parameters of instance methods,
+including setters and operators,
+to be declared \COVARIANT{}.
+\commentary{
+The syntax for doing this is specified in an earlier section (\ref{requiredFormals}).
+}
+
+\LMHash{}%
+It is a compile-time error if the modifier \COVARIANT{} occurs
+in the declaration of a formal parameter of a function
+which is not an instance method, an instance setter, or an operator.
+
+\commentary{
+As specified below, a parameter can also be covariant for other reasons.
+The overall effect of having a covariant parameter $p$
+in the signature of a given method $m$
+is to allow the type of $p$ to be overridden covariantly,
+which means that the type required at run time for a given actual argument
+may be a proper subtype of the type which is known at compile time
+at the call site.
+}
+
+\rationale{
+This mechanism allows developers to explicitly request that
+a compile-time guarantee which is otherwise supported
+(namely: that an actual argument whose static type satisfies the requirement
+will also do so at run time)
+is replaced by dynamic type checks.
+In return for accepting these dynamic type checks,
+developers can use covariant parameters to express software designs
+where the dynamic type checks are known (or at least trusted) to succeed,
+based on reasoning that the static type analysis does not capture.
+}
+
+\LMHash{}%
+Let $m$ be a method signature with formal type parameters
+\List{X}{1}{s},
+positional formal parameters \List{p}{1}{n},
+and named formal parameters \List{q}{1}{k}.
+Let $m'$ be a method signature with formal type parameters
+\List{X'\!}{1}{s},
+positional formal parameters \List{p'\!}{1}{n'},
+and named formal parameters \List{q'\!}{1}{k'}.
+%
+Assume that $j \in 1 .. n'$, and $j \leq n$;
+we say that $p'_j$ is the parameter in $m'$ that
+\IndexCustom{corresponds}{parameter corresponds to parameter}
+to the formal parameter $p_j$ in $m$.
+Assume that $j \in 1 .. k'$ and $l \in 1 .. k$;
+we say that $q'_j$ is the parameter in $m'$ that
+\NoIndex{corresponds} to the formal parameter
+$q_l$ in $m$ if $q'_j = q_l$.
+%
+Similarly, we say that the formal type parameter
+$X'_j$ from $m'$
+\NoIndex{corresponds} to the formal type parameter
+$X_j$ from $m$, for all $j \in 1 .. s$.
+
+\commentary{
+This includes the case where $m$ respectively $m'$ has
+optional positional parameters,
+in which case $k = 0$ respectively $k' = 0$ must hold,
+but we can have $n \not= n'$.
+The case where the numbers of formal type parameters differ is not relevant.
+}
+
+% Being covariant is a property of a parameter of the interface of a class;
+% this means that we only talk about the originating keyword \COVARIANT{}
+% and the class that contains the relevant declaration when we detect for
+% the first time that a given parameter is covariant. From that point and on
+% it is "carried" along the subtype links associated with class interfaces,
+% such that we can get it inductively from an indirect superinterface just
+% by checking whether the direct superinterfaces "have" a method signature
+% with the relevant name and a corresponding parameter, and then checking
+% that parameter. The same approach is applicable for covariant-by-class.
+
+\LMHash{}%
+Let $C$ be a class that declares a method $m$ which has
+a parameter $p$ whose declaration has the modifier \COVARIANT{};
+in this case we say that the parameter $p$ is
+\IndexCustom{covariant-by-declaration}{parameter!covariant-by-declaration}.
+%
+In this case the interface of $C$ has the method signature $m$,
+and that signature has the parameter $p$;
+we also say that the parameter $p$ in this method signature is
+\NoIndex{covariant-by-declaration}.
+%
+Finally, the parameter $p$ of the method signature $m$
+of the interface of a class $C$ is
+\NoIndex{covariant-by-declaration}
+if a direct superinterface of $C$
+has an accessible method signature $m'$ with the same name as $m$,
+which has a parameter $p'$ that corresponds to $p$,
+such that $p'$ is covariant-by-declaration.
+
+\LMHash{}%
+Assume that $C$ is a generic class with formal type parameter declarations
+\code{$X_1\ \EXTENDS\ B_1 \ldots,\ X_s\ \EXTENDS\ B_s$},
+let $m$ be a declaration of an instance method in $C$
+(which can be a method, a setter, or an operator),
+let $p$ be a parameter declared by $m$, and
+let $T$ be the declared type of $p$.
+%
+The parameter $p$ is
+\IndexCustom{covariant-by-class}{parameter!covariant-by-class}
+if, for any $j \in 1 .. s$,
+$X_j$ occurs in a covariant or an invariant position in $T$.
+%
+In this case the interface of $C$ also has the method signature $m$,
+and that signature has the parameter $p$;
+we also say that the parameter $p$ in this method signature is
+\NoIndex{covariant-by-class}.
+Finally, the parameter $p$ of the method signature $m$
+of the interface of the class $C$ is
+\NoIndex{covariant-by-class}
+if a direct superinterface of $C$
+has an accessible method signature $m'$ with the same name as $m$,
+which has a parameter $p'$ that corresponds to $p$,
+such that $p'$ is covariant-by-class.
+
+\LMHash{}%
+A formal parameter $p$ is
+\IndexCustom{covariant}{parameter!covariant}
+if $p$ is covariant-by-declaration or $p$ is covariant-by-class.
+
+\commentary{
+It is possible for a parameter to be simultaneously
+covariant-by-declaration and covariant-by-class.
+Note that a parameter may be
+covariant-by-declaration or covariant-by-class
+based on a declaration in any direct or indirect superinterface,
+including any superclass:
+The definitions above propagate these properties
+to an interface from each of its direct superinterfaces,
+but they will in turn receive the property from their direct superinterfaces,
+and so on.
+}
+
+
 \subsection{Type of a Function}
 \LMLabel{typeOfAFunction}
 
 \LMHash{}%
-If a function declaration does not declare a return type explicitly, its return type is \DYNAMIC{} (\ref{typeDynamic}),
-unless it is a constructor function, in which case its return type is the immediately enclosing class,
-or it is a setter or operator \code{[]=}, in which case its return type is \VOID{}.
+This section specifies the static type which is ascribed to
+the function denoted by a function declaration,
+and the dynamic type of the corresponding function object.
+
+\LMHash{}%
+In this specification,
+the notation used to denote the type of a function follows
+the syntax of the language, except that \EXTENDS{} is abbreviated to
+\FunctionTypeExtends.
+This means that every function type is of one of the forms
+\FunctionTypePositionalStd{T_0}
+\FunctionTypeNamedStd{T_0}
+
+\noindent
+where $T_0$ is the return type,
+$X_j$ are the formal type parameters with bounds $B_j$, $j \in 1 .. s$,
+$T_j$ are the formal parameter types for $j \in 1 .. n + k$.
+Non-generic function types are covered by the case $s = 0$,
+where the type parameter declaration list
+\code{<\ldots{}>}
+as a whole is omitted.
+%
+Similarly, the optional brackets \code{[]} and \code{\{\}} are omitted
+when there are no optional parameters.
+
+% We promise that the two forms always get the same treatment for k=0.
+\commentary{
+Both forms with optionals cover function types with no optionals when $k = 0$,
+and every rule in this specification is such that
+any of the two forms may be used without ambiguity
+to determine the treatment of function types with no optionals.
+}
+
+\LMHash{}%
+If a function declaration does not declare a return type explicitly,
+its return type is \DYNAMIC{} (\ref{typeDynamic}),
+unless it is a constructor,
+in which case it is not considered to have a return type,
+or it is a setter or operator \code{[]=},
+in which case its return type is \VOID{}.
 
 \LMHash{}%
 A function declaration may declare formal type parameters.
-The type of the function includes the names of the type parameters and their upper bounds.
+The type of the function includes the names of the type parameters
+and for each type parameter the upper bound,
+which is considered to be the built-in class \code{Object} if no bound is specified.
 When consistent renaming of type parameters can make two function types identical,
 they are considered to be the same type.
 
 \commentary{
-It is convenient to include the type parameter names in function types because they are needed in order to express such things as relations among different type parameters, and F-bounds.
-However, we do not wish to distinguish two function types if they have the same structure and only differ in the choice of names.
+It is convenient to include the formal type parameter names in function types
+because they are needed in order to express such things as relations among
+different type parameters, F-bounds, and the types of formal parameters.
+However, we do not wish to distinguish between two function types if they have
+the same structure and only differ in the choice of names.
 This treatment of names is also known as alpha-equivalence.
 }
 
 \LMHash{}%
 In the following three paragraphs,
-if the number $m$ of formal type parameters is zero then the type parameter list in the function type should be omitted.
+if the number $m$ of formal type parameters is zero then
+the type parameter list in the function type is omitted.
 
 \LMHash{}%
 Let $F$ be a function with
-formal type parameters $X_1\ B_1, \ldots,\ X_m\ B_m$,
-required formal parameters $T_1\ p_1, \ldots,\ T_n\ p_n$,
-return type $T_0$
+type parameters \TypeParametersStd,
+required formal parameter types \List{T}{1}{n},
+return type $T_0$,
 and no optional parameters.
-Then the type of $F$ is
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n$) $ \rightarrow T_0$}.
+Then the static type of $F$ is
+\FunctionTypeAllRequiredStd{T_0}.
 
 \LMHash{}%
 Let $F$ be a function with
-formal type parameters $X_1\ B_1, \ldots,\ X_m\ B_m$,
-required formal parameters $T_1\ p_1, \ldots,\ T_n\ p_n$,
+type parameters \TypeParametersStd,
+required formal parameter types  \List{T}{1}{n},
 return type $T_0$
-and positional optional parameters $T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}$.
-Then the type of $F$ is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}$]) $ \rightarrow T_0$}.
+and positional optional parameter types \List{T}{n+1}{n+k}.
+Then the static type of $F$ is
+\FunctionTypePositionalStd{T_0}.
 
 \LMHash{}%
 Let $F$ be a function with
-formal type parameters $X_1\ B_1, \ldots,\ X_m\ B_m$,
-required formal parameters $T_1\ p_1, \ldots,\ T_n\ p_n$,
-return type $T_0$
-and named optional parameters $T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}$.
-Then the type of $F$ is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}$\}) $ \rightarrow T_0$}.
+type parameters \TypeParametersStd,
+required formal parameter types \List{T}{1}{n},
+return type $T_0$,
+and named parameters \PairList{T}{x}{n+1}{n+k}.
+Then the static type of $F$ is
+\FunctionTypeNamedStd{T_0}.
 
 \LMHash{}%
-The run-time type of a function object always implements the class \FUNCTION{}.
-
+Let $T$ be the static type of a function declaration $F$.
+Let $u$ be the run-time type of a function object $o$ obtained by
+function closurization
+(\ref{functionClosurization})
+or instance method closurization
+(\ref{ordinaryMemberClosurization})
+applied to $F$,
+and let $t$ be the actual type corresponding to $T$
+at the occasion where $o$ was created
+(\ref{actualTypeOfADeclaration}).
+\commentary{$T$ may contain free type variables, but $t$ contains their actual values.}
+The following must then hold:
+$u$ is a class that implements the built-in class \FUNCTION{};
+$u$ is a subtype of $t$;
+and $u$ is not a subtype of any function type which is a proper subtype of $t$.
 \commentary{
-One cannot assume, based on the above, that given a function \code{f}, \code{f.runtimeType} will actually be \FUNCTION{}, or that any two distinct function objects necessarily have the same run-time type.
+If we had omitted the last requirement then
+\code{f \IS{} int\,\FUNCTION([int])}
+could evaluate to \TRUE{} with the declaration
+\code{void f()\,\{\}},
+e.g., by letting $u$ be \code{Null}.
 }
 
 \rationale{
-It is up to the implementation to choose an appropriate representation for function objects.
-For example, consider that a function object produced via property extraction treats equality differently from other function objects, and is therefore likely a different class.
-Implementations may also use different classes for function objects based on arity and or type.
-Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not.
-The variations are manifold, and so this specification only guarantees that function objects are instances of some class that implements \FUNCTION{}.
+It is up to the implementation to choose
+an appropriate representation for function objects.
+For example, consider that
+a function object produced via property extraction
+treats equality differently from other function objects,
+and is therefore likely a different class.
+Implementations may also use different classes for function objects
+based on arity and or type.
+Arity may be implicitly affected by whether a function is
+an instance method (with an implicit receiver parameter) or not.
+The variations are manifold and, e.g.,
+one cannot assume that any two distinct function objects
+will necessarily have the same run-time type.
 }
 
 
@@ -1431,7 +1662,6 @@
 
 <methodSignature> ::= <constructorSignature> <initializers>?
   \alt <factoryConstructorSignature>
-% This doesn't work: `static @override foo() => 42`, but `functionSignature` starts with metadata. https://github.com/dart-lang/sdk/issues/29614
   \alt \STATIC{}? <functionSignature>
   \alt \STATIC{}? <getterSignature>
   \alt \STATIC{}? <setterSignature>
@@ -1444,10 +1674,8 @@
   \alt ((\EXTERNAL{} \STATIC{}?))? <getterSignature>
   \alt ((\EXTERNAL{} \STATIC{}?))? <setterSignature>
   \alt \EXTERNAL{}? <operatorSignature>
-% This doesn't work: `static @override foo() => 42`, but `functionSignature` starts with metadata. https://github.com/dart-lang/sdk/issues/29614
   \alt ((\EXTERNAL{} \STATIC{}?))? <functionSignature>
   \alt \STATIC{} (\FINAL{} | \CONST{}) <type>? <staticFinalDeclarationList>
-%      \CONST{} type? staticFinalDeclarationList;
   \alt \FINAL{} <type>? <initializedIdentifierList>
   \alt (\STATIC{} | \COVARIANT{})? (\VAR{} | <type>) <initializedIdentifierList>
 
@@ -1459,12 +1687,8 @@
 
 \LMHash{}%
 It is possible to include the modifier \COVARIANT{} in some forms of declarations.
-This modifier has no effect.
-
-\rationale{
-The modifier \COVARIANT{} is used in strong mode.
-The modifier is allowed here even though it has no effect, such that source code can be used in both contexts.
-}
+The effect of doing this is described elsewhere
+(\ref{covariantParameters}).
 
 \LMHash{}%
 A class has constructors, instance members and static members.
@@ -1510,13 +1734,57 @@
 
 \rationale{
 We want different behavior for concrete classes and abstract classes.
-If $A$ is intended to be abstract, we want the static checker to warn about any attempt to instantiate $A$, and we do not want the checker to complain about unimplemented methods in $A$.
-In contrast, if $A$ is intended to be concrete, the checker should warn about all unimplemented methods, but allow clients to instantiate it freely.
+If $A$ is intended to be abstract,
+we want the static checker to warn about any attempt to instantiate $A$,
+and we do not want the checker to complain about unimplemented methods in $A$.
+In contrast, if $A$ is intended to be concrete,
+the checker should warn about all unimplemented methods,
+but allow clients to instantiate it freely.
+}
+
+\commentary{
+The interface of a class $C$ is
+an implicit interface that declares instance member signatures
+that correspond to the instance members declared by $C$,
+and whose direct superinterfaces are
+the direct superinterfaces of $C$
+(\ref{interfaces}, \ref{superinterfaces}).
 }
 
 \LMHash{}%
-The \Index{interface of a class} $C$ is an implicit interface that declares instance members that correspond to the instance members declared by $C$, and whose direct superinterfaces are the direct superinterfaces of $C$ (\ref{superinterfaces}).
-When a class name appears as a type, that name denotes the interface of the class.
+When a class name appears as a type,
+that name denotes the interface of the class.
+
+\LMHash{}%
+% The use of 'concrete member' below may seem redundant, because a class
+% does not inherit abstract members from its superclass, but this
+% underscores the fact that even when an abstract declaration of $m$ is
+% declared in $C$, $C$ does not "have" $m$.
+A concrete class must fully implement its interface:
+Let $C$ be a concrete class with interface $I$.
+Assume that $I$ has an accessible member signature $m$.
+It is a compile-time error if $C$ does not have
+a concrete accessible member with the same name as $m$,
+unless $C$ has a non-trivial \code{noSuchMethod}
+(\ref{theMethodNoSuchMethod}).
+It is a compile-time error if $C$ has
+a concrete accessible member with the same name as $m$,
+with a method signature $m'$ which is not a correct override of $m$
+(\ref{correctMemberOverrides}),
+unless that concrete member is a \code{noSuchMethod} forwarder
+(\ref{theMethodNoSuchMethod}).
+
+\commentary{
+In particular, it is an error for a class to be concrete even if it inherits
+a member implementation for every member signature in its interface,
+unless each of them has parameters and types such that they satisfy
+the corresponding member signature.
+But when there is a non-trivial \code{noSuchMethod} it is allowed
+to leave some members unimplemented,
+and it is allowed to to have a \code{noSuchMethod} forwarder which does not
+satisfy the class interface
+(in which case it will be overridden by another \code{noSuchMethod} forwarder).
+}
 
 % making an exception for the setters generated for final fields is tempting but problematic.
 % If a super type defines a setter, it will be overridden yet have no impact on the interface.
@@ -1569,28 +1837,73 @@
 \LMLabel{instanceMethods}
 
 \LMHash{}%
-Instance methods are functions (\ref{functions}) whose declarations are immediately contained within a class declaration and that are not declared \STATIC{}.
-The instance methods of a class $C$ are those instance methods declared by $C$ and the instance methods inherited by $C$ from its superclass.
+\IndexCustom{Instance methods}{method!instance}
+are functions (\ref{functions})
+whose declarations are immediately contained within a class declaration
+and that are not declared \STATIC{}.
+The \Index{instance methods of a class} $C$ are the instance methods declared by $C$
+and the instance methods inherited by $C$ from its superclass
+(\ref{inheritanceAndOverriding}).
 
 \LMHash{}%
-It is a compile-time error if an instance method $m_1$ overrides (\ref{inheritanceAndOverriding}) an instance member $m_2$ and $m_1$ has a greater number of required parameters than $m_2$.
-It is a compile-time error if an instance method $m_1$ overrides an instance member $m_2$ and $m_1$ has fewer positional parameters than $m_2$.
-It is a compile-time error if an instance method $m_1$ overrides an instance member $m_2$ and $m_1$ does not declare all the named parameters declared by $m_2$.
-
-\LMHash{}%
-%% TODO(eernst): We need to use the concept of 'correctly overrides' rather than 'is a subtype of', e.g., to treat `void` correctly.
-It is a compile-time error 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$.
+Consider a class $C$.
+It is a compile-time error if an instance method declaration in $C$ has
+a member signature $m$
+(\ref{interfaces})
+% Note that $m'$ is accessible, due to the definition of 'overrides'.
+which overrides a member signature $m'$
+from a direct superinterface of $C$
+(\ref{interfaceInheritanceAndOverriding}),
+unless this is a correct member override
+(\ref{correctMemberOverrides}).
 
 \commentary{
-A method declaration may conflict with other declarations
+This is not the only kind of conflict that may exist:
+An instance member declaration $D$ may conflict with another declaration $D'$,
+even in the case where they do not have the same name
+or they are not the same kind of declaration.
+E.g., $D$ could be an instance getter and $D'$ a static setter
 (\ref{classMemberConflicts}).
 }
 
+\LMHash{}%
+For each parameter $p$ of $m$ where \COVARIANT{} is present,
+it is a compile-time error if there exists
+a direct or indirect superinterface $J$ of $C$ which has
+an accessible method signature $m''$ with the same name as $m$,
+such that $m''$ has a parameter $p''$ that corresponds to $p$
+(\ref{covariantParameters}),
+unless the type of $p$ is assignable to the type of $p''$.
+
+\commentary{
+This means that
+a parameter which is covariant-by-declaration can have a type
+which is a supertype or a subtype of the type of
+a corresponding parameter in a superinterface,
+but the two types cannot be unrelated.
+Note that this requirement must be satisfied
+for each direct or indirect superinterface separately,
+because assignability is not transitive.
+}
+
+\rationale{
+The superinterface may be the statically known type of the receiver,
+so this means that we relax the potential typing relationship
+between the statically known type of a parameter and the
+type which is actually required at run time
+to the assignability relationship,
+rather than the strict supertype relationship
+which applies to a parameter which is not covariant.
+It should be noted that it is not statically known
+at the call site whether any given parameter is covariant,
+because the covariance could be introduced in
+a proper subtype of the statically known type of the receiver.
+We chose to give priority to flexibility rather than safety here,
+because the whole point covariant parameters is that developers
+can make the choice to increase the flexibility
+in a trade-off where some static type safety is lost.
+}
+
 
 \subsubsection{Operators}
 \LMLabel{operators}
@@ -2027,23 +2340,25 @@
 A getter definition that is prefixed with the \STATIC{} modifier defines a static getter.
 Otherwise, it defines an instance getter.
 The name of the getter is given by the identifier in the definition.
-The effect of a static getter declaration in class $C$ is to add an instance getter with the same name and signature to the \code{Type} object for class $C$ that forwards (\ref{functionDeclarations}) to the static getter.
 
 \LMHash{}%
-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$.
+The \Index{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 \Index{static getters of a class} $C$ are
+those static getters declared by $C$.
 
 \commentary{
 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.
+The rules for when a getter correctly overrides another member
+are given elsewhere
+(\ref{correctMemberOverrides}).
 }
 
-\LMHash{}%
-It is a compile-time error if a getter $m_1$ overrides (\ref{inheritanceAndOverriding}) a getter $m_2$
-and the return type of $m_1$ is not a subtype of the return type of $m_2$.
-
 
 \subsection{Setters}
 \LMLabel{setters}
@@ -2063,33 +2378,39 @@
 A setter definition that is prefixed with the \STATIC{} modifier defines a static setter.
 Otherwise, it defines an instance setter.
 The name of a setter is obtained by appending the string `=' to the identifier given in its signature.
-The effect of a static setter declaration in class $C$ is to add an instance setter with the same name and signature to the \code{Type} object for class $C$ that forwards (\ref{functionDeclarations}) to the static setter.
 
 \commentary{
 Hence, a setter name can never conflict with, override or be overridden by a getter or method.
 }
 
 \LMHash{}%
-The instance setters of a class $C$ are those instance setters declared by $C$ either implicitly or explicitly, and the instance setters inherited by $C$ from its superclass.
-The static setters of a class $C$ are those static setters declared by $C$.
+The \Index{instance setters of a class} $C$ are
+those instance setters declared by $C$
+either implicitly or explicitly,
+and the instance setters inherited by $C$ from its superclass.
+The \Index{static setters of a class} $C$ are
+those static setters declared by $C$,
+either implicitly or explicitly.
 
 \LMHash{}%
-It is a compile-time error if a setter's formal parameter list does not consist of exactly one required formal parameter $p$.
+It is a compile-time error if a setter's formal parameter list
+does not consist of exactly one required formal parameter $p$.
 \rationale{
 We could enforce this via the grammar, but we'd have to specify the evaluation rules in that case.
 }
 
 \LMHash{}%
 It is a static warning if a setter declares a return type other than \VOID{}.
-It is a compile-time error if a setter $m_1$ overrides (\ref{inheritanceAndOverriding}) a setter $m_2$
-and the parameter type of $m_1$ is not a supertype of the parameter type of $m_2$.
 It is a static warning if a class has
-a setter named $v=$ with argument type $T$ and
+a setter named \code{$v$=} with argument type $T$ and
 a getter named $v$ with return type $S$,
 and $S$ may not be assigned to $T$.
 
 \commentary{
-A setter declaration may conflict with other declarations
+The rules for when a setter correctly overrides another member
+are given elsewhere
+(\ref{correctMemberOverrides}).
+A setter declaration may conflict with other declarations as well
 (\ref{classMemberConflicts}).
 }
 
@@ -2110,14 +2431,15 @@
 is an instance method, getter or setter that is not abstract.
 
 \rationale{
-Earlier versions of Dart required that abstract members be identified by prefixing them with the modifier \ABSTRACT{}.
-The elimination of this requirement is motivated by the desire to use abstract classes as interfaces.
-Every Dart class induces an implicit interface.
-
-Using an abstract class instead of an interface has important advantages.
-An abstract class can provide default implementations; it can also provide static methods, obviating the need for service classes such as \code{Collections} or \code{Lists}, whose entire purpose is to group utilities related to a given type.
-
-Eliminating the requirement for an explicit modifier on members makes abstract classes more concise, making abstract classes an attractive substitute for interface declarations.
+Abstract instance members are useful because of their interplay with classes.
+Every Dart class induces an implicit interface,
+and Dart does not support specifying interfaces explicitly.
+Using an abstract class instead of a traditional interface
+has important advantages.
+An abstract class can provide default implementations.
+It can also provide static methods,
+obviating the need for service classes such as \code{Collections} or \code{Lists},
+whose entire purpose is to group utilities related to a given type.
 }
 
 \commentary{
@@ -2133,22 +2455,12 @@
 }
 
 \rationale{
-The purpose of an abstract method is to provide a declaration for purposes such as type checking and reflection.
-In classes used as mixins, it is often useful to introduce such declarations for methods that the mixin expects will be provided by the superclass the mixin is applied to.
+The purpose of an abstract method is to provide a declaration
+for purposes such as type checking and reflection.
+In mixins, it is often useful to introduce such declarations for methods that
+the mixin expects will be provided by the superclass the mixin is applied to.
 }
 
-\LMHash{}%
-%% TODO(eernst): This is semi-redundant: We should define what it means for
-%% a class to be 'fully implemented' and require once and for all that it is
-%% a compile-time error if a concrete class is not fully implemented. That
-%% is very nearly what line 2706++ already says. This will then be commentary,
-%% just focusing on the case where a concrete $C$ _declares_ an abstract $m$.
-It is a compile-time error if an abstract member $m$ is declared or inherited in a concrete class $C$ unless:
-\begin{itemize}
-\item $m$ overrides a concrete member, or
-\item $C$ has a concrete \code{noSuchMethod()} method distinct from the one declared in class \code{Object}.
-\end{itemize}
-
 \rationale{
 We wish to detect if one declares a concrete class with abstract members.
 However, code like the following should work:
@@ -2177,8 +2489,13 @@
 \LMLabel{instanceVariables}
 
 \LMHash{}%
-Instance variables are variables whose declarations are immediately contained within a class declaration and that are not declared \STATIC{}.
-The instance variables of a class $C$ are those instance variables declared by $C$ and the instance variables inherited by $C$ from its superclass.
+\IndexCustom{Instance variables}{variables!instance}
+are variables whose declarations
+are immediately contained within a class declaration
+and that are not declared \STATIC{}.
+The \Index{instance variables of a class} $C$ are
+the instance variables declared by $C$
+and the instance variables inherited by $C$ from its superclass.
 
 \LMHash{}%
 It is a compile-time error if an instance variable is declared to be constant.
@@ -2195,6 +2512,23 @@
 An instance getter for it can always be defined manually if desired.
 }
 
+\LMHash{}%
+It is possible for the declaration of an instance variable
+to include the modifier \COVARIANT{}
+(\ref{variables}).
+The effect of this is that the formal parameter of
+the corresponding implicitly induced setter
+is considered to be covariant-by-declaration
+(\ref{covariantParameters}).
+
+\commentary{
+The modifier \COVARIANT{} on an instance variable has no other effects.
+In particular, the return type of the implicitly induced getter
+can already be overridden covariantly without \COVARIANT{},
+and it can never be overridden to a supertype or an unrelated type,
+regardless of whether the modifier \COVARIANT{} is present.
+}
+
 
 \subsection{Constructors}
 \LMLabel{constructors}
@@ -2282,6 +2616,7 @@
 \LMHash{}%
 Initializing formals are executed during the execution of generative constructors detailed below.
 Executing an initializing formal \code{\THIS{}.\id} causes the instance variable \id{} of the immediately surrounding class to be assigned the value of the corresponding actual parameter,
+%% TODO(eernst): This should be a compile-time error -- check, revise if true!
 unless \id{} is a final variable that has already been initialized, in which case a run-time error occurs.
 
 \commentary{
@@ -2687,13 +3022,13 @@
 $T$ is a type name, and \id{} is an identifier,
 then consider a declaration of a redirecting factory constructor $k$ of one of the forms
 
-\begin{dartCode}
+\begin{normativeDartCode}
 $\ConstMetavar$ \FACTORY{}
     $N$($T_1\ x_1 \ldots,\ T_n\ x_n,\ $[$T_{n+1}\ x_{n+1}$=$d_1, \ldots,\ T_{n+k}\ x_{n+k}$=$d_k$]) = $R$;
 \\
 $\ConstMetavar$ \FACTORY{}
     $N$($T_1\ x_1 \ldots,\ T_n\ x_n,\ $\{$T_{n+1}\ x_{n+1}$=$d_1, \ldots,\ T_{n+k}\ x_{n+k}$=$d_k$\}) = $R$;
-\end{dartCode}
+\end{normativeDartCode}
 
 \noindent
 where $R$ is of one of the forms
@@ -2946,16 +3281,16 @@
 are functions, other than getters or setters, whose declarations are immediately contained within a class declaration and that are declared \STATIC{}.
 The static methods of a class $C$ are those static methods declared by $C$.
 
-\LMHash{}%
-The effect of a static method declaration in class $C$ is to add an instance method with the same name and signature to the \code{Type} object for class $C$ that forwards (\ref{functionDeclarations}) to the static method.
-
 \rationale{
 Inheritance of static methods has little utility in Dart.
 Static methods cannot be overridden.
-Any required static function can be obtained from its declaring library, and there is no need to bring it into scope via inheritance.
-Experience shows that developers are confused by the idea of inherited methods that are not instance methods.
+Any required static function can be obtained from its declaring library,
+and there is no need to bring it into scope via inheritance.
+Experience shows that developers are confused by
+the idea of inherited methods that are not instance methods.
 
-Of course, the entire notion of static methods is debatable, but it is retained here because so many programmers are familiar with it.
+Of course, the entire notion of static methods is debatable,
+but it is retained here because so many programmers are familiar with it.
 Dart static methods may be seen as functions of the enclosing library.
 }
 
@@ -3067,7 +3402,7 @@
 Let $C = S_0$ be a class declared in library $L$, and
 let $\{S_1, \ldots, S_k\}$ be the set of all superclasses of $C$,
 where $S_i$ is the superclass of $S_{i-1}$ for $i \in 1 .. k$.
-\commentary{This means that $S_k$ is the built-in class \code{Object}.}
+\commentary{$S_k$ is the built-in class \code{Object}.}
 Let $C$ declare a concrete member $m$, and
 let $m'$ be a concrete member of $S_j, j \in 1 .. k$, that has the same name as $m$,
 such that $m'$ is accessible to $L$.
@@ -3081,47 +3416,21 @@
 }
 
 \rationale{
-Again, a local definition of overriding would be preferable, but fails to account for library privacy.
-}
-
-\LMHash{}%
-Whether an override is legal or not is described elsewhere in this specification (see \ref{instanceMethods}, \ref{getters} and \ref{setters}).
-
-\commentary{
-For example getters may not legally override methods and vice versa.
-Setters never override methods or getters, and vice versa, because their names always differ.
-}
-
-\rationale{
-It is nevertheless convenient to define the override relation between members in this way, so that we can concisely describe the illegal cases.
+Again, a local definition of overriding would be preferable,
+but fails to account for library privacy.
 }
 
 \commentary{
-Note that instance variables do not participate in the override relation, but the getters and setters they induce do.
-Also, getters don't override setters and vice versa.
-Finally, static members never override anything.
+Whether an override is legal or not is specified relative to
+all direct superinterfaces, not just the interface of the superclass,
+and that is described elsewhere
+(\ref{instanceMethods}).
+Static members never override anything,
+but they may participate in some conflicts
+involving declarations in superinterfaces
+(\ref{classMemberConflicts}).
 }
 
-\LMHash{}%
-Let $C$ be a concrete class
-whose interface has an accessible member $m$ named \id{}.
-It is a compile-time error if $C$ does not have
-a concrete member $m'$ named \id{} which is a correct override of $m$,
-unless $C$ has a concrete method named \code{noSuchMethod}
-which is different from the one in the built-in class \code{Object},
-and $C$ does not have a concrete member named \id.
-
-\commentary{
-So it is an error even if $C$ does have a concrete member $m'$ named \id{}
-if $m'$ is an \emph{incorrect} override of $m$,
-also when $C$ has a \code{noSuchMethod} which is not from \code{Object}.
-Note that it is allowed to let inaccessible methods remain unimplemented;
-invocations of such methods will be redirected to \code{noSuchMethod}.
-}
-
-%% TODO(eernst): Why don't we just get rid of this list entirely?
-%% It's 'for convenience', but that's not otherwise a priority in this
-%% document, it is more important that it is correct and consistent.
 \commentary{
 For convenience, here is a summary of the relevant rules,
 using `error' to denote compile-time errors.
@@ -3152,26 +3461,9 @@
   they override each other.
   This may or may not be legal.
 \item \label{typeSigAssignable}
-  %% TODO(eernst): This is commentary, but we may need to adjust it
-  %% to say 'correctly overrides'.
   If two members override each other,
-  it is an error if their type signatures are not assignable to each other
-  (\ref{instanceMethods}, \ref{getters}, \ref{setters})
-  %% TODO(eernst): Revisit relative to the new subtyping.md rules.
-  (and since these are function types, this means the same as
-  "subtypes of each other").
-\item \label{requiredParams}
-  If two members override each other,
-  it is an error if the overriding member has
-  more required parameters than the overridden one (\ref{instanceMethods}).
-\item \label{optionalPositionals}
-  If two members override each other,
-  it is an error if the overriding member has
-  fewer positional parameters than the overridden one (\ref{instanceMethods}).
-\item \label{namedParams}
-  If two members override each other,
-  it is an error if the overriding member does not have
-  all the named parameters that the overridden one has (\ref{instanceMethods}).
+  it is an error unless it is a correct override
+  (\ref{correctMemberOverrides}).
 \item Setters, getters and operators never have
   optional parameters of any kind;
   it's an error (\ref{operators}, \ref{getters}, \ref{setters}).
@@ -3187,38 +3479,31 @@
   it has no body and is not labeled \EXTERNAL{}
   (\ref{abstractInstanceMembers}, \ref{externalFunctions}).
 \item A class is abstract if{}f it is explicitly labeled \ABSTRACT{}.
-\item It is an error if a concrete class has an abstract member
-  (declared or inherited), and there is no \code{noSuchMethod}.
+\item It is an error if a concrete class does not implement some member
+  of its interface, and there is no non-trivial \code{noSuchMethod}
+  (\ref{classes}).
 \item It is an error to call a non-factory constructor of an abstract class
   using an instance creation expression (\ref{instanceCreation}),
   such a constructor may only be invoked from another constructor
   using a super invocation (\ref{superInvocation}).
 \item If a class defines an instance member named $m$,
-  and any of its superinterfaces have a member named $m$,
+  and any of its superinterfaces have a member signature named $m$,
   the interface of the class contains the $m$ from the class itself.
-\item
-  %% TODO(eernst): This needs to be updated when we introduce the
-  %% new override/conflict rules.
-  An interface inherits all members of its superinterfaces
+\item An interface inherits all members of its superinterfaces
   that are not overridden and not members of multiple superinterfaces.
-\item
-  %% TODO(eernst): This must be rewritten when we introduce the new
-  %% override/conflict rules.
-  If multiple superinterfaces of an interface
-  define a member with the same name $m$,
+\item If multiple superinterfaces of an interface
+  define a member with the same name as $m$,
   then at most one member is inherited.
-  %% TODO(eernst): Switch to use 'correctly overrides' terminology.
   That member (if it exists) is the one whose type is a subtype
   of all the others.
-  If there is no such member, then an error occurs
+  If there is no such member, an error occurs
   (\ref{interfaceInheritanceAndOverriding}).
 \item Rule \ref{typeSigAssignable} applies to interfaces as well as classes
   (\ref{interfaceInheritanceAndOverriding}).
 \item It is an error if a concrete class does not have an implementation
   for a method in its interface
-  unless it has a concrete \code{noSuchMethod} method
-  (\ref{superinterfaces})
-  distinct from the one in class \code{Object}.
+  unless it has a non-trivial \code{noSuchMethod}
+  (\ref{theMethodNoSuchMethod}).
 \item The identifier of a named constructor cannot be
   the same as the name of a static member declared in the same class
   (\ref{classMemberConflicts}).
@@ -3228,11 +3513,12 @@
 
 \subsection{Superinterfaces}
 \LMLabel{superinterfaces}
-% what about rules about classes that fail to implement their interfaces?
 
 \LMHash{}%
-A class has a set of direct superinterfaces.
-This set includes the interface of its superclass and the interfaces specified in the \IMPLEMENTS{} clause of the class.
+A class has a set of \Index{direct superinterfaces}.
+This set contains the interface of its superclass
+and the interfaces of the classes specified in
+the \IMPLEMENTS{} clause of the class.
 
 \begin{grammar}
 <interfaces> ::= \IMPLEMENTS{} <typeList>
@@ -3263,38 +3549,11 @@
 \LMHash{}%
 It is a compile-time error if the interface of a class $C$ is a superinterface of itself.
 
-\LMHash{}%
-Let $C$ be a concrete class that does not have a concrete \code{noSuchMethod()} method distinct from the one declared in class \code{Object}.
-%% TODO(eernst): Adjust to use 'correctly overrides' terminology.
-It is a compile-time error if the implicit interface of $C$ has an accessible instance member $m$ of type $F$,
-and $C$ does not declare or inherit a corresponding concrete instance member $m$ of type $F'$ such that $F' <: F$.
-
 \commentary{
 A class does not inherit members from its superinterfaces.
 However, its implicit interface does.
 }
 
-\rationale{
-We choose to raise these compile-time errors only for concrete classes;
-an abstract class might legitimately be designed with the expectation that concrete subclasses will implement part of the interface.
-We also disable these errors if a concrete \code{noSuchMethod()} declaration is present or inherited from any class other than \code{Object},
-unless a concrete member $m$ is declared or inherited.
-The point is that there is an error to disable,
-so the signature of the concrete $m$ is not a correct override of the signature in the class interface.
-Otherwise, when all such errors have been disabled,
-the supported interface is going to be implemented via \code{noSuchMethod()}
-and no actual declarations of the implemented interface's members are needed.
-This allows proxy classes for specific types to be implemented without provoking errors.
-}
-
-\LMHash{}%
-%% TODO(eernst): Switch to use 'correctly overrides' terminology.
-It is a compile-time error if the implicit interface of a class $C$ has an instance member $m$ of type $F$ and $C$ declares or inherits a corresponding instance member $m$ of type $F'$ if $F'$ is not a subtype of $F$.
-
-\rationale{
-However, if a class does explicitly declare a member that conflicts with its superinterface, this always yields an error.
-}
-
 
 \subsection{Class Member Conflicts}
 \LMLabel{classMemberConflicts}
@@ -3325,18 +3584,397 @@
 \LMLabel{interfaces}
 
 \LMHash{}%
-An \Index{interface} defines how one may interact with an object.
-An interface has methods, getters and setters and a set of superinterfaces.
+This section introduces the notion of interfaces.
+We define the notion of member signatures first,
+because that concept is needed in the definition of interfaces.
+
+% We need a separate concept of instance member signatures,
+% such that we can obtain a clean treatment of how to compute
+% the interface of a class and the common interface of a set
+% of superinterfaces, e.g., the superinterfaces of a class or
+% the common interface represented by an `on` clause in a
+% `mixin`. For instance, we do not want to specify each time
+% we check for conflicts that the body doesn't matter, or
+% that the metadata doesn't matter, the interface of a class
+% should simply never contain a body of any member in the
+% first place. Also the clear separation of a syntactic
+% declaration and a member signature provides a well-defined
+% occasion to introduce transformations, e.g., to replace
+% some parameter types by others, which is needed for the
+% specification of a correct override relation.
+
+\LMHash{}%
+A \Index{member signature} $s$
+can be derived from a class instance member declaration $D$.
+It contains the same information as $D$,
+except that $s$ omits the body, if any;
+it contains the return type and parameter types
+even if they are implicit in $D$;
+it omits the names of positional parameters;
+it omits the modifier \FINAL{} from each parameter, if any;
+it omits metadata
+(\ref{metadata});
+and it omits information about whether the member is
+\EXTERNAL{}, \ASYNC{}, \ASYNC*, or \SYNC*.
+It makes no difference whether $D$ is given as explicit syntax
+or it is induced implicitly, e.g., by a variable declaration.
+Finally, if $s$ has formal parameters,
+each of them has the modifier \COVARIANT{}
+(\ref{requiredFormals})
+if and only if that parameter is covariant-by-declaration
+(\ref{covariantParameters}).
+
+\LMHash{}%
+We use a syntax similar to that of an abstract member declaration
+to specify member signatures.
+The difference is that the names of positional parameters are omitted.
+This syntax is only used for the purposes of specification.
+
+\rationale{
+Member signatures are synthetic entities, that is,
+they are not supported as concrete syntax in a Dart program,
+they are computed entities used during static analysis.
+However, it is useful to be able to indicate the
+properties of a member signature in this specification
+via a syntactic representation.
+A member signature makes it explicit
+whether a parameter is covariant-by-declaration,
+but it remains implicit whether it is covariant-by-class
+(\ref{covariantParameters}).
+The reason for this is that the rule for determining whether
+a given override relation is correct
+(\ref{correctMemberOverrides})
+depends on the former and not on the latter.
+}
+
+\LMHash{}%
+Let $m$ be a method signature of the form
+
+\noindent
+\code{$T_0$ \id<\TypeParametersStd>(}
+
+\noindent
+\code{\qquad\qquad\List{\COVARIANT{}?\ T}{1}{n},}
+
+\noindent
+\code{\qquad\qquad[\PairList{\COVARIANT{}?\ T}{= d}{n+1}{n+k}])}.
+
+\noindent
+The \IndexCustom{function type of}{method signature!function type}
+$m$ is then
+
+\noindent
+\FunctionTypePositionalStd{T_0}.
+
+\LMHash{}%
+Let $m$ be a method signature of the form
+
+\noindent
+\code{$T_0$ \id<\TypeParametersStd>(}
+
+\noindent
+\code{\qquad\qquad\List{\COVARIANT{}?\ T}{1}{n},}
+
+\noindent
+\code{\qquad\qquad\{\TripleList{\COVARIANT{}?\ T}{x}{= d}{n+1}{n+k}\})}.
+
+\noindent
+The \NoIndex{function type of} $m$ is then
+
+\noindent
+\FunctionTypeNamedStd{T_0}.
+
+\LMHash{}%
+Let $m$ be a setter signature of the form
+\code{\VOID\ \SET\ \id(\COVARIANT?\ $T$ $p$)}.
+The \NoIndex{function type of} $m$ is then
+\FunctionTypeSimple{\VOID}{$T$}.
+
+\LMHash{}%
+The function type of a member signature remains unchanged if
+some or all default values are omitted.
+
+\commentary{
+We do not specify the function type of a getter signature.
+For such signatures we will instead directly refer to the return type.
+}
+
+\LMHash{}%
+An \Index{interface} is a synthetic entity that defines
+how one may interact with an object.
+An interface has method, getter and setter signatures,
+and a set of superinterfaces,
+which are again interfaces.
+Each interface is the implicit interface of a class,
+in which case we call it a
+\IndexCustom{class interface}{interface!class},
+or a combination of several other interfaces,
+in which case we call it a
+\IndexCustom{combined interface}{interface!combined}.
+
+\LMHash{}%
+Let $C$ be a class.
+The \Index{class interface} $I$ of $C$ is the interface that declares
+a member signature derived from
+each instance member declared by $C$.
+The \Index{direct superinterfaces} of $I$ are the direct superinterfaces of $C$
+(\ref{superinterfaces}).
+
+\commentary{
+We say that the class interface 'declares' these member signatures,
+such that we can say that an interface 'declares' or 'has' a member,
+just like we do for classes.
+Note that a member signature $s$ of the interface of class $C$
+may have a parameter $p$ with modifier \COVARIANT{},
+even though $s$ was derived from a declaration $D$ in $C$
+and the parameter corresponding to $p$ in $D$ does not
+have that modifier.
+This is because $p$ may have ``inherited''
+the property of being covariant-by-declaration
+from one of its superinterfaces
+(\ref{covariantParameters}).
+}
+
+\LMHash{}%
+%% TODO(eernst): 'list of interfaces' --> 'set of interfaces' if we
+%% switch to use a total order on top types for interface specificity.
+The \Index{combined interface} $I$ of a list of interfaces \List{I}{1}{k}
+is the interface that declares the set of member signatures $M$,
+where $M$ is determined as specified below.
+The \Index{direct superinterfaces} of $I$ is the set \List{I}{1}{k}.
+
+\LMHash{}%
+Let $M_0$ be the set of all member signatures declared by \List{I}{1}{k}.
+$M$ is then the smallest set satisfying the following:
+
+\begin{itemize}
+\item For each name \id{} and library $L$ such that $M_0$ contains
+  a member signature named \id{} which is accessible to $L$,
+  let $m$ be the combined member signature named \id{}
+  from \List{I}{1}{k} with respect to $L$.
+  It is a compile-time error
+  if the computation of this combined member signature failed.
+  Otherwise, $M$ contains $m$.
+\end{itemize}
+
+\rationale{
+Interfaces must be able to contain inaccessible member signatures,
+because they may be accessible from the interfaces associated with
+declarations of subtypes.
+}
+
+\commentary{%
+For instance, class $C$ in library $L$ may declare a private member named
+\code{\_foo},
+a class $D$ in a different library $L_2$ may extend $C$,
+and a class $E$ in library $L$ may extend $D$;
+$E$ may then declare a member that overrides \code{\_foo} from $C$,
+and that override relation must be checked based on the interface of $D$.
+So we cannot allow the interface of $D$
+to ``forget'' inaccessible members like \code{\_foo}.
+
+For conflicts the situation is even more demanding:
+Classes $C_1$ and $C_2$ in library $L$ may declare private members
+\code{String \_foo(int i)} and \code{int get \_foo},
+and a subtype $D_{12}$ in a different library $L_2$ may have
+an \IMPLEMENTS{} clause listing both $C_1$ and $C_2$.
+In that case we must report a conflict even though the conflicting
+declarations are not accessible to $L_2$,
+because those member signatures are then noSuchMethod forwarded
+(\ref{theMethodNoSuchMethod}),
+and an invocation of \code{\_foo} on an instance of $D$ in $L$
+must return an `int` according to the first member signature,
+and it must return a function object according to the second one,
+and an invocation of \code{\_foo(42)}
+must return a \code{String} with the first member signature, and it must fail
+(at compile time or, for a dynamic invocation, run time) with the second.
+}
+
+\rationale{%
+It may not be possible to satisfy such constraints simultaneously,
+and it will inevitably be a complex semantics,
+so we have chosen to make it an error.
+It is unfortunate that the addition of a private declaration
+in one library may break existing code in a different library.
+But it should be noted that the conflicts can be detected locally
+in the library where the private declarations exist,
+because they only arise for private members with
+the same name and incompatible signatures.
+Renaming that private member to anything not used in that library
+will eliminate the conflict and will not break any clients.
+}
+
+
+\subsection{Combined Member Signatures}
+\LMLabel{combinedMemberSignatures}
+
+\LMHash{}%
+This section specifies how to compute a member signature which will
+appropriately stand for a prioritized set of several member signatures,
+taken from a given list of interfaces.
+
+\commentary{
+In general, a combined member signature has a type which is
+a subtype of all the types given for that member.
+This is needed in order to ensure that the type of
+a member \id{} of a class $C$ is well-defined,
+even in the case where $C$ inherits
+several different declarations of \id{}
+and does not override \id{}.
+In case of failure, it serves to specify the situations
+where a developer must add a declaration in order to resolve an ambiguity.
+The member signatures are prioritized in the sense that we will select
+a member signature from the interface with the lowest possible index
+in the case where several member signatures are equally suitable
+to be chosen as the combined member signature.
+That is, ``the first interface wins''.
+}
+
+\LMHash{}%
+For the purposes of computing a combined member signature,
+we need a special notion of
+\IndexCustom{equality}{member signature equality}
+of member signatures.
+Two member signatures $m_1$ and $m_2$ are equal
+if{}f they have the same name,
+are accessible to the same set of libraries,
+have the same same return type (for getters),
+or the same function type and the same occurrences of \COVARIANT{}
+(for methods and setters).
+
+\commentary{
+In particular, private methods from different libraries are never equal.
+Top types differ as well.
+For instance,
+\FunctionTypeSimple{\DYNAMIC}{} and \FunctionTypeSimple{\code{Object}}{}
+are not equal, even though they are subtypes of each other.
+We need this distinction because management of top type discrepancies is
+one of the purposes of computing a combined interface.
+}
+
+\LMHash{}%
+Now we define combined member signatures.
+Let \id{} be an identifier, $L$ a library,
+\List{I}{1}{k} a list of interfaces,
+and $M_0$ the set of
+all member signatures from \List{I}{1}{k} named \id{}
+and accessible to $L$.
+The
+\IndexCustom{combined member signature
+  named \id{} from \List{I}{1}{k} with respect to $L$}{%
+  combined member signature}
+is the member signature which is obtained as follows:
+
+\LMHash{}%
+If $M_0$ is empty, computation of the combined member signature failed.
+
+\LMHash{}%
+If $M_0$ contains exactly one member signature $m'$,
+the combined member signature is $m'$.
+
+\LMHash{}%
+Otherwise, $M_0$ contains more than one member signature \List{m}{1}{q}.
+
+\LMHash{}%
+\Case{Failing mixtures}
+If $M_0$ contains at least one getter signature
+and at least one non-getter signature,
+the computation of the combined member signature failed.
+
+\LMHash{}%
+\Case{Getters}
+If $M_0$ contains getter signatures only,
+the computation of the combined member signature proceeds as described below
+for methods and setters,
+except that it uses the return type of the getter signature
+where methods and setters use the function type of the member signature.
+
+
+\LMHash{}%
+\Case{Methods and setters}
+In this case $M_0$ consists of setter signatures only,
+or method signatures only,
+because the name \id{} in the former case always end in \syntax{`='},
+which is never true in the latter case.
+
+\LMHash{}%
+Determine whether there exists a non-empty set $N \subseteq 1 .. q$ such that
+for each $i \in N$,
+the function type of $m_i$ is a subtype of
+the function type of $m_j$ for each $j \in 1 .. q$.
+%
+If no such set exists, the computation of the combined member signature failed.
+\commentary{%
+A useful intuition about this situation is that
+the given member signatures do not agree on
+which type is suitable for the member named \id.
+Otherwise we have a set of member signatures which are ``most specific''
+in the sense that their function types are subtypes of them all.
+}
+
+{ % Scope for N_min, M_min, N_firstMin.
+
+\def\Nall{\ensuremath{N_{\mbox{\scriptsize{}all}}}}
+\def\Mall{\ensuremath{M_{\mbox{\scriptsize{}all}}}}
+\def\MallFirst{\ensuremath{M_{\mbox{\scriptsize{}first}}}}
+
+\LMHash{}%
+Otherwise, when a set $N$ as specified above exists,
+let \Nall{} be the greatest set satisfying the requirement on $N$,
+and let $\Mall{} = \{ m_i\;|\;i \in \Nall\}$.
+\commentary{
+That is, \Mall{} contains all member signatures named \id{}
+with the most specific type.
+Dart subtyping is a partial pre-order,
+which ensures that such a greatest set of least elements exists,
+if any non-empty set of least elements exist.
+We can have several such signatures because member signatures
+can be such that they are not equal,
+and yet their function types are subtypes of each other.
+We need to compute one member signature from \Mall{},
+and we do that by using the ordering of the given interfaces.
+}
+
+\LMHash{}%
+Let $j \in 1 .. k$ be the smallest number such that
+$\MallFirst{} = \Mall{} \cap I_j$ is non-empty.
+Let $m_i$ be the single element that \MallFirst{} contains.
+\commentary{
+This set contains exactly one element because it is non-empty
+and no interface contains more than one member signature named \id.
+In other words, we choose $m_i$ as the member signature from
+the first possible interface
+among the most specific member signatures \Mall.
+}
+}
+
+\LMHash{}
+The combined member signature is then $m'$,
+which is obtained from $m_i$ by adding the modifier \COVARIANT{}
+to each parameter $p$ (if it is not already present)
+when there exists a $j \in 1 .. q$
+such that the parameter corresponding to $p$
+(\ref{covariantParameters})
+has the modifier \COVARIANT{}.
+\commentary{
+In other words,
+each parameter in the combined member signature is marked covariant
+if any of the corresponding parameters are marked covariant,
+not just among the most specific signatures,
+but among \emph{all} signatures named \id{} (which are accessible to $L$)
+in the given list of interfaces.
+}
 
 
 \subsection{Superinterfaces}
 \LMLabel{interfaceSuperinterfaces}
 
 \LMHash{}%
-An interface has a set of direct superinterfaces.
-
-\LMHash{}%
-An interface $J$ is a superinterface of an interface $I$ if{}f either $J$ is a direct superinterface of $I$ or $J$ is a superinterface of a direct superinterface of $I$.
+An interface has a set of direct superinterfaces
+(\ref{interfaces}).
+An interface $J$ is a \Index{superinterface} of an interface $I$
+if{}f either $J$ is a direct superinterface of $I$
+or $J$ is a superinterface of a direct superinterface of $I$.
 
 
 \subsubsection{Inheritance and Overriding}
@@ -3344,58 +3982,111 @@
 
 \LMHash{}%
 Let $J$ be an interface and $K$ be a library.
-We define $inherited(J, K)$ to be the set of members $m$ such that all of the following hold:
+We define $\inherited{J, K}$ to be the set of member signatures $m$
+such that all of the following hold:
 \begin{itemize}
 \item $m$ is accessible to $K$ and
 \item $A$ is a direct superinterface of $J$ and either
   \begin{itemize}
-  \item $A$ declares a member $m$ or
-  \item $m$ is a member of $inherited(A, K)$.
+  \item $A$ declares a member signature $m$ or
+  \item $m$ is a member of $\inherited{A, K}$.
   \end{itemize}
 \item $m$ is not overridden by $J$.
 \end{itemize}
 
 \LMHash{}%
-Furthermore, we define $overrides(J, K)$ to be the set of members $m'$ such that all of the following hold:
+Furthermore, we define $\overrides{J, K}$ to be
+the set of member signatures $m'$
+such that all of the following hold:
 \begin{itemize}
-\item $J$ is the implicit interface of a class $C$.
-\item $C$ declares a member $m$.
+\item $J$ is the interface of a class $C$.
+\item $C$ declares a member signature $m$.
 \item $m'$ has the same name as $m$.
 \item $m'$ is accessible to $K$.
 \item $A$ is a direct superinterface of $J$ and either
   \begin{itemize}
-  \item $A$ declares a member $m'$ or
+  \item $A$ declares a member signature $m'$ or
   \item $m'$ is a member of $inherited(A, K)$.
   \end{itemize}
 \end{itemize}
 
 \LMHash{}%
-Let $I$ be the implicit interface of a class $C$ declared in library $L$.
-$I$ \Index{inherits} all members of $inherited(I, L)$ and $I$ \Index{overrides} $m'$ if $m' \in overrides(I, L)$.
+Let $I$ be the interface of a class $C$ declared in library $L$.
+$I$ \Index{inherits} all members of $\inherited{I, L}$
+and $I$ \Index{overrides} $m'$ if $m' \in \overrides{I, L}$.
 
 \LMHash{}%
-All the compile-time errors pertaining to the overriding of instance members given in section \ref{classes} above hold for overriding between interfaces as well.
+All the compile-time errors pertaining to the overriding of instance members
+given in section~\ref{classes} hold for overriding between interfaces as well.
 
 \LMHash{}%
-It is a compile-time error if $m$ is a method and $m'$ is a getter, or if $m$ is a getter and $m'$ is a method.
+If the above rule would cause multiple member signatures
+with the same name \id{} to be inherited then
+exactly one member is inherited, namely
+the combined member signature named \id{},
+from the direct superinterfaces
+%% TODO(eernst): This is only well-defined when $J$ is a class interface.
+in the textual order that they are declared,
+with respect to $L$
+(\ref{combinedMemberSignatures}).
 
-%Let $I = S_0$ be the implicit interface of a class $C$ declared in library $L$, and let $\{S_1, \ldots, S_k\}$ be the set of all superinterfaces of $I$.
 
-%Let $I$ be the implicit interface of a class $C$.  $I$ inherits any instance members of its superinterfaces that are not overridden by members declared in $C$.
-
-% tighten definition? do we need chain as for classes?  Definition for interface override?
+\subsubsection{Correct Member Overrides}
+\LMLabel{correctMemberOverrides}
 
 \LMHash{}%
-However, if the above rules would cause multiple members $m_1, \ldots, m_k$ with the same name $n$ to be inherited (because identically named members existed in several superinterfaces) then at most one member is inherited.
+Let $m$ and $m'$ be member signatures with the same name \id.
+Then $m$ is a \Index{correct override} of $m'$
+if{}f the following criteria are all satisfied:
 
-\LMHash{}%
-If some but not all of the $m_i, 1 \le i \le k$ are getters, a compile-time error occurs.
+\begin{itemize}
+\item
+  $m$ and $m'$ are both methods, both getters, or both setters.
+  % We cannot have a setter and a method, say, because they cannot have
+  % the same name. However, we must _allow_ $m$ and $m'$ to be two setters.
+\item
+  If $m$ and $m'$ are both methods or both setters:
+  Let $F$ be the function type of $m$
+  except that the parameter type is the built-in class \code{Object}
+  for each parameter of $m$ which has the modifier \COVARIANT{}.
+  Let $F'$ be the function type of $m'$.
+  $F$ must then be a subtype of $F'$.
 
-\LMHash{}%
-%% TODO(eernst): Adjust to use 'correctly overrides' terminology.
-Otherwise, if the static types $T_1, \ldots, T_k$ of the members $m_1, \ldots, m_k$ are not identical then there must be an $x \in 1 .. k$ such that $T_x <: T_i$ for all $i \in 1 .. k$,
-or a compile-time error occurs.
-The member that is inherited  is $m_x$, if it exists.
+  \commentary{%
+  The subtype requirement ensures that argument list shapes
+  that are admissible for an invocation of a method with signature $m'$
+  are also admissible for an invocation of a method with signature $m$.
+  For instance, $m'$ may accept 2 or 3 positional arguments,
+  and $m$ may accept 1, 2, 3, or 4 positional arguments, but not vice versa.
+  This is a built-in property of the function type subtype rules.
+  %
+  Note that a member signature differs from
+  an underlying syntactic declaration $D$ in a class $C$.
+  In particular,
+  a parameter in a member signature has the modifier \COVARIANT{}
+  if and only if the parameter is covariant-by-declaration
+  (\ref{covariantParameters}),
+  and that may be the case due to declarations in a supertype of $C$,
+  so that modifier need not be present in $D$.
+  %
+  There is an additional potential compile-time error associated with
+  a parameter which is covariant-by-declaration
+  (\ref{instanceMethods}).
+  But we cannot cover that here as a property of member overrides,
+  because it is concerned with declarations in all superinterfaces,
+  indirect as well as direct.
+  }
+\item
+  If $m$ and $m'$ are both methods,
+  $p$ is an optional parameter of $m$,
+  $p'$ is the parameter of $m'$ corresponding to $p$,
+  $p$ has default value $d$ and $p'$ has default value $d'$,
+  then $d$ and $d'$ must be identical,
+  or a compile-time warning occurs.
+\item
+  If $m$ and $m'$ are both getters:
+  The return type of $m$ must be a subtype of the return type of $m'$.
+\end{itemize}
 
 
 \section{Mixins}
@@ -3462,9 +4153,9 @@
 
 For each generative constructor of the form \code{$S_q$($T_{1}$ $a_{1}$, $\ldots$, $T_{k}$ $a_{k}$)} of $S$ that is accessible to $L_C$, $C$ has an implicitly declared constructor of the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 $C_q$($T_{1}$ $a_{1}$, \ldots, $T_{k}$ $a_{k}$): $\SUPER_q$($a_{1}$, $\ldots$, $a_{k}$);
-\end{dartCode}
+\end{normativeDartCode}
 
 \noindent
 where $C_q$ is obtained from $S_q$ by replacing occurrences of $S_N$,
@@ -3476,10 +4167,10 @@
 \LMHash{}%
 For each generative constructor of the form \code{$S_q$($T_{1}$ $a_{1}$, \ldots , $T_{k}$ $a_{k}$, [$T_{k+1}$ $a_{k+1}$ = $d_1$, \ldots , $T_{k+p}$ $a_{k+p}$ = $d_p$])} of $S$ that is accessible to $L_C$, $C$ has an implicitly declared constructor of the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 $C_q$($T_{1}$ $a_{1}$, \ldots , $T_{k}$ $a_{k}$, [$T_{k+1}$ $a_{k+1}$ = $d'_{1}$, \ldots , $T_{k+p}$ $a_{k+p}$ = $d'_p$])
     : $\SUPER_q$($a_{1}$, \ldots , $a_{k}$, $a_{k+1}$, \ldots, $a_p$);
-\end{dartCode}
+\end{normativeDartCode}
 
 \noindent
 where $C_q$ is obtained from $S_q$ by replacing occurrences of $S_N$,
@@ -3494,10 +4185,10 @@
 \LMHash{}%
 For each generative constructor of the form \code{$S_q$($T_{1}$ $a_{1}$, \ldots , $T_{k}$ $a_{k}$, \{$T_{k+1}$ $a_{k+1}$ = $d_1$, \ldots , $T_{k+n}$ $a_{k+n}$ = $d_n$\})} of $S$ that is accessible to $L_C$, $C$ has an implicitly declared constructor of the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 $C_q$($T_{1}$ $a_{1}$, \ldots , $T_{k}$ $a_{k}$, \{$T_{k+1}$ $a_{k+1}$ = $d'_1$, \ldots , $T_{k+n}$ $a_{k+n}$ = $d'_n$\})
     : $\SUPER_q$($a_{1}$, \ldots , $a_{k}$, $a_{k+1}$: $a_{k+1}$, \ldots, $a_p$: $a_p$);
-\end{dartCode}
+\end{normativeDartCode}
 
 \noindent
 where $C_q$ is obtained from $S_q$ by replacing occurrences of $S_N$
@@ -3563,17 +4254,17 @@
 
 to \code{$S$<$V_1, \ldots, V_{k_S}$>} for the name $C$ is equivalent to
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \ABSTRACT{} \CLASS{} $C<T_1, \ldots, T_{k_{M_1}}, U_1, \ldots, U_{k_{M_2}}, V_1, \ldots, V_{k_S}> = $
       $Id_2<U_1, \ldots, U_{k_{M_2}}, V_1 \ldots V_{k_S}>$ \WITH{} $M_1 <T_1, \ldots, T_{k_{M_1}}>$;
-\end{dartCode}
+\end{normativeDartCode}
 
 where $Id_2$ denotes
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \ABSTRACT{} \CLASS{} $Id_2<U_1, \ldots, U_{k_{M_2}}, V_1, \ldots, V_{k_S}> =$
                          $S<V_1, \ldots, V_{k_S}>$ \WITH{} $M_2<U_1, \ldots, U_{k_{M_2}}>$;
-\end{dartCode}
+\end{normativeDartCode}
 
 and $Id_2$ is a unique identifier that does not exist anywhere in the program.
 
@@ -3610,7 +4301,7 @@
 \code{$m$ \ENUM{} $E$ \{$m_0\,\,\id_0, \ldots,\ m_{n-1}\,\,\id_{n-1}$\}}
 has the same effect as a class declaration
 
-\begin{dartCode}
+\begin{normativeDartCode}
 $m$ \CLASS{} $E$ \{
   \FINAL{} int index;
   \CONST{} $E$(\THIS{}.index);
@@ -3620,7 +4311,7 @@
   \STATIC{} \CONST{} List<$E$> values = const <$E$>[\id$_0, \ldots, $ \id$_{n-1}$];
   String toString() => \{ 0: `$E$.\id$_0$', $\ldots$, n-1: `$E$.\id$_{n-1}$'\}[index]
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 \commentary{
 It is also a compile-time error to subclass, mix-in or implement an enum or to explicitly instantiate an enum.
@@ -5419,64 +6110,33 @@
 \LMLabel{functionExpressions}
 
 \LMHash{}%
-%% TODO(eernst): A function literal is a syntactic construct, and we may use
-%% function closurization to obtain a corresponding function object.
 A \IndexCustom{function literal}{literal!function}
-is an object that encapsulates an executable unit of code.
+is an anonymous declaration and an expression
+that encapsulates an executable unit of code.
 
 \begin{grammar}
 <functionExpression> ::= <formalParameterPart> <functionBody>
 \end{grammar}
 
-%% TODO[inference]: The static and dynamic type of a function literal
-%% interacts with inference: If a type-from-context $T$ exists and the
-%% function literal can be given a type which is a subtype of $T$, we may
-%% end up typing both the function as a whole and the body of the function
-%% very differently than we would in a situation where no type-from-context
-%% exists. So the rules below must be changed to be the default case (where
-%% no type-from-context is available, or it is `Object` or some other
-%% non-constraing type, and other cases where the type-from-context is
-%% actually used to select the function literal signature must be described
-%% specifically for each relevant type of situation.
+\LMHash{}%
+The grammar does not allow a function literal to declare a return type,
+but it is possible for a function literal to have a
+\IndexCustom{declared return type}{literal!function!declared return type},
+because it can be obtained by means of type inference.
+Such a return type is included
+when we refer to the declared return type of a function.
+
+\commentary{%
+Type inference will be specified in a future version of this document.
+Currently we consider type inference to be a phase that has completed,
+and this document specifies the meaning of Dart programs
+where inferred types have already been added.
+}
 
 \LMHash{}%
-The class of a function literal implements the built-in class \FUNCTION{}.
-
-\LMHash{}%
-The static type of a function literal of the form
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
-
-\code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$]) => $e$}
-
-\noindent
-is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow T_0$},
-
-\noindent
-%% TODO[inference]: The static type of the function literal may come from context.
-where $T_0$ is the static type of $e$.
-
-\LMHash{}%
-The static type of a function literal of the form
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
-
-\code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$]) \ASYNC{} => $e$}
-
-\noindent
-is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
-
-\code{($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Future<\flatten{T_0}>},
-
-\noindent
-where $T_0$ is the static type of $e$.
-
-\LMHash{}%
-In the previous two paragraphs, the type argument lists are omitted in the case where $m = 0$, and \flatten{T} is defined as follows:
+We define the auxiliary function
+\IndexCustom{\flatten{T}}{flatten(t)@\emph{flatten}$(T)$},
+which is used below and in other sections, as follows:
 
 \begin{itemize}
 \item If $T$ is \code{FutureOr<$S$>} for some $S$ then $\flatten{T} = S$.
@@ -5484,10 +6144,10 @@
 \item Otherwise if
 \code{$T <:$ Future}
 then let $S$ be a type such that
-\code{$T <<$ Future<$S$>}
+\code{$T <:$ Future<$S$>}
 and for all $R$, if
-\code{$T <<$ Future<$R$>}
-then $S << R$.
+\code{$T <:$ Future<$R$>}
+then $S <: R$.
 
 \rationale{
 This ensures that
@@ -5505,139 +6165,210 @@
 \end{itemize}
 
 \LMHash{}%
+\Case{Positional, arrow}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
+\code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$]) => $e$}
+
+\noindent
+is
+\FunctionTypePositionalStd{T_0},
+
+\noindent
+%% TODO[inference]: The static type of the function literal may come from context.
+where $T_0$ is the static type of $e$.
+
+\LMHash{}%
+\Case{Positional, arrow, future}
+The static type of a function literal of the form
+
+\noindent
+\code{<\TypeParametersStd>}
+
+\noindent
+\code{($T_1\ a_1, \ldots,\ T_n\ a_n,$ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$]) \ASYNC{} => $e$}
+
+\noindent
+is
+\FunctionTypePositionalStdCr{\code{Future<\flatten{T_0}>}},
+
+\noindent
+where $T_0$ is the static type of $e$.
+
+\LMHash{}%
+\Case{Named, arrow}
+The static type of a function literal of the form
+
+\noindent
+\code{<\TypeParametersStd>}
+
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ \{$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$\}) => $e$}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow T_0$},
+\FunctionTypeNamedStd{T_0},
 
 \noindent
 where $T_0$ is the static type of $e$.
 
 \LMHash{}%
+\Case{Named, arrow, future}
 The static type of a function literal of the form
 
-\code{<$X_1 B_1, \ldots,\ X_m B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ \{$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$\}) \ASYNC{} => $e$}
 
 \noindent
 is
-
-\code{<$X_1 B_1, \ldots,\ X_m B_m$>}
-
-\code{($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Future<\flatten{T_0}>},
+\FunctionTypeNamedStdCr{\code{Future<\flatten{T_0}>}},
 
 \noindent
 where $T_0$ is the static type of $e$.
 
 \LMHash{}%
+\Case{Positional, block}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParameters{X}{B}{S}>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k}= d_k$]) \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ \DYNAMIC{}}.
+\FunctionTypePositionalStdCr{\DYNAMIC}
 
 \LMHash{}%
+\Case{Positional, block, future}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$]) \ASYNC{} \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Future}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypePositionalStdCr{\code{Future}}.
 
 \LMHash{}%
+\Case{Positional, block, stream}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k}= d_k$]) \ASYNC*{} \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Stream}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypePositionalStdCr{\code{Stream}}.
 
 \LMHash{}%
+\Case{Positional, block, iterable}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k}= d_k$]) \SYNC*{} \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Iterable}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypePositionalStdCr{\code{Iterable}}.
 
 \LMHash{}%
+\Case{Named, block}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ [$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k}= d_k$]) \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ \DYNAMIC{}}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypePositionalStdCr{\DYNAMIC}.
 
 \LMHash{}%
+\Case{Named, block, future}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ \{$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$\}) \ASYNC{} \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Future}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypeNamedStdCr{\code{Future}}.
 
 \LMHash{}%
+\Case{Named, block, stream}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ \{$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$\}) \ASYNC*{} \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Stream}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypeNamedStdCr{\code{Stream}}.
 
 \LMHash{}%
+\Case{Named, block, iterable}
 The static type of a function literal of the form
 
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
+\noindent
+\code{<\TypeParametersStd>}
 
+\noindent
 \code{($T_1\ a_1, \ldots,\ T_n\ a_n, $ \{$T_{n+1}\ x_{n+1} = d_1, \ldots,\ T_{n+k}\ x_{n+k} = d_k$\}) \SYNC*{} \{ $s$ \}}
 
 \noindent
 is
-
-\code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Iterable}.
+%% TODO(eernst): Adjust to take type inference into account.
+\FunctionTypeNamedStdCr{\code{Iterable}}.
 
 \LMHash{}%
 In all of the above cases,
 the type argument lists are omitted when $m=0$,
-and whenever $T_i, 1 \le i \le n+k$, is not specified,
+and whenever $T_i$ is not specified, $i \in 1 .. n+k$,
 it is considered to have been specified as \DYNAMIC{}.
 
+\LMHash{}%
+Evaluation of a function literal yields a function object $o$.
+
+\commentary{
+The run-time type of $o$ is specified based on
+the static type $T$ of the function literal
+and the binding of type variables occurring in $T$
+at the occasion where the evaluation occurred
+(\ref{typeOfAFunction}).
+}
+
 
 \subsection{This}
 \LMLabel{this}
@@ -6403,7 +7134,7 @@
 the word `function' is more low-level than `function object',
 but `function' still denotes a semantic entity
 which is associated with a function declaration,
-even though there may not be corresponding entity in the heap at run time.
+even though there may not be a corresponding entity in the heap at run time.
 }
 
 \LMHash{}%
@@ -6425,13 +7156,16 @@
 and let $p_{h+1}, \ldots, p_{h+k}$ be the optional parameters of $F$.
 Let $S_i$ be the static type of the formal parameters $p_i, i \in 1 .. h+k$,
 and for each $q$ let $S_q$ be the type of the parameter named $q$,
-where each parameter type is obtained by replacing $X_j$ by $A_j, j \in 1 .. s$, in the given parameter type annotation.
+where each parameter type is obtained by replacing $X_j$ by $A_j, j \in 1 .. s$,
+in the given parameter type annotation.
 Finally, let $T_i$ be the static type of $a_i$.
 
 \commentary{
-We have an actual argument list consisting of $r$ type arguments, $m$ positional arguments, and $l$ named arguments.
-We have a function with $s$ type parameters, $h$ required parameters, and $k$ optional parameters.
-Figure~\ref{fig:argumentsAndParameters} shows how this situation may arise.
+We have an actual argument list consisting of $r$ type arguments,
+$m$ positional arguments, and $l$ named arguments.
+We have a function with $s$ type parameters,
+$h$ required parameters, and $k$ optional parameters.
+Figure~\ref{fig:argumentsAndParameters} shows how this situation arises.
 }
 
 % View on declaration:
@@ -6518,6 +7252,32 @@
 It is a compile-time error if $T_j$ may not be assigned to $S_j, j \in 1 .. m$.
 It is a compile-time error if $T_{m+j}$ may not be assigned to $S_{q_j}, j \in 1 .. l$.
 
+\commentary{
+Consider the case where the function invocation in focus here is
+an instance method invocation.
+In that case, for each actual argument,
+the corresponding parameter may be covariant.
+However, the above assignability requirements apply equally
+both when the parameter is covariant and when it is not.
+}
+
+\rationale{
+Parameter covariance in an instance method invocation can be introduced by
+a subtype of the statically known receiver type,
+which means that any attempt to flag a given actual argument as dangerous
+due to the dynamic type check that it will be subjected to
+will be incomplete:
+some actual arguments can be subjected to such a dynamic type check
+even though this is not known statically at the call site.
+This is not surprising for a mechanism like parameter covariance which is
+designed for the very purpose of allowing developers to explicitly request
+that this specific kind of compile-time safety is violated.
+The point is that this mechanism postpones the enforcement of
+the underlying invariant to run time,
+and in return allows some useful program designs
+that would otherwise be rejected at compile-time.
+}
+
 \LMHash{}%
 For the dynamic semantics,
 let $f$ be a function with $s$ type parameters and $h$ required parameters;
@@ -6764,14 +7524,26 @@
 \LMHash{}%
 Function closurization applied to a function declaration $f$
 amounts to the creation of a function object $o$
-which is an instance of a class whose interface is a subtype of the actual type
+which is an instance of a class $C$ whose interface is
+a subtype of the actual type $F$
 (\ref{actualTypeOfADeclaration})
 corresponding to the signature in the function declaration $f$,
 using the current bindings of type variables, if any.
+There does not exist a function type $F'$ which is a proper subtype of $F$
+such that $C$ is a subtype of $F'$.
 If $f$ denotes a static method or top-level function,
-the corresponding class does not override the \code{==} operator
+class $C$ does not override the \code{==} operator
 inherited from the \code{Object} class.
-%
+
+\commentary{
+In other words, $C$ has the freedom to be a proper subtype of
+the function type that we can read off of the declaration of $f$
+because it may need to be a specific internal platform defined class,
+but $C$ does not have the freedom to be a subtype of
+a different and more special function type, and it cannot be \code{Null}.
+}
+
+\LMHash{}%
 An invocation of $o$ with a given argument list will bind actuals to formals
 in the same way as an invocation of $f$
 (\ref{bindingActualsToFormals}),
@@ -6949,13 +7721,10 @@
 
 \LMHash{}%
 Let $T$ be the static type of $e$.
-It is a compile-time error if $T$ does not have an accessible (\ref{privacy}) instance member named $m$, unless either:
+It is a compile-time error if $T$ does not have an accessible
+(\ref{privacy})
+instance member named $m$, unless either:
 \begin{itemize}
-\item
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-$T$ is \code{Type}, $e$ is a constant type literal,
-and the class corresponding to $e$ has a static getter named $m$.
-Or
 \item $T$ is \DYNAMIC{}.
 Or
 \item $T$ is \FUNCTION{} and $m$ is \CALL.
@@ -7006,30 +7775,24 @@
 
 \LMHash{}%
 First, the expression $e$ is evaluated to a value $o$.
-Let $f$ be the result of looking up (\ref{lookup}) method $m$ in $o$ with respect to the current library $L$.
-
-\LMHash{}%
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-If method lookup succeeded,
-but $o$ is an instance of \code{Type} and $e$ is not a constant type literal,
-then if $m$ is a method that forwards (\ref{functionDeclarations}) to a static method,
-method lookup is considered to have failed.
+Let $f$ be the result of looking up
+(\ref{lookup})
+method $m$ in $o$ with respect to the current library $L$.
 
 \LMHash{}%
 If the method lookup succeeded,
-the binding of actual arguments to formal parameters is performed as specified in Section~\ref{bindingActualsToFormals}.
-The body of $f$ is then executed with respect to the bindings that resulted from the evaluation of the argument list,
+the binding of actual arguments to formal parameters is performed
+as specified in Section~\ref{bindingActualsToFormals}.
+The body of $f$ is then executed with respect to the bindings
+that resulted from the evaluation of the argument list,
 and with \THIS{} bound to $o$.
 The value of $i$ is the value returned by the execution of $f$'s body.
 
 \LMHash{}%
 If the method lookup failed,
-then let $g$ be the result of looking up getter (\ref{lookup}) $m$ in $o$ with respect to $L$.
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-If getter lookup succeeded,
-but $o$ is an instance of \code{Type} and $e$ is not a constant type literal,
-then if $g$ is a getter that forwards to a static getter,
-getter lookup is considered to have failed.
+then let $g$ be the result of looking up getter
+(\ref{lookup})
+$m$ in $o$ with respect to $L$.
 
 \LMHash{}%
 If the getter lookup succeeded then invoke the getter $o.m$
@@ -7217,77 +7980,152 @@
 A property extraction can be either:
 \begin{enumerate}
 \item An instance method closurization,
-which converts a method into a function object
-(\ref{ordinaryMemberClosurization}).
-Or
-\item A getter invocation, which returns the result of invoking of a getter method
-(\ref{getterAccessAndMethodExtraction}).
+  which converts a method into a function object
+  (\ref{ordinaryMemberClosurization}).
+  Or
+\item A getter invocation, which returns
+  the result of invoking of a getter method
+  (\ref{getterAccessAndMethodExtraction}).
 \end{enumerate}
 
 \commentary{
-Function objects derived from members via closurization are colloquially known as tear-offs.
+Function objects derived from members via closurization
+are colloquially known as tear-offs.
 }
 
 Property extraction can be either conditional or unconditional.
 
 \LMHash{}%
-Evaluation of a \IndexCustom{conditional property extraction expression}{%
+\Case{Conditional}
+Consider a \IndexCustom{conditional property extraction expression}{%
   property extraction!conditional}
-$e$ of the form \code{$e_1$?.\id} proceeds as follows:
+$i$ of the form \code{$e$?.\id}.
 
 \LMHash{}%
-If $e_1$ is a type literal, $e$ is equivalent to \code{$e_1$.$m$}.
+If $e$ is a type literal, $i$ is equivalent to \code{$e$.\id}.
 
 \LMHash{}%
-Otherwise evaluate $e_1$ to an object $o$.
-If $o$ is the null object, $e$ evaluates to the null object (\ref{null}).
+Otherwise, the static type of $i$ is the same as
+the static type of \code{$e$.\id}.
+Let $T$ be the static type of $e$,
+and let $y$ be a fresh variable of type $T$.
+Except for errors inside $e$ and references to the name $y$,
+exactly the same compile-time errors that would be caused by \code{$y$.\id}
+are also generated in the case of \code{$e$?.\id}.
+
+\LMHash{}%
+Evaluation of a conditional property extraction expression $i$
+of the form \code{$e$?.\id} proceeds as follows:
+
+\LMHash{}%
+If $e$ is a type literal,
+evaluation of $i$ amounts to evaluation of \code{$e$.\id}.
+
+\LMHash{}%
+Otherwise evaluate $e$ to an object $o$.
+If $o$ is the null object, $i$ evaluates to the null object (\ref{null}).
 Otherwise let $x$ be a fresh variable bound to $o$
 and evaluate \code{$x$.\id} to a value $r$.
-Then $e$ evaluates to $r$.
-
-The static type of $e$ is the same as the static type of \code{$e_1$.\id}.
-Let $T$ be the static type of $e_1$ and let $y$ be a fresh variable of type $T$.
-Exactly the same compile-time errors that would be caused by \code{$y$.\id} are also generated in the case of \code{$e_1$?.\id}.
+Then $i$ evaluates to $r$.
 
 \LMHash{}%
-\IndexCustom{Unconditional property extraction}{%
+\Case{Unconditional}
+Let \id{} be an identifier;
+an \IndexCustom{unconditional property extraction}{%
   property extraction!unconditional}
-has one of two syntactic forms:
-$e.m$ (\ref{getterAccessAndMethodExtraction}) or
-$\SUPER.m$ (\ref{superGetterAccessAndMethodClosurization}),
-where $e$ is an expression and $m$ is an identifier.
+may be of the form \code{$e$.\id} where $e$ is an expression
+(\ref{getterAccessAndMethodExtraction}),
+or of the form \code{\SUPER.\id}
+(\ref{superGetterAccessAndMethodClosurization}).
 
 
 \subsubsection{Getter Access and Method Extraction}
 \LMLabel{getterAccessAndMethodExtraction}
 
 \LMHash{}%
-Evaluation of a property extraction $i$ of the form $e.m$ proceeds as follows:
+Consider an unconditional property extraction $i$
+(\ref{propertyExtraction})
+of the form \code{$e$.\id}.
+It is a compile-time error if \id{} is a member of class \code{Object}
+and $e$ is either a prefix object (\ref{imports})
+or a type literal.
+
+\commentary{
+It may seem obvious that it is an error to use prefix object,
+but more surprising that it also applies to a type literal.
+In particular, we cannot use \code{int.toString}
+to obtain a function object for the \code{toString} method of the
+\code{Type} object for \code{int}.
+But we can use \code{(int).toString}:
+$e$ is then not a type literal, but a parenthesized expression.
+}
+
+\rationale{
+This is a pragmatic trade-off.
+The ability to tear off instance methods on instances of \code{Type}
+was considered less useful,
+and it was considered more useful to insist on the simple rule that
+a method tear-off on a type literal is \emph{always} a tear-off
+of a static method on the denoted class.
+}
+
+\LMHash{}%
+Let $T$ be the static type of $e$.
+It is a compile-time error if $T$ does not have a method or getter named \id{}
+unless $T$ is \DYNAMIC{},
+or $T$ is \FUNCTION{} and \id{} is \code{call}.
+The static type of $i$ is:
+
+\begin{itemize}
+\item The declared return type of \code{$T$.\id},
+  if $T$ has an accessible instance getter named \id{}.
+\item The function type of the method signature \code{$T$.\id},
+  if $T$ has an accessible instance method named \id{}.
+\item The type \DYNAMIC{} otherwise.
+  \commentary{This only occurs when $T$ is \DYNAMIC{} or \FUNCTION.}
+\end{itemize}
+
+\commentary{
+Note that the type of a method tear-off ignores
+whether any given parameter is covariant.
+However, the dynamic type of a function object
+thus obtained does take parameter covariance into account.
+}
+
+\LMHash{}%
+Evaluation of a property extraction $i$ of the form \code{$e$.\id} proceeds as follows:
 
 \LMHash{}%
 First, the expression $e$ is evaluated to an object $o$.
-Let $f$ be the result of looking up (\ref{lookup}) method (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$.
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards (\ref{functionDeclarations}) to a static method, method lookup fails.
-If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).
+Let $f$ be the result of looking up (\ref{lookup}) method
+(\ref{instanceMethods})
+\id{} in $o$ with respect to the current library $L$.
+If method lookup succeeds then $i$ evaluates to
+the closurization of method $f$ on object $o$
+(\ref{ordinaryMemberClosurization}).
 
 \commentary{
 Note that $f$ is never an abstract method, because method lookup skips abstract methods.
-Hence, if $m$ refers to an abstract method, we will continue to the next step.
-However, since methods and getters never override each other, getter lookup will necessarily fail as well, and \code{noSuchMethod()} will ultimately be invoked.
+If the method lookup failed, e.g.,
+because there is an abstract declaration of \id, but no concrete declaration,
+we will continue to the next step.
+However, since methods and getters never override each other,
+getter lookup will necessarily fail as well,
+and \code{noSuchMethod()} will ultimately be invoked.
 The regrettable implication is that the error will refer to a missing getter rather than an attempt to closurize an abstract method.
 }
 
 \LMHash{}%
 Otherwise, $i$ is a getter invocation.
-Let $f$ be the result of looking up (\ref{lookup}) getter (\ref{getters}) $m$ in $o$ with respect to $L$.
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a getter that forwards to a static getter, getter lookup fails.
+Let $f$ be the result of looking up (\ref{lookup}) getter
+(\ref{getters})
+\id{} in $o$ with respect to $L$.
 Otherwise, the body of $f$ is executed with \THIS{} bound to $o$.
 The value of $i$ is the result returned by the call to the getter function.
 
 \LMHash{}%
-If the getter lookup has failed, then a new instance $im$ of the predefined class \code{Invocation} is created, such that:
+If the getter lookup has failed,
+then a new instance $im$ of the predefined class \code{Invocation} is created, such that:
 \begin{itemize}
 \item \code{$im$.isGetter} evaluates to \code{\TRUE{}}.
 \item \code{$im$.memberName} evaluates to the symbol \code{m}.
@@ -7310,82 +8148,75 @@
 when the static type of $e$ is \DYNAMIC{}.
 }
 
-\LMHash{}%
-It is a compile-time error if $m$ is a member of class \code{Object} and $e$ is either a prefix object (\ref{imports}) or a constant type literal.
-
-\commentary{
-This precludes \code{int.toString} but not \code{(int).toString} because in the latter case, $e$ is a parenthesized expression.
-}
-
-\LMHash{}%
-Let $T$ be the static type of $e$.
-It is a compile-time error if $T$ does not have a method or getter named $m$,
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-unless $T$ is \code{Type},
-$e$ is a constant type literal,
-and the class corresponding to $e$ has a static method or getter named $m$.
-
-\LMHash{}%
-The static type of $i$ is:
-\begin{itemize}
-\item The declared return type of \code{$T$.$m$}, if $T$ has an accessible instance getter named $m$.
-\item
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-The declared return type of $m$, if $T$ is \code{Type},
-$e$ is a constant type literal
-and the class corresponding to $e$ declares an accessible static getter named $m$.
-\item The static type of function \code{$T$.$m$} if $T$ has an accessible instance method named $m$.
-\item
-%% TODO(eernst): This is metaclass stuff, should be deleted.
-The static type of function $m$, if $T$ is \code{Type},
-$e$ is a constant type literal
-and the class corresponding to $e$ declares an accessible static method named $m$.
-\item The type \DYNAMIC{} otherwise.
-\end{itemize}
-
 
 \subsubsection{Super Getter Access and Method Closurization}
 \LMLabel{superGetterAccessAndMethodClosurization}
 
 \LMHash{}%
+Consider a property extraction $i$ of the form \code{\SUPER.\id}.
+
+\LMHash{}%
+Let $S$ be the superclass of the immediately enclosing class.
+It is a compile-time error if $S$ does not have
+an accessible instance method or getter named \id.
+The static type of $i$ is:
+
+\begin{itemize}
+\item The declared return type of \code{$S$.\id},
+  if $S$ has an accessible instance getter named \id.
+\item The function type of the method signature \code{$S$.\id},
+  if $S$ has an accessible instance method named \id.
+\item The type \DYNAMIC{} otherwise.
+  \commentary{This only occurs when $T$ is \DYNAMIC{} or \FUNCTION.}
+\end{itemize}
+
+\commentary{
+Note that the type of a method tear-off ignores
+whether any given parameter is covariant.
+However, the dynamic type of a function object
+thus obtained does take parameter covariance into account.
+}
+
+\LMHash{}%
 Evaluation of a property extraction $i$ of the form $\SUPER.m$ proceeds as follows:
 
 \LMHash{}%
-Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.
-Let $S_{dynamic}$ be the superclass of $C$.
-Let $f$ be the result of looking up method $m$ in $S_{dynamic}$ with respect to the current library $L$.
-If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).
+Let $g$ be the method implementation currently executing,
+and let $C$ be the class in which $g$ is declared.
+Let $S$ be the superclass of $C$.
+Let $f$ be the result of looking up method \id{} in $S$
+with respect to the current library $L$.
+If method lookup succeeds then $i$ evaluates to
+the closurization of method $f$
+with respect to superclass $S$
+(\ref{superClosurization}).
 
 \LMHash{}%
 Otherwise, $i$ is a getter invocation.
-Let $f$ be the result of looking up getter $m$ in $S_{dynamic}$ with respect to $L$.
+Let $f$ be the result of looking up
+getter \id{} in $S$ with respect to $L$.
 The body of $f$ is executed with \THIS{} bound to the current value of \THIS{}.
 The value of $i$ is the result returned by the call to the getter function.
 
 \commentary{
 The getter lookup will not fail, because it is a compile-time error to have
-a super property extraction of a member $m$ when the superclass $S_{dynamic}$
-does not have a concrete member named $m$.
+a super property extraction of a member \id{} when the superclass $S$
+does not have a concrete member named \id.
 }
 
-\LMHash{}%
-Let $S_{static}$ be the superclass of the immediately enclosing class.
-It is a compile-time error if $S_{static}$ does not have an accessible instance method or getter named $m$.
-
-The static type of $i$ is:
-\begin{itemize}
-\item The declared return type of $S_{static}.m$, if $S_{static}$ has an accessible instance getter named $m$.
-\item The static type of function $S_{static}.m$, if $S_{static}$ has an accessible instance method named $m$.
-\item The type \DYNAMIC{} otherwise.
-\end{itemize}
-
 
 \subsubsection{Ordinary Member Closurization}
 \LMLabel{ordinaryMemberClosurization}
 
+\LMHash{}%
+This section specifies the dynamic semantics of
+ordinary member closurizations.
+
 \commentary{
 Note that the non-generic case is covered implicitly using $s = 0$,
-in which case the type parameter declarations are omitted (\ref{generics}).
+in which case the type parameter declaration lists
+and the actual type argument lists passed in invocations
+are omitted (\ref{generics}).
 }
 
 \LMHash{}%
@@ -7404,26 +8235,30 @@
 %\item $(a) \{\RETURN{}$ $u[a];$\} if $f$ is named \code{[]}.
 %\item $(a, b) \{\RETURN{}$ $u[a] = b;$\} if $f$ is named \code{[]=}.
 \item
-\begin{dartCode}
-<$X_1\ \EXTENDS\ B'_1, \ldots,\ X_s\ \EXTENDS\ B'_s$>
-($T_1\ r_1, \ldots,\ T_n\ r_n,\ $\{$T_{n+1}\ p_1 = d_1, \ldots,\ T_{n+k}\ p_k = d_k$\}) =>
-    $u.m$<$X_1, \ldots,\ X_s$>($r_1, \ldots,\ r_n,\ p_1$: $p_1, \ldots,\ p_k$: $p_k$);
-\end{dartCode}
-if $f$ is named $m$ and has type parameter declarations
-$X_1\ \EXTENDS\ B_1$, \ldots,\ $X_s\ \EXTENDS\ B_s$,
-required parameters $r_1, \ldots, r_n$,
-and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\begin{normativeDartCode}
+<\TypeParameters{X}{B'}{s}>
+($\PairList{T}{p}{1}{n},\ $\{$T_{n+1}\ p_{n+1} = d_1, \ldots,\ T_{n+k}\ p_{n+k} = d_k$\}) =>
+\quad$u$.$m$<\List{X}{1}{s}>($\List{p}{1}{n},\ p_{n+1}$: $p_{n+1}, \ldots,\ p_{n+k}$: $p_{n+k}$);
+\end{normativeDartCode}
+where $f$ is an instance method named $m$
+which has type parameter declarations
+\TypeParametersStd{},
+required parameters \List{p}{1}{n},
+and named parameters \List{p}{n+1}{n+k} with defaults \List{d}{1}{k},
+using \code{null} for parameters whose default value is not specified.
 \item
-\begin{dartCode}
-<$X_1\ \EXTENDS\ B'_1, \ldots,\ X_s\ \EXTENDS\ B'_s$>
-($T_1\ r_1, \ldots,\ T_n\ r_n,\ $[$T_{n+1}\ p_1 = d_1, \ldots,\ T_{n+k}\ p_k = d_k$]) =>
-    $u.m$<$X_1, \ldots,\ X_s$>($r_1, \ldots,\ r_n,\ p_1, \ldots,\ p_k$);
-\end{dartCode}
-if $f$ is named $m$ and has type parameter declarations
-$X_1\ \EXTENDS\ B_1$, \ldots,\ $X_s\ \EXTENDS\ B_s$,
-required parameters $r_1, \ldots, r_n$,
+\begin{normativeDartCode}
+<\TypeParameters{X}{B'}{s}>
+($\PairList{T}{p}{1}{n},\ $[$T_{n+1}\ p_{n+1} = d_1, \ldots,\ T_{n+k}\ p_{n+k} = d_k$]) =>
+\quad$u$.$m$<\List{X}{1}{s}>(\List{p}{1}{n+k});
+\end{normativeDartCode}
+where $f$ is an instance method named $m$
+which has type parameter declarations
+\TypeParametersStd{},
+required parameters \List{p}{1}{n},
 and optional positional parameters
-$p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\List{p}{n+1}{n+k} with defaults \List{d}{1}{k},
+using \code{null} for parameters whose default value is not specified.
 \end{itemize}
 
 \LMHash{}%
@@ -7434,23 +8269,14 @@
 Then $B'_j = [t'_1/X'_1, \ldots, t'_{s'}/X'_{s'}]B_j, j \in 1 .. s$.
 
 \commentary{
-That is, we replace the formal type parameters of the enclosing class, if any, by the corresponding actual type arguments.
+That is, we replace the formal type parameters of the enclosing class, if any,
+by the corresponding actual type arguments.
 }
 
-%% TODO: We should specify tear-offs by means of their (static and dynamice)
-%% semantics, not via syntactic sugar, because the syntactic sugar causes
-%% weird phenomena like `a type annotation that denotes the same type as`
-%% etc.
-
-%% TODO[covariant-parameters]: When adding a specification of covariant
-%% parameters we will need to indicate that the dynamic parameter type is
-%% `Object` for such a parameter, and that the static type of the function
-%% as a whole will be taken from the statically known type of the receiver
-%% of the tear-off invocation.
-
 \LMHash{}%
 The parameter types $T_j, j \in 1 .. n+k$, are determined as follows:
-Let the method declaration $D$ be the implementation of $m$ which is invoked by the expression in the body.
+Let the method declaration $D$ be the implementation of $m$
+which is invoked by the expression in the body.
 Let $T$ be the class that contains $D$.
 
 \commentary{
@@ -7458,8 +8284,24 @@
 }
 
 \LMHash{}%
+For each parameter $p_j$, $j \in 1 .. n+k$, if $p_j$ is covariant
+(\ref{covariantParameters})
+then $T_j$ is the built-in class \code{Object}.
+
+\commentary{
+This is concerned with the dynamic type of the function object obtained by
+the member closurization.
+The static type of the expression that gives rise to the member closurization
+is specified elsewhere
+(\ref{propertyExtraction},
+\ref{getterAccessAndMethodExtraction}).
+Note that for the static type it is ignored whether a parameter is covariant.
+}
+
+\LMHash{}%
 If $T$ is a non-generic class then for $j \in 1 .. n+k$,
-$T_j$ is a type annotation that denotes the same type as that which is denoted by the type annotation on the corresponding parameter declaration in $D$.
+$T_j$ is a type annotation that denotes the same type as that
+which is denoted by the type annotation on the corresponding parameter declaration in $D$.
 If that parameter declaration has no type annotation then $T_j$ is \DYNAMIC{}.
 
 \LMHash{}%
@@ -7479,11 +8321,6 @@
 obtained by closurization of $m$ on $o_1$ respectively $o_2$.
 Then \code{$c_1$ == $c_2$} evaluates to true if and only if $o_1$ and $o_2$ is the same object.
 
-%% TODO(eernst): This being a comment, it's presumably spelled out somewhere
-%% else. Find it and check that it does actually say that it is an error
-%% except when the type of $e$ is \DYNAMIC{}.
-%\item The static type of the property extraction is the static type of function \code{$T$.$m$}, where $T$ is the static type of $e$, if \code{$T$.$m$} is defined. Otherwise the static type of $e.m$ is \DYNAMIC{}.
-
 \commentary{
 % Spell out the consequences for `==` and for `identical`, for the receivers
 % and for the closurizations.
@@ -7505,6 +8342,10 @@
 \subsubsection{Super Closurization}
 \LMLabel{superClosurization}
 
+\LMHash{}%
+This section specifies the dynamic semantics of
+super closurizations.
+
 \commentary{
 Note that the non-generic case is covered implicitly using $s = 0$,
 in which case the type parameter declarations are omitted (\ref{generics}).
@@ -7533,25 +8374,28 @@
 %\item $(a) \{\RETURN{}$ $\SUPER[a];$\} if $f$ is named \code{[]}.
 %\item $(a, b) \{\RETURN{}$ $\SUPER[a] = b;$\} if $f$ is named \code{[]=}.
 \item
-\begin{dartCode}
-<$X_1\ \EXTENDS\ B'_1, \ldots,\ X_s\ \EXTENDS\ B'_s$>
-($T_1\ r_1, \ldots,\ T_n\ r_n,\ $\{$T_{n+1}\ p_1 = d_1, \ldots,\ T_{n+k}\ p_k = d_k$\}) =>
-    \SUPER$.m$<$X_1, \ldots,\ X_s$>($r_1, \ldots,\ r_n,\ p_1$: $p_1, \ldots,\ p_k$: $p_k$);
-\end{dartCode}
-if $f$ is named $m$ and has type parameter declarations
-$X_1\ \EXTENDS\ B_1$, \ldots,\ $X_s\ \EXTENDS\ B_s$,
-required parameters $r_1, \ldots, r_n$,
-and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\begin{normativeDartCode}
+<\TypeParameters{X}{B'}{s}>
+($\PairList{T}{p}{1}{n},\ $\{$T_{n+1}\ p_{n+1} = d_1, \ldots,\ T_{n+k}\ p_{n+k} = d_k$\}) =>
+\quad\SUPER$.m$<\List{X}{1}{s}>($\List{p}{1}{n},\ p_{n+1}$: $p_{n+1}, \ldots,\ p_{n+k}$: $p_{n+k}$);
+\end{normativeDartCode}
+where $f$ is an instance method named $m$
+which has type parameter declarations
+\TypeParametersStd{},
+required parameters \List{p}{1}{n},
+and named parameters \List{p}{n+1}{n+k} with defaults \List{d}{1}{k}.
 \item
-\begin{dartCode}
-<$X_1\ \EXTENDS\ B'_1, \ldots,\ X_s\ \EXTENDS\ B'_s$>
-($T_1\ r_1, \ldots,\ T_n\ r_n,\ $[$T_{n+1}\ p_1 = d_1, \ldots,\ T_{n+k}\ p_k = d_k$]) =>
-    \SUPER.$m$<$X_1, \ldots,\ X_s$>($r_1, \ldots,\ r_n,\ p_1, \ldots,\ p_k$);
-\end{dartCode}
-if $f$ is named $m$ and has type parameter declarations
-$X_1\ \EXTENDS\ B_1$, \ldots,\ $X_s\ \EXTENDS\ B_s$,
-required parameters $r_1, \ldots, r_n$,
-and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\begin{normativeDartCode}
+<\TypeParameters{X}{B'}{s}>
+($\PairList{T}{p}{1}{n},\ $[$T_{n+1}\ p_{n+1} = d_1, \ldots,\ T_{n+k}\ p_{n+k} = d_k$]) =>
+\quad\SUPER.$m$<\List{X}{1}{s}>(\List{p}{1}{n+k});
+\end{normativeDartCode}
+where $f$ is an instance method named $m$
+which has type parameter declarations
+\TypeParametersStd{},
+required parameters \List{p}{1}{n},
+and optional positional parameters
+\List{p}{n+1}{n+k} with defaults \List{d}{1}{k}.
 \end{itemize}
 
 \commentary{
@@ -7567,28 +8411,36 @@
 Then $B'_j = [t'_1/X'_1, \ldots, t'_{s'}/X'_{s'}]B_j, j \in 1 .. s$.
 
 \commentary{
-That is, we replace the formal type parameters of the enclosing class, if any, by the corresponding actual type arguments.
-We need to consider the type arguments with respect to a specific class because it is possible for a class to pass different type arguments to its superclass than the ones it receives itself.
+That is, we replace the formal type parameters of the enclosing class, if any,
+by the corresponding actual type arguments.
+We need to consider the type arguments with respect to a specific class because
+it is possible for a class to pass different type arguments to its superclass
+than the ones it receives itself.
 }
 
-%% TODO: We should specify tear-offs by means of their (static and dynamice)
-%% semantics, not via syntactic sugar, because the syntactic sugar causes
-%% weird phenomena like `a type annotation that denotes the same type as`
-%% etc.
-
-%% TODO[covariant-parameters]: When adding a specification of covariant
-%% parameters we will need to indicate that the dynamic parameter type is
-%% `Object` for such a parameter, and that the static type of the function
-%% as a whole will be taken from the statically known type of the receiver
-%% of the tear-off invocation.
-
 \LMHash{}%
 The parameter types $T_j, j \in 1 .. n+k$, are determined as follows:
 Let the method declaration $D$ be the implementation of $m$ in $S$.
 
 \LMHash{}%
+For each parameter $p_j$, $j \in 1 .. n+k$, if $p_j$ is covariant
+(\ref{covariantParameters})
+then $T_j$ is the built-in class \code{Object}.
+
+\commentary{
+This is concerned with the dynamic type of the function object obtained by
+the super closurization.
+The static type of the expression that gives rise to the super closurization
+is specified elsewhere
+(\ref{propertyExtraction},
+\ref{superGetterAccessAndMethodClosurization}).
+Note that for the static type it is ignored whether a parameter is covariant.
+}
+
+\LMHash{}%
 If $S$ is a non-generic class then for $j \in 1 .. n+k$,
-$T_j$ is a type annotation that denotes the same type as that which is denoted by the type annotation on the corresponding parameter declaration in $D$.
+$T_j$ is a type annotation that denotes the same type as that
+which is denoted by the type annotation on the corresponding parameter declaration in $D$.
 If that parameter declaration has no type annotation then $T_j$ is \DYNAMIC{}.
 
 \LMHash{}%
@@ -9442,13 +10294,13 @@
 and let $n0$ be an identifier that does not occur anywhere in the program.
 A for statement of the form \code{\FOR{} ($D$ \id{} \IN{} $e$) $s$} is equivalent to the following code:
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \VAR{} $n0$ = $e$.iterator;
 \WHILE{} ($n0$.moveNext()) \{
    $D$ \id{} = $n0$.current;
    $s$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 For purposes of static typechecking,
 this code is checked under the assumption that $n0$ is declared to be of type $T$,
@@ -9623,24 +10475,24 @@
 \LMHash{}%
  Given a switch statement of the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
    $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 or the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 it is a compile-time error unless the expressions $e_k$ are constant expressions for all $k \in 1 .. n$.
 It is a compile-time error if the values of the expressions $e_k$ are not either:
@@ -9684,24 +10536,24 @@
 \LMHash{}%
 Execution of a switch statement of the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
    $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 or the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 proceeds as follows:
 
@@ -9721,14 +10573,14 @@
 \LMHash{}%
 Matching of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a switch statement
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
    $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 against the value of a variable \id{} proceeds as follows:
 
@@ -9743,13 +10595,13 @@
 \LMHash{}%
 Matching of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a switch statement
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 against the value of a variable \id{} proceeds as follows:
 
@@ -9813,24 +10665,24 @@
 \LMHash{}%
 Execution of the case statements $s_h$ of a switch statement
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 or a switch statement
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
    $\ldots$
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
    $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
-\end{dartCode}
+\end{normativeDartCode}
 
 proceeds as follows:
 
@@ -9940,13 +10792,13 @@
 \LMHash{}%
 Execution of a \TRY{} statement $s$ of the form:
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \TRY{} $b$
 \ON{} $T_1$ \CATCH{} ($e_1$, $t_1$) $c_1$
 \ldots{}
 \ON{} $T_n$ \CATCH{} ($e_n$, $t_n$) $c_n$
 \FINALLY{} $f$
-\end{dartCode}
+\end{normativeDartCode}
 proceeds as follows:
 
 \LMHash{}%
@@ -9971,11 +10823,11 @@
 \LMHash{}%
 Matching an exception object $e$ and stack trace $t$ against a (potentially empty) sequence of \ON{}-\CATCH{} clauses of the form
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \ON{} $T_1$ \CATCH{} ($e_1$, $st_1$) \{ $s_1$ \}
 \ldots
 \ON{} $T_n$ \CATCH{} ($e_n$, $st_n$) \{ $s_n$ \}
-\end{dartCode}
+\end{normativeDartCode}
 proceeds as follows:
 
 \LMHash{}%
@@ -9991,11 +10843,11 @@
 \LMHash{}%
 Otherwise, if the first clause did not match $e$, $e$ and $t$ are recursively matched against the remaining \ON{}-\CATCH{} clauses:
 
-\begin{dartCode}
+\begin{normativeDartCode}
 \ON{} $T_2$ \CATCH{} ($e_2$, $t_2$) \{ $s_2$ \}
 \ldots
 \ON{} $T_n$ \CATCH{} ($e_n$, $t_n$) \{ $s_n$ \}
-\end{dartCode}
+\end{normativeDartCode}
 
 
 \subsection{Return}
@@ -11325,7 +12177,7 @@
 \LMLabel{interfaceTypes}
 
 \LMHash{}%
-The implicit interface of class $I$ is a direct supertype of the implicit interface of class $J$ if{}f:
+The interface of class $I$ is a direct supertype of the interface of class $J$ if{}f:
 \begin{itemize}
 \item $I$ is \code{Object}, and $J$ has no \EXTENDS{} clause.
 \item $I$ is listed in the \EXTENDS{} clause of $J$.
diff --git a/docs/language/informal/covariant-from-class.md b/docs/language/informal/covariant-from-class.md
index 2cdb696..06d54bf 100644
--- a/docs/language/informal/covariant-from-class.md
+++ b/docs/language/informal/covariant-from-class.md
@@ -2,7 +2,8 @@
 
 **Owner**: eernst@
 
-**Status**: Implemented.
+**Status**: This document is now background material.
+For normative text, please consult the language specification.
 
 **Version**: 0.6 (2018-06-01)
 
diff --git a/docs/language/informal/covariant-overrides.md b/docs/language/informal/covariant-overrides.md
index f0f415e..dc0b83b 100644
--- a/docs/language/informal/covariant-overrides.md
+++ b/docs/language/informal/covariant-overrides.md
@@ -2,7 +2,8 @@
 
 **Owner**: rnystrom@, eernst@.
 
-**Status**: Implemented.
+**Status**: This document is now background material.
+For normative text, please consult the language specification.
 
 **Version**: 1.1 (Oct 10, 2017).
 
diff --git a/docs/language/informal/int64.md b/docs/language/informal/int64.md
index 20d89ab..f0b4a6d 100644
--- a/docs/language/informal/int64.md
+++ b/docs/language/informal/int64.md
@@ -5,7 +5,7 @@
 
 **Version**: 2017-09-26.
 
-**Status**: Implemented.
+**Status**: Background material, the normative source is now the language specification.
 
 This document discusses Dart's plan to switch the `int` type so that it represents 64-bit integers instead of bigints. It is part of our continued effort of changing the integer type to fixed size ([issue]).
 
diff --git a/docs/language/informal/interface-conflicts.md b/docs/language/informal/interface-conflicts.md
index cd1d7f3..ebc21f2 100644
--- a/docs/language/informal/interface-conflicts.md
+++ b/docs/language/informal/interface-conflicts.md
@@ -2,7 +2,11 @@
 
 **Owner**: eernst@
 
-**Status**: Under discussion.
+**Status**: Background material, normative text is now in dartLangSpec.tex.
+Note that the rules have changed, which means that
+**this document cannot be used as a reference**, it can only be
+used to get an overview of the ideas; please refer to the language
+specification for all technical details.
 
 **Version**: 0.3 (2018-04-24)
 
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 1760f2a..b945ed6 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -91,6 +91,21 @@
    */
   Future<ResolveResult> getResolvedAst(String path);
 
+  /// Return a future that will complete with information about the results of
+  /// resolving all of the files in the library with the given absolute,
+  /// normalized [path].
+  ///
+  /// Throw [ArgumentError] if the given [path] is not the defining compilation
+  /// unit for a library (that is, is a part of a library).
+  Future<ResolvedLibraryResult> getResolvedLibrary(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving all of the files in the library with the library [element].
+  ///
+  /// Throw [ArgumentError] if the [element] was not produced by this session.
+  Future<ResolvedLibraryResult> getResolvedLibraryByElement(
+      LibraryElement element);
+
   /**
    * Return a future that will complete with the source kind of the file with
    * the given absolute, normalized [path]. If the path does not represent a
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 000fcae..6f2d3ec 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -8,6 +8,7 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart' as results;
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart'
@@ -24,6 +25,7 @@
 import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
 import 'package:analyzer/src/dart/analysis/library_context.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/analysis/search.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
@@ -187,6 +189,13 @@
   final _requestedFiles = <String, List<Completer<AnalysisResult>>>{};
 
   /**
+   * The mapping from the files for which analysis was requested using
+   * [getResolvedLibrary] to the [Completer]s to report the result.
+   */
+  final _requestedLibraries =
+      <String, List<Completer<ResolvedLibraryResult>>>{};
+
+  /**
    * The task that discovers available files.  If this field is not `null`,
    * and the task is not completed, it should be performed and completed
    * before any name searching task.
@@ -468,6 +477,9 @@
     if (_requestedFiles.isNotEmpty) {
       return AnalysisDriverPriority.interactive;
     }
+    if (_requestedLibraries.isNotEmpty) {
+      return AnalysisDriverPriority.interactive;
+    }
     if (_discoverAvailableFilesTask != null &&
         !_discoverAvailableFilesTask.isCompleted) {
       return AnalysisDriverPriority.interactive;
@@ -725,6 +737,83 @@
     return unitResult.element.library;
   }
 
+  /**
+   * Return a [Future] that completes with a [ResolvedLibraryResult] for the
+   * Dart library file with the given [path].  If the file is not a Dart file
+   * or cannot be analyzed, the [Future] completes with `null`.
+   *
+   * Throw [ArgumentError] if the given [path] is not the defining compilation
+   * unit for a library (that is, is a part of a library).
+   *
+   * The [path] must be absolute and normalized.
+   *
+   * The [path] can be any file - explicitly or implicitly analyzed, or neither.
+   *
+   * Invocation of this method causes the analysis state to transition to
+   * "analyzing" (if it is not in that state already), the driver will produce
+   * the resolution result for it, which is consistent with the current file
+   * state (including new states of the files previously reported using
+   * [changeFile]), prior to the next time the analysis state transitions
+   * to "idle".
+   */
+  Future<ResolvedLibraryResult> getResolvedLibrary(String path) {
+    _throwIfNotAbsolutePath(path);
+    if (!_fsState.hasUri(path)) {
+      return new Future.value();
+    }
+
+    FileState file = _fsState.getFileForPath(path);
+
+    if (file.isExternalLibrary) {
+      return Future.value(
+        ResolvedLibraryResultImpl.external(currentSession, file.uri),
+      );
+    }
+
+    if (file.isPart) {
+      throw ArgumentError('Is a part: $path');
+    }
+
+    // Schedule analysis.
+    var completer = new Completer<ResolvedLibraryResult>();
+    _requestedLibraries
+        .putIfAbsent(path, () => <Completer<ResolvedLibraryResult>>[])
+        .add(completer);
+    _scheduler.notify(this);
+    return completer.future;
+  }
+
+  /**
+   * Return a [Future] that completes with a [ResolvedLibraryResult] for the
+   * Dart library file with the given [uri].
+   *
+   * Throw [ArgumentError] if the given [uri] is not the defining compilation
+   * unit for a library (that is, is a part of a library).
+   *
+   * Invocation of this method causes the analysis state to transition to
+   * "analyzing" (if it is not in that state already), the driver will produce
+   * the resolution result for it, which is consistent with the current file
+   * state (including new states of the files previously reported using
+   * [changeFile]), prior to the next time the analysis state transitions
+   * to "idle".
+   */
+  Future<ResolvedLibraryResult> getResolvedLibraryByUri(Uri uri) {
+    FileState file = _fsState.getFileForUri(uri);
+
+    if (file.isExternalLibrary) {
+      return Future.value(
+        ResolvedLibraryResultImpl.external(currentSession, file.uri),
+      );
+    }
+
+    if (file.isPart) {
+      throw ArgumentError('Is a part: $uri');
+    }
+
+    // The file is a local file, we can get the result.
+    return getResolvedLibrary(file.path);
+  }
+
   ApiSignature getResolvedUnitKeyByPath(String path) {
     _throwIfNotAbsolutePath(path);
     ApiSignature signature = getUnitKeyByPath(path);
@@ -959,6 +1048,22 @@
       return;
     }
 
+    // Analyze a requested library.
+    if (_requestedLibraries.isNotEmpty) {
+      String path = _requestedLibraries.keys.first;
+      try {
+        var result = _computeResolvedLibrary(path);
+        _requestedLibraries.remove(path).forEach((completer) {
+          completer.complete(result);
+        });
+      } catch (exception, stackTrace) {
+        _requestedLibraries.remove(path).forEach((completer) {
+          completer.completeError(exception, stackTrace);
+        });
+      }
+      return;
+    }
+
     // Process an index request.
     if (_indexRequestedFiles.isNotEmpty) {
       String path = _indexRequestedFiles.keys.first;
@@ -1256,7 +1361,7 @@
           if (!_fsState.getFileForUri(Uri.parse('dart:async')).exists) {
             return _newMissingDartLibraryResult(file, 'dart:async');
           }
-          libraryContext = await _createLibraryContext(library);
+          libraryContext = _createLibraryContext(library);
 
           LibraryAnalyzer analyzer = new LibraryAnalyzer(
               analysisOptions,
@@ -1267,7 +1372,7 @@
               libraryContext.resynthesizer,
               library,
               _resourceProvider);
-          Map<FileState, UnitAnalysisResult> results = await analyzer.analyze();
+          Map<FileState, UnitAnalysisResult> results = analyzer.analyze();
 
           List<int> bytes;
           CompilationUnit resolvedUnit;
@@ -1319,6 +1424,62 @@
     return analysisResult._index;
   }
 
+  /**
+   * Return the newly computed resolution result of the library with the
+   * given [path].
+   */
+  ResolvedLibraryResultImpl _computeResolvedLibrary(String path) {
+    FileState library = _fsState.getFileForPath(path);
+
+    return _logger.run('Compute resolved library $path', () {
+      _testView.numOfAnalyzedLibraries++;
+      var libraryContext = _createLibraryContext(library);
+
+      LibraryAnalyzer analyzer = new LibraryAnalyzer(
+          analysisOptions,
+          declaredVariables,
+          sourceFactory,
+          libraryContext.isLibraryUri,
+          libraryContext.analysisContext,
+          libraryContext.resynthesizer,
+          library,
+          _resourceProvider);
+      Map<FileState, UnitAnalysisResult> unitResults = analyzer.analyze();
+      var resolvedUnits = <ResolvedUnitResult>[];
+
+      for (var unitFile in unitResults.keys) {
+        if (unitFile.path != null) {
+          var unitResult = unitResults[unitFile];
+          resolvedUnits.add(
+            new AnalysisResult(
+              this,
+              _sourceFactory,
+              unitFile.path,
+              unitFile.uri,
+              unitFile.exists,
+              unitFile.content,
+              unitFile.lineInfo,
+              unitFile.isPart,
+              null,
+              unitResult.unit,
+              unitResult.errors,
+              null,
+            ),
+          );
+        }
+      }
+
+      return new ResolvedLibraryResultImpl(
+        currentSession,
+        library.path,
+        library.uri,
+        resolvedUnits.first.libraryElement,
+        libraryContext.analysisContext.typeProvider,
+        resolvedUnits,
+      );
+    });
+  }
+
   Future<UnitElementResult> _computeUnitElement(String path,
       {bool asIsIfPartWithoutLibrary: false}) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
@@ -1335,7 +1496,7 @@
       }
     }
 
-    LibraryContext libraryContext = await _createLibraryContext(library);
+    LibraryContext libraryContext = _createLibraryContext(library);
     try {
       CompilationUnitElement element =
           libraryContext.computeUnitElement(library.source, file.source);
@@ -1389,9 +1550,7 @@
   /**
    * Return the context in which the [library] should be analyzed.
    */
-  Future<LibraryContext> _createLibraryContext(FileState library) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
+  LibraryContext _createLibraryContext(FileState library) {
     _testView.numOfCreatedLibraryContexts++;
     return new LibraryContext.forSingleLibrary(
         library,
@@ -1955,7 +2114,7 @@
     FileState library = driver.fsState.getFileForPath(libraryPath);
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
-    LibraryContext libraryContext = await driver._createLibraryContext(library);
+    LibraryContext libraryContext = driver._createLibraryContext(library);
     try {
       return libraryContext.store;
     } finally {
@@ -1975,7 +2134,7 @@
  * Every result is independent, and is not guaranteed to be consistent with
  * any previously returned result, even inside of the same library.
  */
-class AnalysisResult extends FileResult implements results.ResolveResult {
+class AnalysisResult extends FileResult implements results.ResolvedUnitResult {
   static final _UNCHANGED = new AnalysisResult(
       null, null, null, null, null, null, null, null, null, null, null, null);
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index f9da8aa..e627abb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -214,10 +214,25 @@
   List<FileState> get importedFiles => _importedFiles;
 
   /**
+   * Return `true` if the file is a stub created for a library in the provided
+   * external summary store.
+   */
+  bool get isExternalLibrary {
+    return _fsState.externalSummaries != null &&
+        _fsState.externalSummaries.linkedMap.containsKey(uriStr);
+  }
+
+  /**
    * Return `true` if the file does not have a `library` directive, and has a
    * `part of` directive, so is probably a part.
    */
-  bool get isPart => _unlinked.libraryNameOffset == 0 && _unlinked.isPartOf;
+  bool get isPart {
+    if (_fsState.externalSummaries != null &&
+        _fsState.externalSummaries.unlinkedMap.containsKey(uriStr)) {
+      return !_fsState.externalSummaries.linkedMap.containsKey(uriStr);
+    }
+    return _unlinked.libraryNameOffset == 0 && _unlinked.isPartOf;
+  }
 
   /**
    * Return `true` if the file is the "unresolved" file, which does not have
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index bce1a66..dfc67fe 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -94,10 +92,8 @@
   /**
    * Compute analysis results for all units of the library.
    */
-  Future<Map<FileState, UnitAnalysisResult>> analyze() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    return PerformanceStatistics.analysis.makeCurrentWhileAsync(() async {
+  Map<FileState, UnitAnalysisResult> analyze() {
+    return PerformanceStatistics.analysis.makeCurrentWhile(() {
       return analyzeSync();
     });
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index 2f1eb6c..2b9ac07 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -144,9 +144,6 @@
   final LibraryElement element;
 
   @override
-  final ResultState state = ResultState.VALID;
-
-  @override
   final TypeProvider typeProvider;
 
   @override
@@ -156,8 +153,23 @@
       this.element, this.typeProvider, this.units)
       : super(session, path, uri);
 
+  ResolvedLibraryResultImpl.external(AnalysisSession session, Uri uri)
+      : this(session, null, uri, null, null, null);
+
+  @override
+  ResultState get state {
+    if (path == null) {
+      return ResultState.NOT_A_FILE;
+    }
+    return ResultState.VALID;
+  }
+
   @override
   ElementDeclarationResult getElementDeclaration(Element element) {
+    if (state != ResultState.VALID) {
+      throw StateError('The result is not valid: $state');
+    }
+
     var elementPath = element.source.fullName;
     var unitResult = units.firstWhere(
       (r) => r.path == elementPath,
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 982f3bb..b44d556 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -130,6 +130,20 @@
   }
 
   @override
+  Future<ResolvedLibraryResult> getResolvedLibrary(String path) {
+    _checkConsistency();
+    return _driver.getResolvedLibrary(path);
+  }
+
+  @override
+  Future<ResolvedLibraryResult> getResolvedLibraryByElement(
+      LibraryElement element) {
+    _checkConsistency();
+    _checkElementOfThisSession(element);
+    return _driver.getResolvedLibraryByUri(element.source.uri);
+  }
+
+  @override
   Future<SourceKind> getSourceKind(String path) {
     _checkConsistency();
     return _driver.getSourceKind(path);
@@ -163,4 +177,13 @@
       throw new InconsistentAnalysisException();
     }
   }
+
+  void _checkElementOfThisSession(Element element) {
+    // TODO(scheglov) Requires 2.2 implementation
+//    if (element.session != this) {
+//      throw new ArgumentError(
+//          '(${element.runtimeType}) $element was not produced by '
+//          'this session.');
+//    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 2c718d9..650778f 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -892,7 +892,7 @@
         constKeyword, typeArguments, leftBracket, entries, rightBracket));
   }
 
-  void endLiteralMapEntry(Token colon, Token endToken) {
+  void handleLiteralMapEntry(Token colon, Token endToken) {
     assert(optional(':', colon));
     debugEvent("LiteralMapEntry");
 
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index 85053fe..66112ea 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -711,7 +711,12 @@
     for (int i = 0; i < count; i++) {
       elements.insert(0, _pop());
     }
-    _push(AstTestFactory.listLiteral2(Keyword.CONST, typeArguments, elements));
+    var typeArg = typeArguments == null
+        ? resynthesizer.typeProvider.dynamicType
+        : typeArguments.arguments[0].type;
+    var staticType = resynthesizer.typeProvider.listType.instantiate([typeArg]);
+    _push(AstTestFactory.listLiteral2(Keyword.CONST, typeArguments, elements)
+      ..staticType = staticType);
   }
 
   void _pushLocalFunctionReference() {
@@ -770,7 +775,16 @@
       Expression key = _pop();
       entries.insert(0, AstTestFactory.mapLiteralEntry2(key, value));
     }
-    _push(AstTestFactory.mapLiteral(Keyword.CONST, typeArguments, entries));
+    var keyType = typeArguments == null
+        ? resynthesizer.typeProvider.dynamicType
+        : typeArguments.arguments[0].type;
+    var valueType = typeArguments == null
+        ? resynthesizer.typeProvider.dynamicType
+        : typeArguments.arguments[1].type;
+    var staticType =
+        resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
+    _push(AstTestFactory.mapLiteral(Keyword.CONST, typeArguments, entries)
+      ..staticType = staticType);
   }
 
   void _pushPrefix(TokenType operator) {
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 7fea9c5..2add257 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -257,7 +257,10 @@
         if (libraryMap == null) {
           getLibraryElement(libraryUri);
           libraryMap = _resynthesizedUnits[libraryUri];
-          assert(libraryMap != null);
+          if (libraryMap == null) {
+            throw new StateError(
+                'Unable to find library `$libraryUri` in a summary file.');
+          }
         }
         CompilationUnitElementImpl unitElement = libraryMap[unitUri];
         // Fill elements in the unit map.
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index d224d7f..8d275c0 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -3731,6 +3731,52 @@
     verify([source]);
   }
 
+  test_issue_35320_lists() async {
+    addNamedSource('/lib.dart', '''
+const x = const <String>['a'];
+''');
+    Source source = addSource('''
+import 'lib.dart';
+const y = const <String>['b'];
+int f(v) {
+  switch(v) {
+    case x:
+      return 0;
+    case y:
+      return 1;
+    default:
+      return 2;
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  test_issue_35320_maps() async {
+    addNamedSource('/lib.dart', '''
+const x = const <String, String>{'a': 'b'};
+''');
+    Source source = addSource('''
+import 'lib.dart';
+const y = const <String, String>{'c': 'd'};
+int f(v) {
+  switch(v) {
+    case x:
+      return 0;
+    case y:
+      return 1;
+    default:
+      return 2;
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_listElementTypeNotAssignable() async {
     Source source = addSource(r'''
 var v1 = <int> [42];
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index a39d370..f692d58 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -341,12 +341,6 @@
   }
 
   @override
-  void beginLiteralMapEntry(Token token) {
-    super.beginLiteralMapEntry(token);
-    begin('LiteralMapEntry');
-  }
-
-  @override
   void beginLiteralString(Token token) {
     super.beginLiteralString(token);
     begin('LiteralString');
@@ -849,12 +843,6 @@
   }
 
   @override
-  void endLiteralMapEntry(Token colon, Token endToken) {
-    end('LiteralMapEntry');
-    super.endLiteralMapEntry(colon, endToken);
-  }
-
-  @override
   void endLiteralString(int interpolationCount, Token endToken) {
     end('LiteralString');
     super.endLiteralString(interpolationCount, endToken);
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 1bcac17..2e121cc 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -48,7 +48,56 @@
 
 @reflectiveTest
 class ClassMemberParserTest_Fasta extends FastaParserTestCase
-    with ClassMemberParserTestMixin {}
+    with ClassMemberParserTestMixin {
+  void test_parseClassMember_operator_gtgtgt() {
+    final sourceText = 'class C { bool operator >>>(other) => false; }';
+
+    // ---------------------------------------------------
+    // TODO(danrubel): Replace this section with a call to parseCompilationUnit
+    // once '>>>' token support is enabled permanently.
+
+    var source = new StringSource(sourceText, 'parser_test_StringSource.dart');
+    GatheringErrorListener errorListener =
+        new GatheringErrorListener(checkRanges: true);
+
+    // Scan tokens
+    StringScanner scanner = new StringScanner(sourceText, includeComments: true)
+      ..enableGtGtGt = true;
+    Token tokens = scanner.tokenize();
+    expect(scanner.hasErrors, isFalse);
+
+    // Run parser
+    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
+    fasta.Parser parser = new fasta.Parser(null);
+    AstBuilder astBuilder = new AstBuilder(errorReporter, source.uri, true);
+    parser.listener = astBuilder;
+    astBuilder.parser = parser;
+    parser.parseUnit(tokens);
+
+    CompilationUnitImpl unit = astBuilder.pop();
+    expect(unit, isNotNull);
+    unit.localDeclarations = astBuilder.localDeclarations;
+    errorListener.assertNoErrors();
+
+    // ---------------------------------------------------
+
+    ClassDeclaration declaration = unit.declarations[0];
+    ClassMember member = declaration.members[0];
+    expect(member, isNotNull);
+    expect(member, new TypeMatcher<MethodDeclaration>());
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name.name, '>>>');
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+}
 
 /**
  * Tests of the fasta parser based on [ComplexParserTestMixin].
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index feb577a..473e17f 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -6919,6 +6919,15 @@
     expect(literal.rightBracket, isNotNull);
   }
 
+  void test_parseMapLiteral_multiple_trailing_comma() {
+    MapLiteral literal = parseMapLiteral(null, null, "{'a' : b, 'x' : y,}");
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.entries, hasLength(2));
+    expect(literal.rightBracket, isNotNull);
+  }
+
   void test_parseMapLiteral_single() {
     MapLiteral literal = parseMapLiteral(null, null, "{'x' : y}");
     expect(literal, isNotNull);
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 1afe213..0345738 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/results.dart' as results;
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -1572,6 +1573,89 @@
     expect(coreLibrary.getType('Object'), isNotNull);
   }
 
+  test_getResolvedLibrary_external() async {
+    var a1 = _p('/aaa/lib/a1.dart');
+    var a2 = _p('/aaa/lib/a2.dart');
+
+    var a1UriStr = 'package:aaa/a1.dart';
+    var a2UriStr = 'package:aaa/a2.dart';
+
+    provider.newFile(a1, "part 'a2.dart';  class A {}");
+    provider.newFile(a2, "part of 'a1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    var driver = createAnalysisDriver(externalSummaries: store);
+    var libraryElement = await driver.getLibraryByUri(a1UriStr);
+    var classA = libraryElement.library.getType('A');
+
+    var resolvedLibrary = await driver.getResolvedLibrary(a1);
+    expect(resolvedLibrary, isNotNull);
+    expect(resolvedLibrary.state, results.ResultState.NOT_A_FILE);
+    expect(() {
+      resolvedLibrary.getElementDeclaration(classA);
+    }, throwsStateError);
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() async {
+      await driver.getResolvedLibrary(a2);
+    }, throwsArgumentError);
+  }
+
+  test_getResolvedLibraryByUri_external() async {
+    var a1 = _p('/aaa/lib/a1.dart');
+    var a2 = _p('/aaa/lib/a2.dart');
+
+    var a1UriStr = 'package:aaa/a1.dart';
+    var a2UriStr = 'package:aaa/a2.dart';
+
+    var a1Uri = Uri.parse(a1UriStr);
+    var a2Uri = Uri.parse(a2UriStr);
+
+    provider.newFile(a1, "part 'a2.dart';  class A {}");
+    provider.newFile(a2, "part of 'a1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    var driver = createAnalysisDriver(externalSummaries: store);
+    var libraryElement = await driver.getLibraryByUri(a1UriStr);
+    var classA = libraryElement.library.getType('A');
+
+    {
+      var resolvedLibrary = await driver.getResolvedLibraryByUri(a1Uri);
+      expect(resolvedLibrary, isNotNull);
+      expect(resolvedLibrary.state, results.ResultState.NOT_A_FILE);
+      expect(() {
+        resolvedLibrary.getElementDeclaration(classA);
+      }, throwsStateError);
+    }
+
+    // We can also get the result from the session.
+    {
+      var session = driver.currentSession;
+      var resolvedLibrary =
+          await session.getResolvedLibraryByElement(libraryElement);
+      expect(resolvedLibrary, isNotNull);
+      expect(resolvedLibrary.state, results.ResultState.NOT_A_FILE);
+      expect(() {
+        resolvedLibrary.getElementDeclaration(classA);
+      }, throwsStateError);
+    }
+
+    // It is an error to ask for a library when we know that it is a part.
+    expect(() async {
+      await driver.getResolvedLibraryByUri(a2Uri);
+    }, throwsArgumentError);
+  }
+
   test_getResult() async {
     String content = 'int f() => 42;';
     addTestFile(content, priority: true);
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 0c00794..a5b9b87 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -2,23 +2,18 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
-import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisOptions, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../context/mock_sdk.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisSessionImplTest);
@@ -26,214 +21,281 @@
 }
 
 @reflectiveTest
-class AnalysisSessionImplTest {
-  MockAnalysisDriver driver;
+class AnalysisSessionImplTest with ResourceProviderMixin {
+  AnalysisContextCollection contextCollection;
+  AnalysisContext context;
   AnalysisSessionImpl session;
 
+  String testContextPath;
+  String aaaContextPath;
+  String bbbContextPath;
+
+  String testPath;
+
   void setUp() {
-    driver = new MockAnalysisDriver();
-    session = new AnalysisSessionImpl(driver);
-    driver.currentSession = session;
+    MockSdk(resourceProvider: resourceProvider);
+
+    testContextPath = newFolder('/home/test').path;
+    aaaContextPath = newFolder('/home/aaa').path;
+    bbbContextPath = newFolder('/home/bbb').path;
+
+    newFile('/home/test/.packages', content: r'''
+test:lib/
+''');
+
+    contextCollection = AnalysisContextCollectionImpl(
+      includedPaths: [testContextPath, aaaContextPath, bbbContextPath],
+      resourceProvider: resourceProvider,
+      sdkPath: convertPath(sdkRoot),
+    );
+    context = contextCollection.contextFor(testContextPath);
+    session = context.currentSession;
+
+    testPath = convertPath('/home/test/lib/test.dart');
   }
 
   test_getErrors() async {
-    ErrorsResult result = new ErrorsResult(null, null, null, null, null, null);
-    driver.errorsResult = result;
-    expect(await session.getErrors('path'), result);
+    newFile(testPath, content: 'class C {');
+    var errorsResult = await session.getErrors(testPath);
+    expect(errorsResult.session, session);
+    expect(errorsResult.path, testPath);
+    expect(errorsResult.errors, isNotEmpty);
   }
 
   test_getLibraryByUri() async {
-    String uri = 'uri';
+    newFile(testPath, content: r'''
+class A {}
+class B {}
+''');
 
-    var source = new _SourceMock(Uri.parse(uri));
-    var unit = new CompilationUnitElementImpl()
-      ..librarySource = source
-      ..source = source;
-    var library = new LibraryElementImpl(null, null, null, null)
-      ..definingCompilationUnit = unit;
-
-    driver.libraryMap[uri] = library;
-    expect(await session.getLibraryByUri(uri), library);
+    var library = await session.getLibraryByUri('package:test/test.dart');
+    expect(library.getType('A'), isNotNull);
+    expect(library.getType('B'), isNotNull);
+    expect(library.getType('C'), isNull);
   }
 
-  test_getParsedAst() async {
-    ParseResult result =
-        new ParseResult(null, null, null, null, null, null, null, null);
-    driver.parseResult = result;
-    expect(await session.getParsedAst('path'), result);
+  test_getParsedAstSync() async {
+    newFile(testPath, content: r'''
+class A {}
+class B {}
+''');
+
+    var unitResult = session.getParsedAstSync(testPath);
+    expect(unitResult.session, session);
+    expect(unitResult.path, testPath);
+    expect(unitResult.uri, Uri.parse('package:test/test.dart'));
+    expect(unitResult.unit.declarations, hasLength(2));
   }
 
   test_getResolvedAst() async {
-    AnalysisResult result = new AnalysisResult(driver, null, null, null, null,
-        null, null, null, null, null, null, null);
-    driver.result = result;
-    expect(await session.getResolvedAst('path'), result);
+    newFile(testPath, content: r'''
+class A {}
+class B {}
+''');
+
+    var unitResult = await session.getResolvedAst(testPath);
+    expect(unitResult.session, session);
+    expect(unitResult.path, testPath);
+    expect(unitResult.uri, Uri.parse('package:test/test.dart'));
+    expect(unitResult.unit.declarations, hasLength(2));
+    expect(unitResult.typeProvider, isNotNull);
+    expect(unitResult.libraryElement, isNotNull);
+  }
+
+  test_getResolvedLibrary() async {
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+
+    var aContent = r'''
+part 'b.dart';
+
+class A /*a*/ {}
+''';
+    newFile(a, content: aContent);
+
+    var bContent = r'''
+part of 'a.dart';
+
+class B /*b*/ {}
+class B2 extends X {}
+''';
+    newFile(b, content: bContent);
+
+    var resolvedLibrary = await session.getResolvedLibrary(a);
+    expect(resolvedLibrary.session, session);
+    expect(resolvedLibrary.path, a);
+    expect(resolvedLibrary.uri, Uri.parse('package:test/a.dart'));
+
+    var typeProvider = resolvedLibrary.typeProvider;
+    expect(typeProvider.intType.element.name, 'int');
+
+    var libraryElement = resolvedLibrary.element;
+    expect(libraryElement, isNotNull);
+
+    var aClass = libraryElement.getType('A');
+    expect(aClass, isNotNull);
+
+    var bClass = libraryElement.getType('B');
+    expect(bClass, isNotNull);
+
+    var aUnitResult = resolvedLibrary.units[0];
+    expect(aUnitResult.path, a);
+    expect(aUnitResult.uri, Uri.parse('package:test/a.dart'));
+    expect(aUnitResult.content, aContent);
+    expect(aUnitResult.unit, isNotNull);
+    expect(aUnitResult.unit.directives, hasLength(1));
+    expect(aUnitResult.unit.declarations, hasLength(1));
+    expect(aUnitResult.errors, isEmpty);
+
+    var bUnitResult = resolvedLibrary.units[1];
+    expect(bUnitResult.path, b);
+    expect(bUnitResult.uri, Uri.parse('package:test/b.dart'));
+    expect(bUnitResult.content, bContent);
+    expect(bUnitResult.unit, isNotNull);
+    expect(bUnitResult.unit.directives, hasLength(1));
+    expect(bUnitResult.unit.declarations, hasLength(2));
+    expect(bUnitResult.errors, isNotEmpty);
+
+    var aDeclaration = resolvedLibrary.getElementDeclaration(aClass);
+    ClassDeclaration aNode = aDeclaration.node;
+    expect(aNode.name.name, 'A');
+    expect(aNode.offset, 16);
+    expect(aNode.length, 16);
+    expect(aNode.name.staticElement.name, 'A');
+
+    var bDeclaration = resolvedLibrary.getElementDeclaration(bClass);
+    ClassDeclaration bNode = bDeclaration.node;
+    expect(bNode.name.name, 'B');
+    expect(bNode.offset, 19);
+    expect(bNode.length, 16);
+    expect(bNode.name.staticElement.name, 'B');
+  }
+
+  test_getResolvedLibrary_getElementDeclaration_notThisLibrary() async {
+    newFile(testPath, content: '');
+
+    var resolvedLibrary = await session.getResolvedLibrary(testPath);
+
+    expect(() {
+      var intClass = resolvedLibrary.typeProvider.intType.element;
+      resolvedLibrary.getElementDeclaration(intClass);
+    }, throwsArgumentError);
+  }
+
+  test_getResolvedLibrary_getElementDeclaration_synthetic() async {
+    newFile(testPath, content: r'''
+int foo = 0;
+''');
+
+    var resolvedLibrary = await session.getResolvedLibrary(testPath);
+    var unitElement = resolvedLibrary.element.definingCompilationUnit;
+
+    var fooElement = unitElement.topLevelVariables[0];
+    expect(fooElement.name, 'foo');
+
+    // We can get the variable element declaration.
+    var fooDeclaration = resolvedLibrary.getElementDeclaration(fooElement);
+    VariableDeclaration fooNode = fooDeclaration.node;
+    expect(fooNode.name.name, 'foo');
+    expect(fooNode.offset, 4);
+    expect(fooNode.length, 7);
+    expect(fooNode.name.staticElement.name, 'foo');
+
+    // Synthetic elements don't have nodes.
+    expect(resolvedLibrary.getElementDeclaration(fooElement.getter), isNull);
+    expect(resolvedLibrary.getElementDeclaration(fooElement.setter), isNull);
+  }
+
+  test_getResolvedLibrary_invalidPartUri() async {
+    newFile(testPath, content: r'''
+part 'a.dart';
+part ':[invalid uri].dart';
+part 'c.dart';
+''');
+
+    var resolvedLibrary = await session.getResolvedLibrary(testPath);
+
+    expect(resolvedLibrary.units, hasLength(3));
+    expect(
+      resolvedLibrary.units[0].path,
+      convertPath('/home/test/lib/test.dart'),
+    );
+    expect(
+      resolvedLibrary.units[1].path,
+      convertPath('/home/test/lib/a.dart'),
+    );
+    expect(
+      resolvedLibrary.units[2].path,
+      convertPath('/home/test/lib/c.dart'),
+    );
+  }
+
+  test_getResolvedLibrary_notLibrary() async {
+    newFile(testPath, content: 'part of "a.dart";');
+
+    expect(() {
+      session.getResolvedLibrary(testPath);
+    }, throwsArgumentError);
+  }
+
+  test_getResolvedLibraryByElement() async {
+    newFile(testPath, content: '');
+
+    var element = await session.getLibraryByUri('package:test/test.dart');
+
+    var resolvedLibrary = await session.getResolvedLibraryByElement(element);
+    expect(resolvedLibrary.session, session);
+    expect(resolvedLibrary.path, testPath);
+    expect(resolvedLibrary.uri, Uri.parse('package:test/test.dart'));
+    expect(resolvedLibrary.units, hasLength(1));
+    expect(resolvedLibrary.units[0].unit.declaredElement, isNotNull);
   }
 
   test_getSourceKind() async {
-    SourceKind kind = SourceKind.LIBRARY;
-    driver.sourceKind = kind;
-    expect(await session.getSourceKind('path'), kind);
+    newFile(testPath, content: 'class C {}');
+
+    var kind = await session.getSourceKind(testPath);
+    expect(kind, SourceKind.LIBRARY);
   }
 
-  test_getTopLevelDeclarations() async {
-    List<TopLevelDeclarationInSource> declarations = [];
-    driver.topLevelDeclarations = declarations;
-    expect(await session.getTopLevelDeclarations('path'), declarations);
+  test_getSourceKind_part() async {
+    newFile(testPath, content: 'part of "a.dart";');
+
+    var kind = await session.getSourceKind(testPath);
+    expect(kind, SourceKind.PART);
   }
 
   test_getUnitElement() async {
-    UnitElementResult result =
-        new UnitElementResult(null, null, null, null, null);
-    driver.unitElementResult = result;
-    expect(await session.getUnitElement('path'), result);
+    newFile(testPath, content: r'''
+class A {}
+class B {}
+''');
+
+    var unitResult = await session.getUnitElement(testPath);
+    expect(unitResult.session, session);
+    expect(unitResult.path, testPath);
+    expect(unitResult.uri, Uri.parse('package:test/test.dart'));
+    expect(unitResult.element.types, hasLength(2));
+
+    var signature = await session.getUnitElementSignature(testPath);
+    expect(unitResult.signature, signature);
   }
 
-  test_getUnitElementSignature() async {
-    String signature = 'xyzzy';
-    driver.unitElementSignature = signature;
-    expect(await session.getUnitElementSignature('path'), signature);
-  }
-
-  test_resourceProvider() {
-    ResourceProvider resourceProvider = new MemoryResourceProvider();
-    driver.resourceProvider = resourceProvider;
+  test_resourceProvider() async {
     expect(session.resourceProvider, resourceProvider);
   }
 
-  test_sourceFactory() {
-    SourceFactory sourceFactory = new SourceFactory([]);
-    driver.sourceFactory = sourceFactory;
-    expect(session.sourceFactory, sourceFactory);
-  }
-
   test_typeProvider() async {
-    _initializeSDK();
-    expect(await session.typeProvider, isNotNull);
+    var typeProvider = await session.typeProvider;
+    expect(typeProvider.intType.element.name, 'int');
   }
 
   test_typeSystem() async {
-    _initializeSDK();
-    expect(await session.typeSystem, isNotNull);
-  }
-
-  void _initializeSDK() {
-    CompilationUnitElementImpl newUnit(String name) {
-      CompilationUnitElementImpl unit = new CompilationUnitElementImpl();
-      unit.accessors = [];
-      unit.enums = [];
-      unit.functions = [];
-      unit.typeAliases = [];
-      return unit;
-    }
-
-    ClassElementImpl newClass(String name) {
-      TypeParameterElementImpl param = new TypeParameterElementImpl('E', 0);
-      param.type = new TypeParameterTypeImpl(param);
-      ClassElementImpl element = new ClassElementImpl(name, 0);
-      element.typeParameters = [param];
-      return element;
-    }
-
-    {
-      CompilationUnitElementImpl coreUnit = newUnit('dart.core');
-      coreUnit.types = <ClassElement>[newClass('Iterable')];
-      LibraryElementImpl core = new LibraryElementImpl(null, null, null, null);
-      core.definingCompilationUnit = coreUnit;
-      driver.libraryMap['dart:core'] = core;
-    }
-    {
-      CompilationUnitElementImpl asyncUnit = newUnit('dart.async');
-      asyncUnit.types = <ClassElement>[
-        newClass('Future'),
-        newClass('FutureOr'),
-        newClass('Stream')
-      ];
-      LibraryElementImpl async = new LibraryElementImpl(null, null, null, null);
-      async.definingCompilationUnit = asyncUnit;
-      driver.libraryMap['dart:async'] = async;
-    }
-  }
-}
-
-class MockAnalysisDriver implements AnalysisDriver {
-  @override
-  AnalysisSession currentSession;
-
-  ErrorsResult errorsResult;
-  Map<String, LibraryElement> libraryMap = <String, LibraryElement>{};
-  ParseResult parseResult;
-  ResourceProvider resourceProvider;
-  AnalysisResult result;
-  SourceFactory sourceFactory;
-  SourceKind sourceKind;
-  List<TopLevelDeclarationInSource> topLevelDeclarations;
-  UnitElementResult unitElementResult;
-  String unitElementSignature;
-
-  AnalysisOptions get analysisOptions => new AnalysisOptionsImpl();
-
-  @override
-  Future<ErrorsResult> getErrors(String path) async {
-    return errorsResult;
-  }
-
-  @override
-  Future<LibraryElement> getLibraryByUri(String uri) async {
-    return libraryMap[uri];
-  }
-
-  @override
-  Future<AnalysisResult> getResult(String path,
-      {bool sendCachedToStream: false}) async {
-    return result;
-  }
-
-  @override
-  Future<SourceKind> getSourceKind(String path) async {
-    return sourceKind;
-  }
-
-  @override
-  Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations(
-      String name) async {
-    return topLevelDeclarations;
-  }
-
-  @override
-  Future<UnitElementResult> getUnitElement(String path) async {
-    return unitElementResult;
-  }
-
-  @override
-  Future<String> getUnitElementSignature(String path) async {
-    return unitElementSignature;
-  }
-
-  @override
-  dynamic noSuchMethod(Invocation invocation) {
-    fail('Unexpected invocation of ${invocation.memberName}');
-  }
-
-  @override
-  Future<ParseResult> parseFile(String path) async {
-    return parseResult;
-  }
-
-  @override
-  ParseResult parseFileSync(String path) {
-    return parseResult;
-  }
-}
-
-class _SourceMock implements Source {
-  @override
-  final Uri uri;
-
-  _SourceMock(this.uri);
-
-  @override
-  noSuchMethod(Invocation invocation) {
-    throw new StateError('Unexpected invocation of ${invocation.memberName}');
+    var typeSystem = await session.typeSystem;
+    var typeProvider = typeSystem.typeProvider;
+    expect(
+      typeSystem.isSubtypeOf(typeProvider.intType, typeProvider.numType),
+      isTrue,
+    );
   }
 }
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index 492f026..cf48c96 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -212,6 +212,14 @@
 ''');
   }
 
+  void test_comma_missing() {
+    testRecovery('''
+f(int a int b) { }
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+f(int a, int b) { }
+''');
+  }
+
   void test_equalEqual() {
     testBinaryExpression('==');
   }
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index d7de722..918c627 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -72,9 +72,11 @@
   /// A source map for a JavaScript output.
   sourceMap,
 
-  /// Additional information requested by the user, such dump info or a deferred
-  /// map.
-  info,
+  /// Dump info output.
+  dumpInfo,
+
+  /// Deferred map output.
+  deferredMap,
 
   /// Implementation specific output used for debugging the compiler.
   debug,
@@ -188,6 +190,6 @@
     return new CompilationResult(compiler,
         isSuccess: success,
         kernelInitializedCompilerState:
-            compiler.libraryLoader.initializedCompilerState);
+            compiler.kernelLoader.initializedCompilerState);
   });
 }
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 82ab539..982a2de 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -34,6 +34,10 @@
   // Experimentally try to force part-file functions to be seen as IIFEs.
   static const String experimentStartupFunctions = '--experiment-code-2';
 
+  // Add instrumentation to log every method call.
+  static const String experimentCallInstrumentation =
+      '--experiment-call-instrumentation';
+
   static const String fastStartup = '--fast-startup';
   static const String fatalWarnings = '--fatal-warnings';
   static const String generateCodeWithCompileTimeErrors =
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 0a8a1b1..4922314 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -11,10 +11,9 @@
 import 'constants/values.dart';
 import 'elements/entities.dart';
 import 'elements/types.dart';
-import 'js_backend/backend.dart' show JavaScriptBackend;
 import 'js_backend/constant_system_javascript.dart';
 import 'js_backend/native_data.dart' show NativeBasicData;
-import 'native/native.dart';
+import 'kernel/dart2js_target.dart';
 import 'types/abstract_value_domain.dart';
 import 'universe/selector.dart' show Selector;
 
@@ -1416,17 +1415,7 @@
   FunctionEntity get boolConversionCheck =>
       _findHelperFunction('boolConversionCheck');
 
-  FunctionEntity get _consoleTraceHelper =>
-      _findHelperFunction('consoleTraceHelper');
-
-  FunctionEntity get _postTraceHelper => _findHelperFunction('postTraceHelper');
-
-  FunctionEntity _traceHelper;
-  FunctionEntity get traceHelper {
-    return _traceHelper ??= JavaScriptBackend.TRACE_METHOD == 'console'
-        ? _consoleTraceHelper
-        : _postTraceHelper;
-  }
+  FunctionEntity get traceHelper => _findHelperFunction('traceHelper');
 
   FunctionEntity get closureFromTearOff =>
       _findHelperFunction('closureFromTearOff');
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index a98f635..c4effda 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -32,7 +32,7 @@
 import 'js_backend/inferred_data.dart';
 import 'js_model/js_strategy.dart';
 import 'kernel/kernel_strategy.dart';
-import 'library_loader.dart' show LibraryLoaderTask, LoadedLibraries;
+import 'kernel/loader.dart' show KernelLoaderTask, KernelResult;
 import 'null_compiler_output.dart' show NullCompilerOutput;
 import 'options.dart' show CompilerOptions, DiagnosticOptions;
 import 'serialization/task.dart';
@@ -101,7 +101,7 @@
   Entity get currentElement => _reporter.currentElement;
 
   List<CompilerTask> tasks;
-  LibraryLoaderTask libraryLoader;
+  KernelLoaderTask kernelLoader;
   GlobalTypeInferenceTask globalInference;
   JavaScriptBackend backend;
   CodegenWorldBuilder _codegenWorldBuilder;
@@ -168,8 +168,8 @@
     enqueuer = backend.makeEnqueuer();
 
     tasks = [
-      libraryLoader =
-          new LibraryLoaderTask(options, provider, reporter, measurer),
+      kernelLoader =
+          new KernelLoaderTask(options, provider, reporter, measurer),
       kernelFrontEndTask,
       globalInference = new GlobalTypeInferenceTask(this),
       constants = backend.constantCompilerTask,
@@ -226,30 +226,6 @@
         });
       });
 
-  /// This method is called when all new libraries loaded through
-  /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
-  /// have been computed.
-  ///
-  /// [loadedLibraries] contains the newly loaded libraries.
-  void processLoadedLibraries(LoadedLibraries loadedLibraries) {
-    frontendStrategy.registerLoadedLibraries(loadedLibraries);
-    loadedLibraries.forEachLibrary((Uri uri) {
-      LibraryEntity library =
-          frontendStrategy.elementEnvironment.lookupLibrary(uri);
-      backend.setAnnotations(library);
-    });
-
-    // TODO(efortuna, sigmund): These validation steps should be done in the
-    // front end for the Kernel path since Kernel doesn't have the notion of
-    // imports (everything has already been resolved). (See
-    // https://github.com/dart-lang/sdk/issues/29368)
-    if (loadedLibraries.containsLibrary(Uris.dart_mirrors)) {
-      reporter.reportWarningMessage(NO_LOCATION_SPANNABLE,
-          MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_WITH_CFE);
-    }
-    backend.onLibrariesLoaded(frontendStrategy.commonElements, loadedLibraries);
-  }
-
   Future runInternal(Uri uri) async {
     // TODO(ahe): This prevents memory leaks when invoking the compiler
     // multiple times. Implement a better mechanism where we can store
@@ -274,16 +250,30 @@
           await serializationTask.deserialize();
       generateJavaScriptCode(results);
     } else {
-      LoadedLibraries loadedLibraries = await libraryLoader.loadLibraries(uri);
-      // Note: libraries may be null because of errors trying to find files or
-      // parse-time errors (when using `package:front_end` as a loader).
-      if (loadedLibraries == null) return;
+      KernelResult result = await kernelLoader.load(uri);
+      if (result == null) return;
       if (compilationFailed && !options.generateCodeWithCompileTimeErrors) {
         return;
       }
-      _mainLibraryUri = loadedLibraries.rootLibraryUri;
-      processLoadedLibraries(loadedLibraries);
-      await compileLoadedLibraries(loadedLibraries);
+      _mainLibraryUri = result.rootLibraryUri;
+
+      frontendStrategy.registerLoadedLibraries(result);
+      for (Uri uri in result.libraries) {
+        LibraryEntity library =
+            frontendStrategy.elementEnvironment.lookupLibrary(uri);
+        backend.setAnnotations(library);
+      }
+
+      // TODO(efortuna, sigmund): These validation steps should be done in the
+      // front end for the Kernel path since Kernel doesn't have the notion of
+      // imports (everything has already been resolved). (See
+      // https://github.com/dart-lang/sdk/issues/29368)
+      if (result.libraries.contains(Uris.dart_mirrors)) {
+        reporter.reportWarningMessage(NO_LOCATION_SPANNABLE,
+            MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_WITH_CFE);
+      }
+
+      await compileFromKernel(result.rootLibraryUri, result.libraries);
     }
   }
 
@@ -303,7 +293,7 @@
     return resolutionEnqueuer;
   }
 
-  JClosedWorld computeClosedWorld(LoadedLibraries loadedLibraries) {
+  JClosedWorld computeClosedWorld(Uri rootLibraryUri, Iterable<Uri> libraries) {
     ResolutionEnqueuer resolutionEnqueuer = startResolution();
     for (LibraryEntity library
         in frontendStrategy.elementEnvironment.libraries) {
@@ -321,7 +311,7 @@
     // compile-time constants that are metadata.  This means adding
     // something to the resolution queue.  So we cannot wait with
     // this until after the resolution queue is processed.
-    deferredLoadTask.beforeResolution(loadedLibraries);
+    deferredLoadTask.beforeResolution(rootLibraryUri, libraries);
     impactStrategy = backend.createImpactStrategy(
         supportDeferredLoad: deferredLoadTask.isProgramSplit,
         supportDumpInfo: options.dumpInfo);
@@ -395,10 +385,9 @@
     checkQueue(codegenEnqueuer);
   }
 
-  /// Performs the compilation when all libraries have been loaded.
-  void compileLoadedLibraries(LoadedLibraries loadedLibraries) {
-    selfTask.measureSubtask("Compiler.compileLoadedLibraries", () {
-      JClosedWorld closedWorld = computeClosedWorld(loadedLibraries);
+  void compileFromKernel(Uri rootLibraryUri, Iterable<Uri> libraries) {
+    selfTask.measureSubtask("Compiler.compileFromKernel", () {
+      JClosedWorld closedWorld = computeClosedWorld(rootLibraryUri, libraries);
       if (closedWorld != null) {
         GlobalTypeInferenceResults globalInferenceResults =
             performGlobalTypeInference(closedWorld);
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 7468875..b97806b 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -408,6 +408,7 @@
 
     new OptionHandler(Flags.experimentLocalNames, passThrough),
     new OptionHandler(Flags.experimentStartupFunctions, passThrough),
+    new OptionHandler(Flags.experimentCallInstrumentation, passThrough),
 
     // The following three options must come last.
     new OptionHandler('-D.+=.*', addInEnvironment),
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index a7e2e97..d1cc893 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -20,7 +20,6 @@
 import 'elements/types.dart';
 import 'elements/entities.dart';
 import 'kernel/kelements.dart' show KLocalFunction;
-import 'library_loader.dart';
 import 'serialization/serialization.dart';
 import 'options.dart';
 import 'universe/use.dart';
@@ -785,15 +784,15 @@
   /// Frees up strategy-specific temporary data.
   void cleanup() {}
 
-  void beforeResolution(LoadedLibraries loadedLibraries) {
-    for (Uri uri in loadedLibraries.libraries) {
+  void beforeResolution(Uri rootLibraryUri, Iterable<Uri> libraries) {
+    for (Uri uri in libraries) {
       LibraryEntity library = elementEnvironment.lookupLibrary(uri);
       reporter.withCurrentElement(library, () {
         checkForDeferredErrorCases(library);
         for (ImportEntity import in elementEnvironment.getImports(library)) {
           if (import.isDeferred) {
-            _deferredImportDescriptions[import] = new ImportDescription(
-                import, library, loadedLibraries.rootLibraryUri);
+            _deferredImportDescriptions[import] =
+                new ImportDescription(import, library, rootLibraryUri);
             isProgramSplit = true;
           }
         }
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index f9f6392..7c14077 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -113,14 +113,6 @@
       _globalInferenceResults.resultOfParameter(e);
 
   FieldInfo visitField(FieldEntity field, {ClassEntity containingClass}) {
-    var isInInstantiatedClass = false;
-    if (containingClass != null) {
-      isInInstantiatedClass =
-          closedWorld.classHierarchy.isInstantiated(containingClass);
-    }
-    if (!isInInstantiatedClass && !_hasBeenResolved(field)) {
-      return null;
-    }
     AbstractValue inferredType = _resultOfMember(field).type;
     // If a field has an empty inferred type it is never used.
     if (inferredType == null ||
@@ -147,7 +139,7 @@
           codegenWorldBuilder.getConstantFieldInitializer(field)];
     }
 
-    if (JavaScriptBackend.TRACE_METHOD == 'post') {
+    if (compiler.options.experimentCallInstrumentation) {
       // We use field.hashCode because it is globally unique and it is
       // available while we are doing codegen.
       info.coverageId = '${field.hashCode}';
@@ -160,12 +152,6 @@
     return info;
   }
 
-  bool _hasBeenResolved(MemberEntity entity) {
-    return compiler.globalInference.typesInferrerInternal.inferrer.types
-        .memberTypeInformations
-        .containsKey(entity);
-  }
-
   ClassInfo visitClass(ClassEntity clazz) {
     // Omit class if it is not needed.
     ClassInfo classInfo = new ClassInfo(
@@ -312,7 +298,7 @@
     int closureSize = _addClosureInfo(info, function);
     size += closureSize;
 
-    if (JavaScriptBackend.TRACE_METHOD == 'post') {
+    if (compiler.options.experimentCallInstrumentation) {
       // We use function.hashCode because it is globally unique and it is
       // available while we are doing codegen.
       info.coverageId = '${function.hashCode}';
@@ -556,9 +542,10 @@
       compiler.outputProvider.createOutputSink(
           compiler.options.outputUri.pathSegments.last,
           'info.json',
-          OutputType.info)
+          OutputType.dumpInfo)
         ..add(jsonBuffer.toString())
         ..close();
+      BasicInfo.resetIds();
     });
   }
 
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 3743e66..1508076 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -18,7 +18,7 @@
 import 'js_backend/native_data.dart';
 import 'js_backend/no_such_method_registry.dart';
 import 'js_backend/runtime_types.dart';
-import 'library_loader.dart';
+import 'kernel/loader.dart';
 import 'native/enqueue.dart' show NativeResolutionEnqueuer;
 import 'native/resolver.dart';
 import 'universe/class_hierarchy.dart';
@@ -30,7 +30,7 @@
 /// the resolved element model.
 abstract class FrontendStrategy {
   /// Registers a set of loaded libraries with this strategy.
-  void registerLoadedLibraries(LoadedLibraries loadedLibraries);
+  void registerLoadedLibraries(KernelResult result);
 
   /// Returns the [ElementEnvironment] for the element model used in this
   /// strategy.
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 7c2d111..3009a68 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -49,6 +49,7 @@
   final bool _inGenerativeConstructor;
 
   LocalsHandler _locals;
+  FieldInitializationScope _fieldScope;
   final SideEffectsBuilder _sideEffectsBuilder;
   final Map<JumpTarget, List<LocalsHandler>> _breaksFor =
       <JumpTarget, List<LocalsHandler>>{};
@@ -70,7 +71,9 @@
 
   KernelTypeGraphBuilder(this._options, this._closedWorld, this._inferrer,
       this._analyzedMember, this._analyzedNode, this._localsMap,
-      [this._locals, Map<Local, FieldEntity> capturedAndBoxed])
+      [this._locals,
+      this._fieldScope,
+      Map<Local, FieldEntity> capturedAndBoxed])
       : this._types = _inferrer.types,
         this._memberData = _inferrer.dataOfMember(_analyzedMember),
         // TODO(johnniwinther): Should side effects also be tracked for field
@@ -85,9 +88,9 @@
             : <Local, FieldEntity>{} {
     if (_locals != null) return;
 
-    FieldInitializationScope fieldScope =
+    _fieldScope =
         _inGenerativeConstructor ? new FieldInitializationScope() : null;
-    _locals = new LocalsHandler(_analyzedNode, fieldScope);
+    _locals = new LocalsHandler(_analyzedNode);
   }
 
   JsToElementMap get _elementMap => _closedWorld.elementMap;
@@ -99,12 +102,12 @@
   bool get inLoop => _loopLevel > 0;
 
   bool get _isThisExposed {
-    return _inGenerativeConstructor ? _locals.fieldScope.isThisExposed : true;
+    return _inGenerativeConstructor ? _fieldScope.isThisExposed : true;
   }
 
   void _markThisAsExposed() {
     if (_inGenerativeConstructor) {
-      _locals.fieldScope.isThisExposed = true;
+      _fieldScope.isThisExposed = true;
     }
   }
 
@@ -141,7 +144,7 @@
           if (!selector.isSetter &&
               _isInClassOrSubclass(field) &&
               field.isAssignable &&
-              _locals.fieldScope.readField(field) == null &&
+              _fieldScope.readField(field) == null &&
               getFieldInitializer(_elementMap, field) == null) {
             // If the field is being used before this constructor
             // actually had a chance to initialize it, say it can be
@@ -198,7 +201,7 @@
 
   void initializationIsIndefinite() {
     if (_inGenerativeConstructor) {
-      _locals.fieldScope.isIndefinite = true;
+      _fieldScope.isIndefinite = true;
     }
   }
 
@@ -257,7 +260,7 @@
       _elementMap.elementEnvironment.forEachLocalClassMember(cls,
           (MemberEntity member) {
         if (member.isField && member.isInstanceMember && member.isAssignable) {
-          TypeInformation type = _locals.fieldScope.readField(member);
+          TypeInformation type = _fieldScope.readField(member);
           MemberDefinition definition = _elementMap.getMemberDefinition(member);
           assert(definition.kind == MemberKind.regular);
           ir.Field node = definition.node;
@@ -291,7 +294,7 @@
   visitFieldInitializer(ir.FieldInitializer node) {
     TypeInformation rhsType = visit(node.value);
     FieldEntity field = _elementMap.getField(node.field);
-    _locals.updateField(field, rhsType);
+    _fieldScope.updateField(field, rhsType);
     _inferrer.recordTypeOfField(field, rhsType);
     return null;
   }
@@ -455,17 +458,26 @@
     List<IsCheck> negativeTests = <IsCheck>[];
     bool simpleCondition =
         handleCondition(node.condition, positiveTests, negativeTests);
-    LocalsHandler saved = _locals;
-    _locals = new LocalsHandler.from(_locals, node);
-    _updateIsChecks(positiveTests, negativeTests);
+    LocalsHandler localsBefore = _locals;
+    FieldInitializationScope fieldScopeBefore = _fieldScope;
 
-    LocalsHandler thenLocals = _locals;
-    _locals = new LocalsHandler.from(saved, node);
+    _locals = new LocalsHandler.from(localsBefore, node);
+    _updateIsChecks(positiveTests, negativeTests);
+    LocalsHandler localsAfterCondition = _locals;
+    FieldInitializationScope fieldScopeAfterThen = _fieldScope;
+
+    _locals = new LocalsHandler.from(localsBefore, node);
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
     visit(node.message);
-    _locals.seenReturnOrThrow = true;
-    saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
-    _locals = saved;
+
+    LocalsHandler localsAfterMessage = _locals;
+    FieldInitializationScope fieldScopeAfterMessage = _fieldScope;
+    localsAfterMessage.seenReturnOrThrow = true;
+    _locals = localsBefore.mergeDiamondFlow(
+        _inferrer, localsAfterCondition, localsAfterMessage);
+    _fieldScope = fieldScopeBefore?.mergeDiamondFlow(
+        _inferrer, fieldScopeAfterThen, fieldScopeAfterMessage);
     return null;
   }
 
@@ -525,18 +537,24 @@
       do {
         changed = false;
         for (ir.SwitchCase switchCase in node.cases) {
-          LocalsHandler saved = _locals;
-          _locals = new LocalsHandler.from(_locals, switchCase);
+          LocalsHandler localsBeforeCase = _locals;
+          FieldInitializationScope fieldScopeBeforeCase = _fieldScope;
+          _locals = new LocalsHandler.from(localsBeforeCase, switchCase);
+          _fieldScope = new FieldInitializationScope.from(fieldScopeBeforeCase);
           visit(switchCase);
-          changed = saved.mergeAll(_inferrer, [_locals]) || changed;
-          _locals = saved;
+          LocalsHandler localsAfterCase = _locals;
+          changed = localsBeforeCase.mergeAll(_inferrer, [localsAfterCase]) ||
+              changed;
+          _locals = localsBeforeCase;
+          _fieldScope = fieldScopeBeforeCase;
         }
       } while (changed);
       _locals.endLoop(_inferrer, node);
 
       continueTargets.forEach(_clearBreaksAndContinues);
     } else {
-      LocalsHandler saved = _locals;
+      LocalsHandler localsBeforeCase = _locals;
+      FieldInitializationScope fieldScopeBeforeCase = _fieldScope;
       List<LocalsHandler> localsToMerge = <LocalsHandler>[];
       bool hasDefaultCase = false;
 
@@ -544,13 +562,14 @@
         if (switchCase.isDefault) {
           hasDefaultCase = true;
         }
-        _locals = new LocalsHandler.from(saved, switchCase);
+        _locals = new LocalsHandler.from(localsBeforeCase, switchCase);
         visit(switchCase);
         localsToMerge.add(_locals);
       }
-      saved.mergeAfterBreaks(_inferrer, localsToMerge,
+      localsBeforeCase.mergeAfterBreaks(_inferrer, localsToMerge,
           keepOwnLocals: !hasDefaultCase);
-      _locals = saved;
+      _locals = localsBeforeCase;
+      _fieldScope = fieldScopeBeforeCase;
     }
     _clearBreaksAndContinues(jumpTarget);
     return null;
@@ -1012,22 +1031,24 @@
   TypeInformation handleLoop(ir.Node node, JumpTarget target, void logic()) {
     _loopLevel++;
     bool changed = false;
-    LocalsHandler saved = _locals;
-    saved.startLoop(_inferrer, node);
+    LocalsHandler localsBefore = _locals;
+    FieldInitializationScope fieldScopeBefore = _fieldScope;
+    localsBefore.startLoop(_inferrer, node);
     do {
       // Setup (and clear in case of multiple iterations of the loop)
       // the lists of breaks and continues seen in the loop.
       _setupBreaksAndContinues(target);
-      _locals = new LocalsHandler.from(saved, node);
+      _locals = new LocalsHandler.from(localsBefore, node);
+      _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
       logic();
-      changed = saved.mergeAll(_inferrer, _getLoopBackEdges(target));
+      changed = localsBefore.mergeAll(_inferrer, _getLoopBackEdges(target));
     } while (changed);
     _loopLevel--;
-    saved.endLoop(_inferrer, node);
+    localsBefore.endLoop(_inferrer, node);
     bool keepOwnLocals = node is! ir.DoStatement;
-    saved.mergeAfterBreaks(_inferrer, _getBreaks(target),
+    _locals = localsBefore.mergeAfterBreaks(_inferrer, _getBreaks(target),
         keepOwnLocals: keepOwnLocals);
-    _locals = saved;
+    _fieldScope = fieldScopeBefore;
     _clearBreaksAndContinues(target);
     return null;
   }
@@ -1293,7 +1314,7 @@
           MemberEntity single = targets.first;
           if (single.isField) {
             FieldEntity field = single;
-            _locals.updateField(field, rhsType);
+            _fieldScope.updateField(field, rhsType);
           }
         }
       }
@@ -1378,18 +1399,28 @@
     List<IsCheck> negativeTests = <IsCheck>[];
     bool simpleCondition =
         handleCondition(node.condition, positiveTests, negativeTests);
-    LocalsHandler saved = _locals;
-    _locals = new LocalsHandler.from(_locals, node);
+    LocalsHandler localsBefore = _locals;
+    FieldInitializationScope fieldScopeBefore = _fieldScope;
+    _locals = new LocalsHandler.from(localsBefore, node);
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     _updateIsChecks(positiveTests, negativeTests);
     visit(node.then);
-    LocalsHandler thenLocals = _locals;
-    _locals = new LocalsHandler.from(saved, node);
+
+    LocalsHandler localsAfterThen = _locals;
+    FieldInitializationScope fieldScopeAfterThen = _fieldScope;
+    _locals = new LocalsHandler.from(localsBefore, node);
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     if (simpleCondition) {
       _updateIsChecks(negativeTests, positiveTests);
     }
     visit(node.otherwise);
-    saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
-    _locals = saved;
+    LocalsHandler localsAfterElse = _locals;
+    FieldInitializationScope fieldScopeAfterElse = _fieldScope;
+
+    _locals = localsBefore.mergeDiamondFlow(
+        _inferrer, localsAfterThen, localsAfterElse);
+    _fieldScope = fieldScopeBefore?.mergeDiamondFlow(
+        _inferrer, fieldScopeAfterThen, fieldScopeAfterElse);
     return null;
   }
 
@@ -1425,9 +1456,12 @@
         _negativeIsChecks = <IsCheck>[];
       }
       visit(node.left, conditionContext: _accumulateIsChecks);
-      LocalsHandler saved = _locals;
-      _locals = new LocalsHandler.from(_locals, node);
+      LocalsHandler localsBefore = _locals;
+      FieldInitializationScope fieldScopeBefore = _fieldScope;
+      _locals = new LocalsHandler.from(localsBefore, node);
+      _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
       _updateIsChecks(_positiveIsChecks, _negativeIsChecks);
+
       LocalsHandler narrowed;
       if (oldAccumulateIsChecks) {
         narrowed = new LocalsHandler.topLevelCopyOf(_locals);
@@ -1439,14 +1473,18 @@
       visit(node.right, conditionContext: _accumulateIsChecks);
       if (oldAccumulateIsChecks) {
         bool invalidatedInRightHandSide(IsCheck check) {
-          return narrowed.locals[check.local] != _locals.locals[check.local];
+          TypeInformation narrowedType =
+              narrowed.use(_inferrer, _capturedAndBoxed, check.local);
+          TypeInformation currentType =
+              _locals.use(_inferrer, _capturedAndBoxed, check.local);
+          return narrowedType != currentType;
         }
 
         _positiveIsChecks.removeWhere(invalidatedInRightHandSide);
         _negativeIsChecks.removeWhere(invalidatedInRightHandSide);
       }
-      saved.mergeDiamondFlow(_inferrer, _locals, null);
-      _locals = saved;
+      _locals = localsBefore.mergeFlow(_inferrer, _locals);
+      _fieldScope = fieldScopeBefore;
       return _types.boolType;
     } else if (node.operator == '||') {
       _conditionIsSimple = false;
@@ -1454,14 +1492,16 @@
       List<IsCheck> negativeIsChecks = <IsCheck>[];
       bool isSimple =
           handleCondition(node.left, positiveIsChecks, negativeIsChecks);
-      LocalsHandler saved = _locals;
+      LocalsHandler localsBefore = _locals;
+      FieldInitializationScope fieldScopeBefore = _fieldScope;
       _locals = new LocalsHandler.from(_locals, node);
+      _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
       if (isSimple) {
         _updateIsChecks(negativeIsChecks, positiveIsChecks);
       }
       visit(node.right, conditionContext: false);
-      saved.mergeDiamondFlow(_inferrer, _locals, null);
-      _locals = saved;
+      _locals = localsBefore.mergeFlow(_inferrer, _locals);
+      _fieldScope = fieldScopeBefore;
       return _types.boolType;
     }
     failedAt(CURRENT_ELEMENT_SPANNABLE,
@@ -1475,16 +1515,24 @@
     List<IsCheck> negativeTests = <IsCheck>[];
     bool simpleCondition =
         handleCondition(node.condition, positiveTests, negativeTests);
-    LocalsHandler saved = _locals;
-    _locals = new LocalsHandler.from(_locals, node);
+    LocalsHandler localsBefore = _locals;
+    _locals = new LocalsHandler.from(localsBefore, node);
+    FieldInitializationScope fieldScopeBefore = _fieldScope;
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     _updateIsChecks(positiveTests, negativeTests);
     TypeInformation firstType = visit(node.then);
-    LocalsHandler thenLocals = _locals;
-    _locals = new LocalsHandler.from(saved, node);
+    LocalsHandler localsAfterThen = _locals;
+    FieldInitializationScope fieldScopeAfterThen = _fieldScope;
+    _locals = new LocalsHandler.from(localsBefore, node);
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
     TypeInformation secondType = visit(node.otherwise);
-    saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
-    _locals = saved;
+    LocalsHandler localsAfterElse = _locals;
+    FieldInitializationScope fieldScopeAfterElse = _fieldScope;
+    _locals = localsBefore.mergeDiamondFlow(
+        _inferrer, localsAfterThen, localsAfterElse);
+    _fieldScope = fieldScopeBefore?.mergeDiamondFlow(
+        _inferrer, fieldScopeAfterThen, fieldScopeAfterElse);
     return _types.allocateDiamondPhi(firstType, secondType);
   }
 
@@ -1508,9 +1556,12 @@
         if (variable == info.thisLocal) {
           _inferrer.recordTypeOfField(field, thisType);
         }
+        TypeInformation localType =
+            _locals.use(_inferrer, _capturedAndBoxed, variable);
         // The type is null for type parameters.
-        if (_locals.locals[variable] == null) return;
-        _inferrer.recordTypeOfField(field, _locals.locals[variable]);
+        if (localType != null) {
+          _inferrer.recordTypeOfField(field, localType);
+        }
       }
       _capturedVariables.add(variable);
     });
@@ -1531,6 +1582,8 @@
     // method, like for example the types of local variables.
     LocalsHandler closureLocals =
         new LocalsHandler.from(_locals, node, useOtherTryBlock: false);
+    FieldInitializationScope closureFieldScope =
+        new FieldInitializationScope.from(_fieldScope);
     KernelTypeGraphBuilder visitor = new KernelTypeGraphBuilder(
         _options,
         _closedWorld,
@@ -1539,6 +1592,7 @@
         functionNode,
         _localsMap,
         closureLocals,
+        closureFieldScope,
         _capturedAndBoxed);
     visitor.run();
     _inferrer.recordReturnType(info.callMethod, visitor._returnType);
@@ -1601,32 +1655,41 @@
 
   @override
   visitTryCatch(ir.TryCatch node) {
-    LocalsHandler saved = _locals;
-    _locals = new LocalsHandler.from(_locals, node,
+    LocalsHandler localsBefore = _locals;
+    FieldInitializationScope fieldScopeBefore = _fieldScope;
+    _locals = new LocalsHandler.from(localsBefore, node,
         isTry: true, useOtherTryBlock: false);
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     initializationIsIndefinite();
     visit(node.body);
-    saved.mergeDiamondFlow(_inferrer, _locals, null);
-    _locals = saved;
+    LocalsHandler localsAfterBody = _locals;
+    _locals = localsBefore.mergeFlow(_inferrer, localsAfterBody);
+    _fieldScope = fieldScopeBefore;
     for (ir.Catch catchBlock in node.catches) {
-      saved = _locals;
-      _locals = new LocalsHandler.from(_locals, catchBlock);
+      LocalsHandler localsBeforeCatch = _locals;
+      FieldInitializationScope fieldScopeBeforeCatch = _fieldScope;
+      _locals = new LocalsHandler.from(localsBeforeCatch, catchBlock);
+      _fieldScope = new FieldInitializationScope.from(fieldScopeBeforeCatch);
       visit(catchBlock);
-      saved.mergeDiamondFlow(_inferrer, _locals, null);
-      _locals = saved;
+      LocalsHandler localsAfterCatch = _locals;
+      _locals = localsBeforeCatch.mergeFlow(_inferrer, localsAfterCatch);
+      _fieldScope = fieldScopeBeforeCatch;
     }
     return null;
   }
 
   @override
   visitTryFinally(ir.TryFinally node) {
-    LocalsHandler saved = _locals;
-    _locals = new LocalsHandler.from(_locals, node,
+    LocalsHandler localsBefore = _locals;
+    FieldInitializationScope fieldScopeBefore = _fieldScope;
+    _locals = new LocalsHandler.from(localsBefore, node,
         isTry: true, useOtherTryBlock: false);
+    _fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
     initializationIsIndefinite();
     visit(node.body);
-    saved.mergeDiamondFlow(_inferrer, _locals, null);
-    _locals = saved;
+    LocalsHandler localsAfterBody = _locals;
+    _locals = localsBefore.mergeFlow(_inferrer, localsAfterBody);
+    _fieldScope = fieldScopeBefore;
     visit(node.finalizer);
     return null;
   }
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 835c405..896f862 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -19,7 +19,7 @@
 import '../js_model/element_map.dart';
 import '../js_model/js_world.dart';
 import '../js_model/locals.dart';
-import '../native/behavior.dart' as native;
+import '../native/behavior.dart';
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../types/abstract_value_domain.dart';
@@ -216,8 +216,8 @@
   TypeInformation typeOfParameter(Local element);
 
   /// Returns the type for [nativeBehavior]. See documentation on
-  /// [native.NativeBehavior].
-  TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior);
+  /// [NativeBehavior].
+  TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior);
 
   bool returnsListElementType(Selector selector, AbstractValue mask);
 
@@ -346,14 +346,14 @@
     }
   }
 
-  TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) {
+  TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior) {
     if (nativeBehavior == null) return types.dynamicType;
     List typesReturned = nativeBehavior.typesReturned;
     if (typesReturned.isEmpty) return types.dynamicType;
     TypeInformation returnType;
     for (var type in typesReturned) {
       TypeInformation mappedType;
-      if (type == native.SpecialType.JsObject) {
+      if (type == SpecialType.JsObject) {
         mappedType = types.nonNullExact(commonElements.objectClass);
       } else if (type == commonElements.stringType) {
         mappedType = types.stringType;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index a0ad009..2ebc446 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -144,15 +144,19 @@
     fields?.forEach(f);
   }
 
-  void mergeDiamondFlow(InferrerEngine inferrer,
+  /// Returns the join between [thenScope] and [elseScope] which models the
+  /// flow through either [thenScope] or [elseScope].
+  FieldInitializationScope mergeDiamondFlow(InferrerEngine inferrer,
       FieldInitializationScope thenScope, FieldInitializationScope elseScope) {
+    assert(elseScope != null);
+
     // Quick bailout check. If [isThisExposed] or [isIndefinite] is true, we
     // know the code following won'TypeInformation do anything.
-    if (isThisExposed) return;
-    if (isIndefinite) return;
+    if (isThisExposed) return this;
+    if (isIndefinite) return this;
 
     FieldInitializationScope otherScope =
-        (elseScope == null || elseScope.fields == null) ? this : elseScope;
+        elseScope.fields == null ? this : elseScope;
 
     thenScope.forEach((FieldEntity field, TypeInformation type) {
       TypeInformation otherType = otherScope.readField(field);
@@ -162,6 +166,7 @@
 
     isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed;
     isIndefinite = thenScope.isIndefinite || elseScope.isIndefinite;
+    return this;
   }
 }
 
@@ -245,9 +250,8 @@
  * Placeholder for inferred types of local variables.
  */
 class LocalsHandler {
-  final VariableScope locals;
-  final FieldInitializationScope fieldScope;
-  LocalsHandler tryBlock;
+  final VariableScope _locals;
+  LocalsHandler _tryBlock;
   bool seenReturnOrThrow = false;
   bool seenBreakOrContinue = false;
 
@@ -255,31 +259,28 @@
     return seenReturnOrThrow || seenBreakOrContinue;
   }
 
-  bool get inTryBlock => tryBlock != null;
+  bool get inTryBlock => _tryBlock != null;
 
-  LocalsHandler.internal(
-      ir.Node block, this.fieldScope, this.locals, this.tryBlock);
+  LocalsHandler.internal(ir.Node block, this._locals, this._tryBlock);
 
-  LocalsHandler(ir.Node block, [this.fieldScope])
-      : locals = new VariableScope(block, isTry: false),
-        tryBlock = null;
+  LocalsHandler(ir.Node block)
+      : _locals = new VariableScope(block, isTry: false),
+        _tryBlock = null;
 
   LocalsHandler.from(LocalsHandler other, ir.Node block,
       {bool isTry: false, bool useOtherTryBlock: true})
-      : locals = new VariableScope(block, isTry: isTry, parent: other.locals),
-        fieldScope = new FieldInitializationScope.from(other.fieldScope) {
-    tryBlock = useOtherTryBlock ? other.tryBlock : this;
+      : _locals =
+            new VariableScope(block, isTry: isTry, parent: other._locals) {
+    _tryBlock = useOtherTryBlock ? other._tryBlock : this;
   }
 
   LocalsHandler.deepCopyOf(LocalsHandler other)
-      : locals = new VariableScope.deepCopyOf(other.locals),
-        fieldScope = new FieldInitializationScope.from(other.fieldScope),
-        tryBlock = other.tryBlock;
+      : _locals = new VariableScope.deepCopyOf(other._locals),
+        _tryBlock = other._tryBlock;
 
   LocalsHandler.topLevelCopyOf(LocalsHandler other)
-      : locals = new VariableScope.topLevelCopyOf(other.locals),
-        fieldScope = new FieldInitializationScope.from(other.fieldScope),
-        tryBlock = other.tryBlock;
+      : _locals = new VariableScope.topLevelCopyOf(other._locals),
+        _tryBlock = other._tryBlock;
 
   TypeInformation use(InferrerEngine inferrer,
       Map<Local, FieldEntity> capturedAndBoxed, Local local) {
@@ -287,32 +288,14 @@
     if (field != null) {
       return inferrer.typeOfMember(field);
     } else {
-      return locals[local];
+      return _locals[local];
     }
   }
 
   void update(InferrerEngine inferrer, Map<Local, FieldEntity> capturedAndBoxed,
-      Local local, TypeInformation type, ir.Node node, DartType staticType,
-      {bool isSetIfNull: false}) {
+      Local local, TypeInformation type, ir.Node node, DartType staticType) {
     assert(type != null);
-    if (!inferrer.options.assignmentCheckPolicy.isIgnored) {
-      type = inferrer.types.narrowType(type, staticType);
-    }
-    updateLocal() {
-      TypeInformation currentType = locals[local];
-
-      if (isSetIfNull && currentType != null) {
-        // If-null assignments may return either the new or the original value
-        // narrowed to non-null.
-        type = inferrer.types.addPhiInput(
-            local,
-            inferrer.types.allocatePhi(
-                locals.block, local, inferrer.types.narrowNotNull(currentType),
-                isTry: locals.isTry),
-            type);
-      }
-      locals[local] = type;
-    }
+    type = inferrer.types.narrowType(type, staticType);
 
     FieldEntity field = capturedAndBoxed[local];
     if (field != null) {
@@ -323,94 +306,98 @@
       // potential types after we have left it. We update the parent
       // of the try block so that, at exit of the try block, we get
       // the right phi for it.
-      TypeInformation existing = tryBlock.locals.parent[local];
+      TypeInformation existing = _tryBlock._locals.parent[local];
       if (existing != null) {
         TypeInformation phiType = inferrer.types.allocatePhi(
-            tryBlock.locals.block, local, existing,
-            isTry: tryBlock.locals.isTry);
+            _tryBlock._locals.block, local, existing,
+            isTry: _tryBlock._locals.isTry);
         TypeInformation inputType =
             inferrer.types.addPhiInput(local, phiType, type);
-        tryBlock.locals.parent[local] = inputType;
+        _tryBlock._locals.parent[local] = inputType;
       }
       // Update the current handler unconditionally with the new
       // type.
-      updateLocal();
+      _locals[local] = type;
     } else {
-      updateLocal();
+      _locals[local] = type;
     }
   }
 
   void narrow(InferrerEngine inferrer, Map<Local, FieldEntity> capturedAndBoxed,
-      Local local, DartType type, ir.Node node,
-      {bool isSetIfNull: false}) {
+      Local local, DartType type, ir.Node node) {
     TypeInformation existing = use(inferrer, capturedAndBoxed, local);
     TypeInformation newType =
         inferrer.types.narrowType(existing, type, isNullable: false);
-    update(inferrer, capturedAndBoxed, local, newType, node, type,
-        isSetIfNull: isSetIfNull);
+    update(inferrer, capturedAndBoxed, local, newType, node, type);
   }
 
-  void mergeDiamondFlow(InferrerEngine inferrer, LocalsHandler thenBranch,
-      LocalsHandler elseBranch) {
-    if (fieldScope != null && elseBranch != null) {
-      fieldScope.mergeDiamondFlow(
-          inferrer, thenBranch.fieldScope, elseBranch.fieldScope);
-    }
-    seenReturnOrThrow = thenBranch.seenReturnOrThrow &&
-        elseBranch != null &&
-        elseBranch.seenReturnOrThrow;
-    seenBreakOrContinue = thenBranch.seenBreakOrContinue &&
-        elseBranch != null &&
-        elseBranch.seenBreakOrContinue;
-    if (aborts) return;
+  /// Returns the join between this locals handler and [other] which models the
+  /// flow through either this or [other].
+  LocalsHandler mergeFlow(InferrerEngine inferrer, LocalsHandler other) {
+    seenReturnOrThrow = false;
+    seenBreakOrContinue = false;
 
-    void mergeOneBranch(LocalsHandler other) {
-      other.locals.forEachOwnLocal((Local local, TypeInformation type) {
-        TypeInformation myType = locals[local];
+    if (other.aborts) {
+      return this;
+    } else {
+      other._locals.forEachOwnLocal((Local local, TypeInformation type) {
+        TypeInformation myType = _locals[local];
         if (myType == null) return; // Variable is only defined in [other].
         if (type == myType) return;
-        locals[local] = inferrer.types.allocateDiamondPhi(myType, type);
+        _locals[local] = inferrer.types.allocateDiamondPhi(myType, type);
       });
     }
+    return this;
+  }
+
+  /// Returns the join between [thenBranch] and [elseBranch] which models the
+  /// flow through either [thenBranch] or [elseBranch].
+  LocalsHandler mergeDiamondFlow(InferrerEngine inferrer,
+      LocalsHandler thenBranch, LocalsHandler elseBranch) {
+    assert(elseBranch != null);
+    seenReturnOrThrow =
+        thenBranch.seenReturnOrThrow && elseBranch.seenReturnOrThrow;
+    seenBreakOrContinue =
+        thenBranch.seenBreakOrContinue && elseBranch.seenBreakOrContinue;
+    if (aborts) return this;
 
     void inPlaceUpdateOneBranch(LocalsHandler other) {
-      other.locals.forEachOwnLocal((Local local, TypeInformation type) {
-        TypeInformation myType = locals[local];
+      other._locals.forEachOwnLocal((Local local, TypeInformation type) {
+        TypeInformation myType = _locals[local];
         if (myType == null) return; // Variable is only defined in [other].
         if (type == myType) return;
-        locals[local] = type;
+        _locals[local] = type;
       });
     }
 
     if (thenBranch.aborts) {
-      if (elseBranch == null) return;
       inPlaceUpdateOneBranch(elseBranch);
-    } else if (elseBranch == null) {
-      mergeOneBranch(thenBranch);
     } else if (elseBranch.aborts) {
       inPlaceUpdateOneBranch(thenBranch);
     } else {
       void mergeLocal(Local local) {
-        TypeInformation myType = locals[local];
+        TypeInformation myType = _locals[local];
         if (myType == null) return;
-        TypeInformation elseType = elseBranch.locals[local];
-        TypeInformation thenType = thenBranch.locals[local];
+        TypeInformation elseType = elseBranch._locals[local];
+        TypeInformation thenType = thenBranch._locals[local];
         if (thenType == elseType) {
-          locals[local] = thenType;
+          _locals[local] = thenType;
         } else {
-          locals[local] = inferrer.types.allocateDiamondPhi(thenType, elseType);
+          _locals[local] =
+              inferrer.types.allocateDiamondPhi(thenType, elseType);
         }
       }
 
-      thenBranch.locals.forEachOwnLocal((Local local, _) {
+      thenBranch._locals.forEachOwnLocal((Local local, _) {
         mergeLocal(local);
       });
-      elseBranch.locals.forEachOwnLocal((Local local, _) {
+      elseBranch._locals.forEachOwnLocal((Local local, _) {
         // Discard locals we already processed when iterating over
         // [thenBranch]'s locals.
-        if (!thenBranch.locals.updates(local)) mergeLocal(local);
+        if (!thenBranch._locals.updates(local)) mergeLocal(local);
       });
     }
+    return this;
   }
 
   /**
@@ -443,39 +430,41 @@
    * where [:this:] is the [LocalsHandler] for the paths through the
    * labeled statement that do not break out.
    */
-  void mergeAfterBreaks(InferrerEngine inferrer, List<LocalsHandler> handlers,
+  LocalsHandler mergeAfterBreaks(
+      InferrerEngine inferrer, List<LocalsHandler> handlers,
       {bool keepOwnLocals: true}) {
-    ir.Node level = locals.block;
+    ir.Node level = _locals.block;
     // Use a separate locals handler to perform the merge in, so that Phi
     // creation does not invalidate previous type knowledge while we might
     // still look it up.
     LocalsHandler merged =
-        new LocalsHandler.from(this, level, isTry: locals.isTry);
+        new LocalsHandler.from(this, level, isTry: _locals.isTry);
     Set<Local> seenLocals = new Setlet<Local>();
     bool allBranchesAbort = true;
     // Merge all other handlers.
     for (LocalsHandler handler in handlers) {
       allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow;
-      merged.mergeHandler(inferrer, handler, seenLocals);
+      merged._mergeHandler(inferrer, handler, seenLocals);
     }
     // If we want to keep own locals, we merge [seenLocals] from [this] into
     // [merged] to update the Phi nodes with original values.
     if (keepOwnLocals && !seenReturnOrThrow) {
       for (Local variable in seenLocals) {
-        TypeInformation originalType = locals[variable];
+        TypeInformation originalType = _locals[variable];
         if (originalType != null) {
-          merged.locals[variable] = inferrer.types
-              .addPhiInput(variable, merged.locals[variable], originalType);
+          merged._locals[variable] = inferrer.types
+              .addPhiInput(variable, merged._locals[variable], originalType);
         }
       }
     }
     // Clean up Phi nodes with single input and store back result into
     // actual locals handler.
-    merged.locals.forEachOwnLocal((Local variable, TypeInformation type) {
-      locals[variable] = inferrer.types.simplifyPhi(level, variable, type);
+    merged._locals.forEachOwnLocal((Local variable, TypeInformation type) {
+      _locals[variable] = inferrer.types.simplifyPhi(level, variable, type);
     });
     seenReturnOrThrow =
         allBranchesAbort && (!keepOwnLocals || seenReturnOrThrow);
+    return this;
   }
 
   /**
@@ -484,24 +473,24 @@
    * unless the local is already present in the set [seen]. This effectively
    * overwrites the current type knowledge in this handler.
    */
-  bool mergeHandler(InferrerEngine inferrer, LocalsHandler other,
+  bool _mergeHandler(InferrerEngine inferrer, LocalsHandler other,
       [Set<Local> seen]) {
     if (other.seenReturnOrThrow) return false;
     bool changed = false;
-    other.locals.forEachLocalUntilNode(locals.block, (local, otherType) {
-      TypeInformation myType = locals[local];
+    other._locals.forEachLocalUntilNode(_locals.block, (local, otherType) {
+      TypeInformation myType = _locals[local];
       if (myType == null) return;
       TypeInformation newType;
       if (seen != null && !seen.contains(local)) {
         newType = inferrer.types
-            .allocatePhi(locals.block, local, otherType, isTry: locals.isTry);
+            .allocatePhi(_locals.block, local, otherType, isTry: _locals.isTry);
         seen.add(local);
       } else {
         newType = inferrer.types.addPhiInput(local, myType, otherType);
       }
       if (newType != myType) {
         changed = true;
-        locals[local] = newType;
+        _locals[local] = newType;
       }
     });
     return changed;
@@ -515,39 +504,35 @@
     bool changed = false;
     assert(!seenReturnOrThrow);
     handlers.forEach((other) {
-      changed = mergeHandler(inferrer, other) || changed;
+      changed = _mergeHandler(inferrer, other) || changed;
     });
     return changed;
   }
 
   void startLoop(InferrerEngine inferrer, ir.Node loop) {
-    locals.forEachLocal((Local variable, TypeInformation type) {
+    _locals.forEachLocal((Local variable, TypeInformation type) {
       TypeInformation newType =
           inferrer.types.allocateLoopPhi(loop, variable, type, isTry: false);
       if (newType != type) {
-        locals[variable] = newType;
+        _locals[variable] = newType;
       }
     });
   }
 
   void endLoop(InferrerEngine inferrer, ir.Node loop) {
-    locals.forEachLocal((Local variable, TypeInformation type) {
+    _locals.forEachLocal((Local variable, TypeInformation type) {
       TypeInformation newType =
           inferrer.types.simplifyPhi(loop, variable, type);
       if (newType != type) {
-        locals[variable] = newType;
+        _locals[variable] = newType;
       }
     });
   }
 
-  void updateField(FieldEntity element, TypeInformation type) {
-    fieldScope.updateField(element, type);
-  }
-
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('LocalsHandler(');
-    sb.write('locals=$locals');
+    sb.write('locals=$_locals');
     sb.write(')');
     return sb.toString();
   }
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 669b6c6..78e4277 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -7,8 +7,23 @@
 import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/type_algebra.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
+import 'scope.dart';
 import 'static_type_base.dart';
 
+/// Enum values for how the target of a static type should be interpreted.
+enum ClassRelation {
+  /// The target is any subtype of the static type.
+  subtype,
+
+  /// The target is a subclass or mixin application of the static type.
+  ///
+  /// This corresponds to accessing a member through a this expression.
+  thisExpression,
+
+  /// The target is an exact instance of the static type.
+  exact,
+}
+
 /// Visitor that computes and caches the static type of expression while
 /// visiting the full tree at expression level.
 ///
@@ -26,6 +41,8 @@
 
   Map<ir.Expression, ir.DartType> get staticTypeCacheForTesting => _cache;
 
+  VariableScopeModel get variableScopeModel => null;
+
   @override
   ir.DartType defaultNode(ir.Node node) =>
       throw UnsupportedError('Unhandled node $node (${node.runtimeType})');
@@ -90,6 +107,10 @@
   ir.DartType _computePropertyGetType(
       ir.PropertyGet node, ir.DartType receiverType) {
     ir.Member interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget == null && receiverType is ir.InterfaceType) {
+      interfaceTarget = node.interfaceTarget = typeEnvironment.hierarchy
+          .getInterfaceMember(receiverType.classNode, node.name);
+    }
     if (interfaceTarget != null) {
       ir.Class superclass = interfaceTarget.enclosingClass;
       receiverType = getTypeAsInstanceOf(receiverType, superclass);
@@ -126,6 +147,10 @@
   ir.DartType visitPropertySet(ir.PropertySet node) {
     ir.DartType receiverType = visitNode(node.receiver);
     ir.DartType valueType = super.visitPropertySet(node);
+    if (node.interfaceTarget == null && receiverType is ir.InterfaceType) {
+      node.interfaceTarget = typeEnvironment.hierarchy
+          .getInterfaceMember(receiverType.classNode, node.name, setter: true);
+    }
     receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
     handlePropertySet(node, receiverType, valueType);
     return valueType;
@@ -219,6 +244,75 @@
     return receiverType;
   }
 
+  /// Returns `true` if [member] can be called with the structure of
+  /// [arguments].
+  bool _isApplicable(ir.Arguments arguments, ir.Member member) {
+    /// Returns `true` if [arguments] are applicable to the function type
+    /// structure.
+    bool isFunctionTypeApplicable(
+        int typeParameterCount,
+        int requiredParameterCount,
+        int positionalParameterCount,
+        Iterable<String> Function() getNamedParameters) {
+      if (arguments.types.isNotEmpty &&
+          arguments.types.length != typeParameterCount) {
+        return false;
+      }
+      if (arguments.positional.length < requiredParameterCount) {
+        return false;
+      }
+      if (arguments.positional.length > positionalParameterCount) {
+        return false;
+      }
+      Iterable<String> namedParameters = getNamedParameters();
+      if (arguments.named.length > namedParameters.length) {
+        return false;
+      }
+      if (arguments.named.isNotEmpty) {
+        for (ir.NamedExpression namedArguments in arguments.named) {
+          if (!namedParameters.contains(namedArguments.name)) {
+            return false;
+          }
+        }
+      }
+      return true;
+    }
+
+    /// Returns `true` if [arguments] are applicable to a value of the static
+    /// [type].
+    bool isTypeApplicable(ir.DartType type) {
+      if (type is ir.DynamicType) return true;
+      if (type == typeEnvironment.rawFunctionType) return true;
+      if (type is ir.FunctionType) {
+        return isFunctionTypeApplicable(
+            type.typeParameters.length,
+            type.requiredParameterCount,
+            type.positionalParameters.length,
+            () => type.namedParameters.map((p) => p.name).toSet());
+      }
+      return false;
+    }
+
+    if (member is ir.Procedure) {
+      if (member.kind == ir.ProcedureKind.Setter ||
+          member.kind == ir.ProcedureKind.Factory) {
+        return false;
+      } else if (member.kind == ir.ProcedureKind.Getter) {
+        return isTypeApplicable(member.getterType);
+      } else if (member.kind == ir.ProcedureKind.Method ||
+          member.kind == ir.ProcedureKind.Operator) {
+        return isFunctionTypeApplicable(
+            member.function.typeParameters.length,
+            member.function.requiredParameterCount,
+            member.function.positionalParameters.length,
+            () => member.function.namedParameters.map((p) => p.name).toSet());
+      }
+    } else if (member is ir.Field) {
+      return isTypeApplicable(member.type);
+    }
+    return false;
+  }
+
   /// Computes the result type of the method invocation [node] on a receiver of
   /// type [receiverType].
   ///
@@ -236,6 +330,13 @@
         node.arguments.named.isEmpty) {
       interfaceTarget = node.interfaceTarget = objectEquals;
     }
+    if (interfaceTarget == null && receiverType is ir.InterfaceType) {
+      ir.Member member = typeEnvironment.hierarchy
+          .getInterfaceMember(receiverType.classNode, node.name);
+      if (_isApplicable(node.arguments, member)) {
+        interfaceTarget = node.interfaceTarget = member;
+      }
+    }
     if (interfaceTarget != null) {
       if (isSpecialCasedBinaryOperator(interfaceTarget)) {
         ir.DartType argumentType = argumentTypes.positional[0];
@@ -247,8 +348,21 @@
       ir.DartType getterType = ir.Substitution.fromInterfaceType(receiverType)
           .substituteType(interfaceTarget.getterType);
       if (getterType is ir.FunctionType) {
+        List<ir.DartType> typeArguments = node.arguments.types;
+        if (interfaceTarget is ir.Procedure &&
+            interfaceTarget.function.typeParameters.isNotEmpty &&
+            typeArguments.isEmpty) {
+          // If this was a dynamic call the invocation does not have the
+          // inferred default type arguments so we need to create them here
+          // to perform a valid substitution.
+          ir.Substitution substitution =
+              ir.Substitution.fromInterfaceType(receiverType);
+          typeArguments = interfaceTarget.function.typeParameters
+              .map((t) => substitution.substituteType(t.defaultType))
+              .toList();
+        }
         return ir.Substitution.fromPairs(
-                getterType.typeParameters, node.arguments.types)
+                getterType.typeParameters, typeArguments)
             .substituteType(getterType.returnType);
       } else {
         return const ir.DynamicType();
@@ -817,7 +931,12 @@
 
   @override
   Null visitVariableDeclaration(ir.VariableDeclaration node) {
-    visitNode(node.initializer);
+    ir.DartType type = visitNode(node.initializer);
+    if (node.initializer != null &&
+        variableScopeModel != null &&
+        variableScopeModel.isEffectivelyFinal(node)) {
+      node.type = type;
+    }
     handleVariableDeclaration(node);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index 025f6d8..bd195e7 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -9,7 +9,7 @@
 import '../diagnostics/diagnostic_listener.dart';
 import '../diagnostics/messages.dart';
 import '../elements/entities.dart';
-import '../native/native.dart' as native;
+import '../kernel/dart2js_target.dart';
 import '../serialization/serialization.dart';
 
 /// Returns `true` if parameter and returns types should be trusted for
@@ -69,7 +69,7 @@
     FunctionEntity method = element;
     LibraryEntity library = element.library;
     bool platformAnnotationsAllowed = library.canonicalUri.scheme == 'dart' ||
-        native.maybeEnableNative(library.canonicalUri);
+        maybeEnableNative(library.canonicalUri);
 
     bool hasNoThrows = false;
     bool hasNoSideEffects = false;
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 9190a79..360666b 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -26,8 +26,8 @@
 import '../js/rewrite_async.dart';
 import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
 import '../js_emitter/sorter.dart' show Sorter;
-import '../library_loader.dart' show LoadedLibraries;
-import '../native/native.dart' as native;
+import '../kernel/dart2js_target.dart';
+import '../native/enqueue.dart';
 import '../ssa/ssa.dart' show SsaFunctionCompiler;
 import '../tracer.dart';
 import '../types/types.dart';
@@ -318,14 +318,6 @@
   final Map<MemberEntity, jsAst.Expression> generatedCode =
       <MemberEntity, jsAst.Expression>{};
 
-  /// If [true], the compiler will emit code that logs whenever a method is
-  /// called. When TRACE_METHOD is 'console' this will be logged
-  /// directly in the JavaScript console. When TRACE_METHOD is 'post' the
-  /// information will be sent to a server via a POST request.
-  static const String TRACE_METHOD = const String.fromEnvironment('traceCalls');
-  static const bool TRACE_CALLS =
-      TRACE_METHOD == 'post' || TRACE_METHOD == 'console';
-
   Namer _namer;
 
   Namer get namer {
@@ -388,8 +380,8 @@
 
   final SuperMemberData superMemberData = new SuperMemberData();
 
-  native.NativeResolutionEnqueuer _nativeResolutionEnqueuer;
-  native.NativeCodegenEnqueuer _nativeCodegenEnqueuer;
+  NativeResolutionEnqueuer _nativeResolutionEnqueuer;
+  NativeCodegenEnqueuer _nativeCodegenEnqueuer;
 
   Tracer tracer;
 
@@ -550,7 +542,7 @@
         compiler.frontendStrategy.createRuntimeTypesNeedBuilder();
     BackendImpacts impacts =
         new BackendImpacts(compiler.options, commonElements);
-    _nativeResolutionEnqueuer = new native.NativeResolutionEnqueuer(
+    _nativeResolutionEnqueuer = new NativeResolutionEnqueuer(
         compiler.options,
         elementEnvironment,
         commonElements,
@@ -633,7 +625,7 @@
         commonElements,
         elementEnvironment,
         closedWorld.nativeData);
-    _nativeCodegenEnqueuer = new native.NativeCodegenEnqueuer(
+    _nativeCodegenEnqueuer = new NativeCodegenEnqueuer(
         compiler.options,
         elementEnvironment,
         commonElements,
@@ -703,10 +695,10 @@
     return worldImpact;
   }
 
-  native.NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
+  NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
       _nativeResolutionEnqueuer;
 
-  native.NativeEnqueuer get nativeCodegenEnqueuer => _nativeCodegenEnqueuer;
+  NativeEnqueuer get nativeCodegenEnqueuer => _nativeCodegenEnqueuer;
 
   /**
    * Unit test hook that returns code of an element as a String.
@@ -750,7 +742,7 @@
   void setAnnotations(LibraryEntity library) {
     AnnotationProcessor processor =
         compiler.frontendStrategy.annotationProcesser;
-    if (native.maybeEnableNative(library.canonicalUri)) {
+    if (maybeEnableNative(library.canonicalUri)) {
       processor.extractNativeAnnotations(library);
     }
     processor.extractJsInteropAnnotations(library);
@@ -760,18 +752,6 @@
     }
   }
 
-  /// This method is called when all new libraries loaded through
-  /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
-  /// have been computed.
-  void onLibrariesLoaded(
-      CommonElements commonElements, LoadedLibraries loadedLibraries) {
-    if (loadedLibraries.containsLibrary(Uris.dart_core)) {
-      assert(loadedLibraries.containsLibrary(Uris.dart_core));
-      assert(loadedLibraries.containsLibrary(Uris.dart__interceptors));
-      assert(loadedLibraries.containsLibrary(Uris.dart__js_helper));
-    }
-  }
-
   /// Called when the compiler starts running the codegen enqueuer. The
   /// [WorldImpact] of enabled backend features is returned.
   WorldImpact onCodegenStart(JClosedWorld closedWorld,
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 282086e..73b9075 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -16,7 +16,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../native/enqueue.dart';
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../options.dart';
 import '../universe/feature.dart';
 import '../universe/use.dart'
@@ -286,7 +286,7 @@
       }
     }
 
-    for (native.NativeBehavior behavior in worldImpact.nativeData) {
+    for (NativeBehavior behavior in worldImpact.nativeData) {
       _nativeResolutionEnqueuer.registerNativeBehavior(
           transformed, behavior, worldImpact);
     }
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index aef92595..8f18ffb 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -18,7 +18,6 @@
 import '../universe/world_impact.dart'
     show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
 import 'allocator_analysis.dart';
-import 'backend.dart';
 import 'backend_impact.dart';
 import 'backend_usage.dart';
 import 'checked_mode_helpers.dart';
@@ -429,7 +428,7 @@
       _registerBackendImpact(impactBuilder, _impacts.getRuntimeTypeArgument);
     }
 
-    if (JavaScriptBackend.TRACE_CALLS) {
+    if (_options.experimentCallInstrumentation) {
       _registerBackendImpact(impactBuilder, _impacts.traceHelper);
     }
     _registerBackendImpact(impactBuilder, _impacts.assertUnreachable);
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 19fecf5..9da5325 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -1718,7 +1718,7 @@
     mapping.addAll(_closedWorld.outputUnitData
         .computeDeferredMap(compiler.options, _elementEnvironment));
     compiler.outputProvider.createOutputSink(
-        compiler.options.deferredMapUri.path, '', OutputType.info)
+        compiler.options.deferredMapUri.path, '', OutputType.deferredMap)
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
       ..close();
   }
diff --git a/pkg/compiler/lib/src/js_emitter/headers.dart b/pkg/compiler/lib/src/js_emitter/headers.dart
index ad9e783..9af8ea1 100644
--- a/pkg/compiler/lib/src/js_emitter/headers.dart
+++ b/pkg/compiler/lib/src/js_emitter/headers.dart
@@ -33,6 +33,11 @@
 //    successCallback. If it fails to do so, it should call errorCallback with
 //    an error.
 //
+// dartCallInstrumentation(id, qualifiedName):
+//    if this function is defined, it will be called at each entry of a
+//    method or constructor. Used only when compiling programs with
+//    --experiment-call-instrumentation.
+//
 // defaultPackagesBase:
 //    Override the location where `package:` uris are resolved from. By default
 //    they are resolved under "packages/" from the current window location.
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index a5e2a7c..5201c75 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
@@ -412,7 +412,7 @@
         omittedUnits:
             omittedFragments.map((fragemnt) => fragemnt.outputUnit).toSet()));
     compiler.outputProvider.createOutputSink(
-        compiler.options.deferredMapUri.path, '', OutputType.info)
+        compiler.options.deferredMapUri.path, '', OutputType.deferredMap)
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
       ..close();
   }
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 5d1215e..a342420 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -18,7 +18,7 @@
 import '../js_emitter/code_emitter_task.dart';
 import '../js_model/closure.dart' show JRecordField;
 import '../js_model/elements.dart' show JGeneratorBody;
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../serialization/serialization.dart';
 import '../ssa/type_builder.dart';
 import '../types/abstract_value_domain.dart';
@@ -92,16 +92,15 @@
   Name getName(ir.Name name);
 
   /// Computes the [native.NativeBehavior] for a call to the [JS] function.
-  native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
+  NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
 
   /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
   /// function.
-  native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
-      ir.StaticInvocation node);
+  NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node);
 
   /// Computes the [native.NativeBehavior] for a call to the
   /// [JS_EMBEDDED_GLOBAL] function.
-  native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
+  NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node);
 
   /// Returns the [js.Name] for the `JsGetName` [constant] value.
@@ -220,7 +219,7 @@
 
   /// Returns the returned type annotation in the [nativeBehavior].
   AbstractValue typeFromNativeBehavior(
-      native.NativeBehavior nativeBehavior, JClosedWorld closedWorld);
+      NativeBehavior nativeBehavior, JClosedWorld closedWorld);
 }
 
 /// Map from kernel IR nodes to local entities.
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index acd6671..07c24f3 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -41,7 +41,7 @@
 import '../kernel/element_map_impl.dart';
 import '../kernel/env.dart';
 import '../kernel/kelements.dart';
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../options.dart';
 import '../ordered_typeset.dart';
 import '../serialization/serialization.dart';
@@ -87,6 +87,7 @@
   static const String typedefDataTag = 'typedef-data';
   static const String memberDataTag = 'member-data';
   static const String typeVariableDataTag = 'type-variable-data';
+  static const String nestedClosuresTag = 'nested-closures';
 
   final CompilerOptions options;
   final DiagnosticReporter reporter;
@@ -333,7 +334,10 @@
       JClassEnv env = new JClassEnv.readFromDataSource(source);
       JClassData data = new JClassData.readFromDataSource(source);
       classMap[env.cls] = classes.registerByIndex(index, cls, data, env);
-      libraries.getEnv(cls.library).registerClass(cls.name, env);
+      if (cls is! JRecord && cls is! JClosureClass) {
+        // Synthesized classes are not part of the library environment.
+        libraries.getEnv(cls.library).registerClass(cls.name, env);
+      }
       assert(index == cls.classIndex);
     });
     source.end(classDataTag);
@@ -376,6 +380,12 @@
       assert(index == typeVariable.typeVariableIndex);
     });
     source.end(typeVariableDataTag);
+
+    source.begin(nestedClosuresTag);
+    _nestedClosureMap.addAll(
+        source.readMemberMap(() => source.readMembers<IndexedFunction>()));
+    source.end(nestedClosuresTag);
+
     source.end(tag);
   }
 
@@ -457,6 +467,10 @@
     });
     sink.end(typeVariableDataTag);
 
+    sink.begin(nestedClosuresTag);
+    sink.writeMemberMap(_nestedClosureMap, sink.writeMembers);
+    sink.end(nestedClosuresTag);
+
     sink.end(tag);
   }
 
@@ -1146,16 +1160,16 @@
   /// Looks up [typeName] for use in the spec-string of a `JS` call.
   // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
   // the `ForeignResolver`.
-  native.TypeLookup typeLookup({bool resolveAsRaw: true}) {
+  TypeLookup typeLookup({bool resolveAsRaw: true}) {
     return resolveAsRaw
         ? (_cachedTypeLookupRaw ??= _typeLookup(resolveAsRaw: true))
         : (_cachedTypeLookupFull ??= _typeLookup(resolveAsRaw: false));
   }
 
-  native.TypeLookup _cachedTypeLookupRaw;
-  native.TypeLookup _cachedTypeLookupFull;
+  TypeLookup _cachedTypeLookupRaw;
+  TypeLookup _cachedTypeLookupFull;
 
-  native.TypeLookup _typeLookup({bool resolveAsRaw: true}) {
+  TypeLookup _typeLookup({bool resolveAsRaw: true}) {
     bool cachedMayLookupInMain;
     bool mayLookupInMain() {
       var mainUri = elementEnvironment.mainLibrary.canonicalUri;
@@ -1220,28 +1234,28 @@
 
   /// Computes the [native.NativeBehavior] for a call to the [JS] function.
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
+  NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 2 ||
         node.arguments.named.isNotEmpty) {
       reporter.reportErrorMessage(
           CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS);
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     String specString = _getStringArgument(node, 0);
     if (specString == null) {
       reporter.reportErrorMessage(
           CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
 
     String codeString = _getStringArgument(node, 1);
     if (codeString == null) {
       reporter.reportErrorMessage(
           CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
 
-    return native.NativeBehavior.ofJsCall(
+    return NativeBehavior.ofJsCall(
         specString,
         codeString,
         typeLookup(resolveAsRaw: true),
@@ -1250,28 +1264,27 @@
         commonElements);
   }
 
-  /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
+  /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
   /// function.
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
-      ir.StaticInvocation node) {
+  NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     if (node.arguments.positional.length < 2) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     String specString = _getStringArgument(node, 0);
     if (specString == null) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
-    return native.NativeBehavior.ofJsBuiltinCall(
+    return NativeBehavior.ofJsBuiltinCall(
         specString,
         typeLookup(resolveAsRaw: true),
         CURRENT_ELEMENT_SPANNABLE,
@@ -1279,34 +1292,34 @@
         commonElements);
   }
 
-  /// Computes the [native.NativeBehavior] for a call to the
+  /// Computes the [NativeBehavior] for a call to the
   /// [JS_EMBEDDED_GLOBAL] function.
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
+  NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
       reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
           "JS embedded global expression has no type.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     if (node.arguments.positional.length < 2) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     if (node.arguments.positional.length > 2 ||
         node.arguments.named.isNotEmpty) {
       reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
           "JS embedded global has more than 2 arguments.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     String specString = _getStringArgument(node, 0);
     if (specString == null) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
-    return native.NativeBehavior.ofJsEmbeddedGlobalCall(
+    return NativeBehavior.ofJsEmbeddedGlobalCall(
         specString,
         typeLookup(resolveAsRaw: true),
         CURRENT_ELEMENT_SPANNABLE,
@@ -2397,8 +2410,8 @@
   }
 }
 
-/// [native.BehaviorBuilder] for kernel based elements.
-class JsBehaviorBuilder extends native.BehaviorBuilder {
+/// [BehaviorBuilder] for kernel based elements.
+class JsBehaviorBuilder extends BehaviorBuilder {
   final ElementEnvironment elementEnvironment;
   final CommonElements commonElements;
   final DiagnosticReporter reporter;
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 2187722..9ab34db 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -2,15 +2,44 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// TODO(johnniwinther): Add a test that ensure that this library doesn't depend
+// on the dart2js internals.
 library compiler.src.kernel.dart2js_target;
 
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/core_types.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/target/targets.dart';
+import 'invocation_mirror_constants.dart';
 
-import '../native/native.dart' show maybeEnableNative;
-import '../universe/selector.dart';
+const Iterable<String> _allowedDartSchemePaths = const <String>[
+  'async',
+  'html',
+  'html_common',
+  'indexed_db',
+  'js',
+  'js_util',
+  'svg',
+  '_native_typed_data',
+  'web_audio',
+  'web_gl',
+  'web_sql'
+];
+
+bool maybeEnableNative(Uri uri) {
+  bool allowedTestLibrary() {
+    String scriptName = uri.path;
+    return scriptName.contains('tests/compiler/dart2js_native') ||
+        scriptName.contains('tests/compiler/dart2js_extra');
+  }
+
+  bool allowedDartLibrary() {
+    if (uri.scheme != 'dart') return false;
+    return _allowedDartSchemePaths.contains(uri.path);
+  }
+
+  return allowedTestLibrary() || allowedDartLibrary();
+}
 
 /// A kernel [Target] to configure the Dart Front End for dart2js.
 class Dart2jsTarget extends Target {
@@ -59,13 +88,13 @@
       bool isSuper) {
     int kind;
     if (name.startsWith('get:')) {
-      kind = Selector.invocationMirrorGetterKind;
+      kind = invocationMirrorGetterKind;
       name = name.substring(4);
     } else if (name.startsWith('set:')) {
-      kind = Selector.invocationMirrorSetterKind;
+      kind = invocationMirrorSetterKind;
       name = name.substring(4);
     } else {
-      kind = Selector.invocationMirrorMethodKind;
+      kind = invocationMirrorMethodKind;
     }
     return new ir.StaticInvocation(
         coreTypes.index
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 5edfd7d..9533b15 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -13,7 +13,7 @@
 import '../js/js.dart' as js;
 import '../js_backend/namer.dart';
 import '../js_backend/native_data.dart';
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
 
@@ -86,17 +86,16 @@
   /// Returns the [Name] corresponding to [name].
   Name getName(ir.Name name);
 
-  /// Computes the [native.NativeBehavior] for a call to the [JS] function.
-  native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
+  /// Computes the [NativeBehavior] for a call to the [JS] function.
+  NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
 
-  /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
+  /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
   /// function.
-  native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
-      ir.StaticInvocation node);
+  NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node);
 
-  /// Computes the [native.NativeBehavior] for a call to the
+  /// Computes the [NativeBehavior] for a call to the
   /// [JS_EMBEDDED_GLOBAL] function.
-  native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
+  NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node);
 
   /// Returns the [js.Name] for the `JsGetName` [constant] value.
@@ -147,15 +146,15 @@
   bool isNativeClass(ir.Class node);
 
   /// Computes the native behavior for reading the native [field].
-  native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
+  NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
       {bool isJsInterop});
 
   /// Computes the native behavior for writing to the native [field].
-  native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field);
+  NativeBehavior getNativeBehaviorForFieldStore(ir.Field field);
 
   /// Computes the native behavior for calling the function or constructor
   /// [member].
-  native.NativeBehavior getNativeBehaviorForMethod(ir.Member member,
+  NativeBehavior getNativeBehaviorForMethod(ir.Member member,
       {bool isJsInterop});
 
   /// Compute the kind of foreign helper function called by [node], if any.
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 981f998..ec2f758 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -41,7 +41,8 @@
 import '../js_backend/native_data.dart';
 import '../js_backend/no_such_method_registry.dart';
 import '../js_model/locals.dart';
-import '../native/native.dart' as native;
+import '../kernel/dart2js_target.dart';
+import '../native/behavior.dart';
 import '../native/resolver.dart';
 import '../options.dart';
 import '../ordered_typeset.dart';
@@ -104,7 +105,7 @@
   final Map<ir.Field, IndexedField> fieldMap = {};
   final Map<ir.TreeNode, Local> localFunctionMap = {};
 
-  native.BehaviorBuilder _nativeBehaviorBuilder;
+  BehaviorBuilder _nativeBehaviorBuilder;
   FrontendStrategy _frontendStrategy;
 
   Map<KMember, Map<ir.TreeNode, ir.DartType>> staticTypeCacheForTesting;
@@ -817,18 +818,18 @@
   }
 
   /// Looks up [typeName] for use in the spec-string of a `JS` call.
-  // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
+  // TODO(johnniwinther): Use this in [NativeBehavior] instead of calling
   // the `ForeignResolver`.
-  native.TypeLookup typeLookup({bool resolveAsRaw: true}) {
+  TypeLookup typeLookup({bool resolveAsRaw: true}) {
     return resolveAsRaw
         ? (_cachedTypeLookupRaw ??= _typeLookup(resolveAsRaw: true))
         : (_cachedTypeLookupFull ??= _typeLookup(resolveAsRaw: false));
   }
 
-  native.TypeLookup _cachedTypeLookupRaw;
-  native.TypeLookup _cachedTypeLookupFull;
+  TypeLookup _cachedTypeLookupRaw;
+  TypeLookup _cachedTypeLookupFull;
 
-  native.TypeLookup _typeLookup({bool resolveAsRaw: true}) {
+  TypeLookup _typeLookup({bool resolveAsRaw: true}) {
     bool cachedMayLookupInMain;
     bool mayLookupInMain() {
       var mainUri = elementEnvironment.mainLibrary.canonicalUri;
@@ -891,30 +892,30 @@
     return node.arguments.positional[index].accept(new Stringifier());
   }
 
-  /// Computes the [native.NativeBehavior] for a call to the [JS] function.
+  /// Computes the [NativeBehavior] for a call to the [JS] function.
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
+  NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 2 ||
         node.arguments.named.isNotEmpty) {
       reporter.reportErrorMessage(
           CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS);
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     String specString = _getStringArgument(node, 0);
     if (specString == null) {
       reporter.reportErrorMessage(
           CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
 
     String codeString = _getStringArgument(node, 1);
     if (codeString == null) {
       reporter.reportErrorMessage(
           CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
 
-    return native.NativeBehavior.ofJsCall(
+    return NativeBehavior.ofJsCall(
         specString,
         codeString,
         typeLookup(resolveAsRaw: true),
@@ -923,28 +924,27 @@
         commonElements);
   }
 
-  /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
+  /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
   /// function.
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
-      ir.StaticInvocation node) {
+  NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     if (node.arguments.positional.length < 2) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     String specString = _getStringArgument(node, 0);
     if (specString == null) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
-    return native.NativeBehavior.ofJsBuiltinCall(
+    return NativeBehavior.ofJsBuiltinCall(
         specString,
         typeLookup(resolveAsRaw: true),
         CURRENT_ELEMENT_SPANNABLE,
@@ -952,34 +952,34 @@
         commonElements);
   }
 
-  /// Computes the [native.NativeBehavior] for a call to the
+  /// Computes the [NativeBehavior] for a call to the
   /// [JS_EMBEDDED_GLOBAL] function.
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
+  NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
       ir.StaticInvocation node) {
     if (node.arguments.positional.length < 1) {
       reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
           "JS embedded global expression has no type.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     if (node.arguments.positional.length < 2) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     if (node.arguments.positional.length > 2 ||
         node.arguments.named.isNotEmpty) {
       reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
           "JS embedded global has more than 2 arguments.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
     String specString = _getStringArgument(node, 0);
     if (specString == null) {
       reporter.internalError(
           CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
-      return new native.NativeBehavior();
+      return new NativeBehavior();
     }
-    return native.NativeBehavior.ofJsEmbeddedGlobalCall(
+    return NativeBehavior.ofJsEmbeddedGlobalCall(
         specString,
         typeLookup(resolveAsRaw: true),
         CURRENT_ELEMENT_SPANNABLE,
@@ -1332,14 +1332,15 @@
     env.addComponent(component);
   }
 
-  native.BehaviorBuilder get nativeBehaviorBuilder =>
+  BehaviorBuilder get nativeBehaviorBuilder =>
       _nativeBehaviorBuilder ??= new KernelBehaviorBuilder(elementEnvironment,
           commonElements, nativeBasicData, reporter, options);
 
-  ResolutionImpact computeWorldImpact(KMember member) {
+  ResolutionImpact computeWorldImpact(
+      KMember member, VariableScopeModel variableScopeModel) {
     ir.Member node = members.getData(member).node;
-    KernelImpactBuilder builder =
-        new KernelImpactBuilder(this, member, reporter, options);
+    KernelImpactBuilder builder = new KernelImpactBuilder(
+        this, member, reporter, options, variableScopeModel);
     node.accept(builder);
     if (retainDataForTesting) {
       staticTypeCacheForTesting ??= {};
@@ -1504,7 +1505,7 @@
 
   /// Computes the native behavior for reading the native [field].
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
+  NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
       {bool isJsInterop}) {
     DartType type = getDartType(field.type);
     List<ConstantValue> metadata = getMetadata(field.annotations);
@@ -1515,14 +1516,14 @@
 
   /// Computes the native behavior for writing to the native [field].
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
+  NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
     DartType type = getDartType(field.type);
     return nativeBehaviorBuilder.buildFieldStoreBehavior(type);
   }
 
   /// Computes the native behavior for calling [member].
   // TODO(johnniwinther): Cache this for later use.
-  native.NativeBehavior getNativeBehaviorForMethod(ir.Member member,
+  NativeBehavior getNativeBehaviorForMethod(ir.Member member,
       {bool isJsInterop}) {
     DartType type;
     if (member is ir.Procedure) {
@@ -1890,8 +1891,8 @@
   }
 }
 
-/// [native.BehaviorBuilder] for kernel based elements.
-class KernelBehaviorBuilder extends native.BehaviorBuilder {
+/// [BehaviorBuilder] for kernel based elements.
+class KernelBehaviorBuilder extends BehaviorBuilder {
   final ElementEnvironment elementEnvironment;
   final CommonElements commonElements;
   final DiagnosticReporter reporter;
@@ -1997,14 +1998,13 @@
   CommonElements get commonElements => elementMap.commonElements;
 
   @override
-  native.NativeBehavior computeNativeFieldStoreBehavior(
-      covariant KField field) {
+  NativeBehavior computeNativeFieldStoreBehavior(covariant KField field) {
     ir.Field node = elementMap.getMemberNode(field);
     return elementMap.getNativeBehaviorForFieldStore(node);
   }
 
   @override
-  native.NativeBehavior computeNativeFieldLoadBehavior(covariant KField field,
+  NativeBehavior computeNativeFieldLoadBehavior(covariant KField field,
       {bool isJsInterop}) {
     ir.Field node = elementMap.getMemberNode(field);
     return elementMap.getNativeBehaviorForFieldLoad(node,
@@ -2012,8 +2012,7 @@
   }
 
   @override
-  native.NativeBehavior computeNativeMethodBehavior(
-      covariant KFunction function,
+  NativeBehavior computeNativeMethodBehavior(covariant KFunction function,
       {bool isJsInterop}) {
     ir.Member node = elementMap.getMemberNode(function);
     return elementMap.getNativeBehaviorForMethod(node,
@@ -2022,7 +2021,7 @@
 
   @override
   bool isNativeMethod(covariant KFunction function) {
-    if (!native.maybeEnableNative(function.library.canonicalUri)) return false;
+    if (!maybeEnableNative(function.library.canonicalUri)) return false;
     ir.Member node = elementMap.getMemberNode(function);
     return node.annotations.any((ir.Expression expression) {
       return expression is ir.ConstructorInvocation &&
diff --git a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
new file mode 100644
index 0000000..246429e
--- /dev/null
+++ b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
@@ -0,0 +1,7 @@
+// 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.
+
+const int invocationMirrorMethodKind = 0;
+const int invocationMirrorGetterKind = 1;
+const int invocationMirrorSetterKind = 2;
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 09d6756..f6bcf24 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -14,6 +14,7 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/scope.dart';
 import '../ir/static_type.dart';
 import '../ir/util.dart';
 import '../js_backend/native_data.dart';
@@ -33,9 +34,10 @@
   final DiagnosticReporter reporter;
   final CompilerOptions _options;
   final MemberEntity currentMember;
+  final VariableScopeModel variableScopeModel;
 
-  KernelImpactBuilder(
-      this.elementMap, this.currentMember, this.reporter, this._options)
+  KernelImpactBuilder(this.elementMap, this.currentMember, this.reporter,
+      this._options, this.variableScopeModel)
       : this.impactBuilder =
             new ResolutionWorldImpactBuilder('${currentMember}'),
         super(elementMap.typeEnvironment);
@@ -505,7 +507,7 @@
       ir.DartType returnType) {
     Selector selector = elementMap.getSelector(node);
     List<DartType> typeArguments = _getTypeArguments(node.arguments);
-    var receiver = node.receiver;
+    ir.Expression receiver = node.receiver;
     if (receiver is ir.VariableGet &&
         receiver.variable.isFinal &&
         receiver.variable.parent is ir.FunctionDeclaration) {
@@ -521,6 +523,9 @@
       impactBuilder.registerDynamicUse(
           new ConstrainedDynamicUse(selector, null, typeArguments));
     } else {
+      ClassRelation relation = receiver is ir.ThisExpression
+          ? ClassRelation.thisExpression
+          : ClassRelation.subtype;
       DartType receiverDartType = elementMap.getDartType(receiverType);
 
       ir.Member interfaceTarget = node.interfaceTarget;
@@ -536,8 +541,8 @@
       } else {
         Object constraint;
         if (receiverDartType is InterfaceType) {
-          constraint = new StrongModeConstraint(
-              commonElements, _nativeBasicData, receiverDartType.element);
+          constraint = new StrongModeConstraint(commonElements,
+              _nativeBasicData, receiverDartType.element, relation);
         }
 
         if (interfaceTarget is ir.Field ||
@@ -573,8 +578,11 @@
     Object constraint;
     DartType receiverDartType = elementMap.getDartType(receiverType);
     if (receiverDartType is InterfaceType) {
+      ClassRelation relation = node.receiver is ir.ThisExpression
+          ? ClassRelation.thisExpression
+          : ClassRelation.subtype;
       constraint = new StrongModeConstraint(
-          commonElements, _nativeBasicData, receiverDartType.element);
+          commonElements, _nativeBasicData, receiverDartType.element, relation);
     }
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
         new Selector.getter(elementMap.getName(node.name)),
@@ -612,8 +620,11 @@
     Object constraint;
     DartType receiverDartType = elementMap.getDartType(receiverType);
     if (receiverDartType is InterfaceType) {
+      ClassRelation relation = node.receiver is ir.ThisExpression
+          ? ClassRelation.thisExpression
+          : ClassRelation.subtype;
       constraint = new StrongModeConstraint(
-          commonElements, _nativeBasicData, receiverDartType.element);
+          commonElements, _nativeBasicData, receiverDartType.element, relation);
     }
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
         new Selector.setter(elementMap.getName(node.name)),
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 8eb8e55..31c810f 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -25,7 +25,6 @@
 import '../js_backend/native_data.dart';
 import '../js_backend/no_such_method_registry.dart';
 import '../js_backend/runtime_types.dart';
-import '../library_loader.dart';
 import '../native/enqueue.dart' show NativeResolutionEnqueuer;
 import '../native/resolver.dart';
 import '../options.dart';
@@ -36,6 +35,7 @@
 import 'deferred_load.dart';
 import 'element_map.dart';
 import 'element_map_impl.dart';
+import 'loader.dart';
 
 /// Front end strategy that loads '.dill' files and builds a resolved element
 /// model from kernel IR nodes.
@@ -57,8 +57,8 @@
   }
 
   @override
-  void registerLoadedLibraries(LoadedLibraries loadedLibraries) {
-    _elementMap.addComponent(loadedLibraries.component);
+  void registerLoadedLibraries(KernelResult kernelResult) {
+    _elementMap.addComponent(kernelResult.component);
   }
 
   @override
@@ -204,7 +204,7 @@
   WorldImpact run() {
     return _compilerTask.measure(() {
       _nativeMemberResolver.resolveNativeMember(element);
-      _compilerTask.measureSubtask('closures', () {
+      ScopeModel scopeModel = _compilerTask.measureSubtask('closures', () {
         ScopeModel scopeModel = _elementMap.computeScopeModel(element);
         if (scopeModel?.closureScopeModel != null) {
           closureModels[element] = scopeModel.closureScopeModel;
@@ -212,7 +212,8 @@
         return scopeModel;
       });
       return _compilerTask.measureSubtask('worldImpact', () {
-        ResolutionImpact impact = _elementMap.computeWorldImpact(element);
+        ResolutionImpact impact = _elementMap.computeWorldImpact(
+            element, scopeModel?.variableScopeModel);
         WorldImpact worldImpact =
             _impactTransformer.transformResolutionImpact(impact);
         if (impactCache != null) {
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
index 563fc9c..af7cde7 100644
--- a/pkg/compiler/lib/src/kernel/kernel_world.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -16,7 +16,6 @@
 import '../js_backend/runtime_types.dart';
 import '../options.dart';
 import '../universe/class_hierarchy.dart';
-import '../universe/class_set.dart';
 import '../universe/resolution_world_builder.dart';
 import '../world.dart';
 
@@ -74,12 +73,9 @@
       this.processedMembers,
       this.mixinUses,
       this.typesImplementedBySubclasses,
-      Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
-      Map<ClassEntity, ClassSet> classSets,
+      this.classHierarchy,
       this.annotationsData})
-      : _implementedClasses = implementedClasses,
-        classHierarchy = new ClassHierarchyImpl(
-            commonElements, classHierarchyNodes, classSets) {
+      : _implementedClasses = implementedClasses {
     _rtiNeed = rtiNeedBuilder.computeRuntimeTypesNeed(
         resolutionWorldBuilder, this, options);
   }
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
similarity index 68%
rename from pkg/compiler/lib/src/library_loader.dart
rename to pkg/compiler/lib/src/kernel/loader.dart
index e9baa28..6abde20 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -14,21 +14,20 @@
 import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
 import 'package:kernel/target/targets.dart';
 
-import '../compiler_new.dart' as api;
-import 'kernel/front_end_adapter.dart';
-import 'kernel/dart2js_target.dart' show Dart2jsTarget;
+import '../../compiler_new.dart' as api;
+import '../common/tasks.dart' show CompilerTask, Measurer;
+import '../common.dart';
+import '../options.dart';
 
-import 'common/tasks.dart' show CompilerTask, Measurer;
-import 'common.dart';
-import 'options.dart';
+import 'front_end_adapter.dart';
+import 'dart2js_target.dart' show Dart2jsTarget;
 
-/// A loader that builds a kernel IR representation of the component.
+/// A task that produces the kernel IR representation of the application.
 ///
 /// It supports loading both .dart source files or pre-compiled .dill files.
-/// When given .dart source files, it invokes the shared frontend
-/// (`package:front_end`) to produce the corresponding kernel IR representation.
-// TODO(sigmund): move this class to a new file under src/kernel/.
-class LibraryLoaderTask extends CompilerTask {
+/// When given .dart source files, it invokes the common front-end (CFE)
+/// to produce the corresponding kernel IR representation.
+class KernelLoaderTask extends CompilerTask {
   final DiagnosticReporter _reporter;
 
   final api.CompilerInput _compilerInput;
@@ -44,15 +43,15 @@
   /// This is used for testing.
   bool forceSerialization = false;
 
-  LibraryLoaderTask(
+  KernelLoaderTask(
       this._options, this._compilerInput, this._reporter, Measurer measurer)
       : initializedCompilerState = _options.kernelInitializedCompilerState,
         super(measurer);
 
-  String get name => 'Library loader';
+  String get name => 'kernel loader';
 
   /// Loads an entire Kernel [Component] from a file on disk.
-  Future<LoadedLibraries> loadLibraries(Uri resolvedUri) {
+  Future<KernelResult> load(Uri resolvedUri) {
     return measure(() async {
       var isDill = resolvedUri.path.endsWith('.dill');
       ir.Component component;
@@ -85,12 +84,11 @@
         component = new ir.Component();
         new BinaryBuilder(data).readComponent(component);
       }
-      return _createLoadedLibraries(component);
+      return _toResult(component);
     });
   }
 
-  // Only visible for unit testing.
-  LoadedLibraries _createLoadedLibraries(ir.Component component) {
+  KernelResult _toResult(ir.Component component) {
     Uri rootLibraryUri = null;
     Iterable<ir.Library> libraries = component.libraries;
     if (component.mainMethod != null) {
@@ -119,38 +117,27 @@
 
       libraries = libraries.where(seen.contains);
     }
-    return new LoadedLibraries(component, rootLibraryUri,
+    return new KernelResult(component, rootLibraryUri,
         libraries.map((lib) => lib.importUri).toList());
   }
 }
 
-/// Information on the set libraries loaded as a result of a call to
-/// [LibraryLoader.loadLibrary].
-class LoadedLibraries {
-  final ir.Component _component;
-  final Uri _rootLibraryUri;
-  final List<Uri> _libraries;
+/// Result of invoking the CFE to produce the kernel IR.
+class KernelResult {
+  final ir.Component component;
 
-  LoadedLibraries(this._component, this._rootLibraryUri, this._libraries) {
+  /// The [Uri] of the root library containing main.
+  final Uri rootLibraryUri;
+
+  /// Returns the [Uri]s of all libraries that have been loaded that are
+  /// reachable from the [rootLibraryUri].
+  ///
+  /// Note that [component] may contain some libraries that are excluded here.
+  final Iterable<Uri> libraries;
+
+  KernelResult(this.component, this.rootLibraryUri, this.libraries) {
     assert(rootLibraryUri != null);
   }
 
-  /// Returns the root component for the loaded libraries.
-  ir.Component get component => _component;
-
-  /// The [Uri] of the root library.
-  Uri get rootLibraryUri => _rootLibraryUri;
-
-  /// Returns the [Uri]s of all libraries that have been loaded.
-  Iterable<Uri> get libraries => _libraries;
-
-  /// Returns `true` if a library with canonical [uri] was loaded in this bulk.
-  bool containsLibrary(Uri uri) {
-    return _libraries.contains(uri);
-  }
-
-  /// Applies all library [Uri]s in this bulk to [f].
-  void forEachLibrary(f(Uri Uri)) => _libraries.forEach(f);
-
-  String toString() => 'root=$_rootLibraryUri,libraries=${_libraries}';
+  String toString() => 'root=$rootLibraryUri,libraries=${libraries}';
 }
diff --git a/pkg/compiler/lib/src/native/native.dart b/pkg/compiler/lib/src/native/native.dart
deleted file mode 100644
index ae0ce99..0000000
--- a/pkg/compiler/lib/src/native/native.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library native;
-
-export 'behavior.dart';
-export 'enqueue.dart';
-export 'js.dart';
-
-const Iterable<String> _allowedDartSchemePaths = const <String>[
-  'async',
-  'html',
-  'html_common',
-  'indexed_db',
-  'js',
-  'js_util',
-  'svg',
-  '_native_typed_data',
-  'web_audio',
-  'web_gl',
-  'web_sql'
-];
-
-bool maybeEnableNative(Uri uri) {
-  bool allowedTestLibrary() {
-    String scriptName = uri.path;
-    return scriptName.contains('tests/compiler/dart2js_native') ||
-        scriptName.contains('tests/compiler/dart2js_extra');
-  }
-
-  bool allowedDartLibary() {
-    if (uri.scheme != 'dart') return false;
-    return _allowedDartSchemePaths.contains(uri.path);
-  }
-
-  return allowedTestLibrary() || allowedDartLibary();
-}
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index c7ab17f..808e242 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -71,7 +71,8 @@
   OutputSink createOutputSink(String name, String extension, OutputType type) {
     if (_outputProvider != null) {
       switch (type) {
-        case OutputType.info:
+        case OutputType.dumpInfo:
+        case OutputType.deferredMap:
           if (extension == '') {
             // Needed to make Pub generate the same output name.
             extension = 'deferred_map';
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 4513395..0c05a18 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -241,6 +241,12 @@
   /// Experimental part file function generation.
   bool experimentStartupFunctions = false;
 
+  /// Experimental instrumentation to investigate code bloat.
+  ///
+  /// If [true], the compiler will emit code that logs whenever a method is
+  /// called.
+  bool experimentCallInstrumentation = false;
+
   /// The path to the file that contains the profiled allocations.
   ///
   /// The file must contain the Map that was produced by using
@@ -298,6 +304,8 @@
       ..experimentLocalNames = _hasOption(options, Flags.experimentLocalNames)
       ..experimentStartupFunctions =
           _hasOption(options, Flags.experimentStartupFunctions)
+      ..experimentCallInstrumentation =
+          _hasOption(options, Flags.experimentCallInstrumentation)
       ..generateCodeWithCompileTimeErrors =
           _hasOption(options, Flags.generateCodeWithCompileTimeErrors)
       ..generateSourceMap = !_hasOption(options, Flags.noSourceMaps)
@@ -422,18 +430,13 @@
   /// Whether the type assertion should be emitted and checked.
   final bool isEmitted;
 
-  /// Whether the type assertion should be ignored.
-  final bool isIgnored;
-
-  const CheckPolicy(
-      {this.isTrusted: false, this.isEmitted: false, this.isIgnored: false});
+  const CheckPolicy({this.isTrusted: false, this.isEmitted: false});
 
   static const trusted = const CheckPolicy(isTrusted: true);
   static const checked = const CheckPolicy(isEmitted: true);
-  static const ignored = const CheckPolicy(isIgnored: true);
 
   String toString() => 'CheckPolicy(isTrusted=$isTrusted,'
-      'isEmitted=$isEmitted,isIgnored=$isIgnored)';
+      'isEmitted=$isEmitted)';
 }
 
 String _extractStringOption(
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 986b990..f6551af 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -352,7 +352,8 @@
       case OutputType.jsPart:
         uri = out.resolve('$name.$extension');
         break;
-      case OutputType.info:
+      case OutputType.dumpInfo:
+      case OutputType.deferredMap:
         if (name == '') {
           name = out.pathSegments.last;
         }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 25993e7..d9a0664 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -32,7 +32,9 @@
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../js_model/element_map.dart';
 import '../js_model/js_strategy.dart';
-import '../native/native.dart' as native;
+import '../kernel/invocation_mirror_constants.dart';
+import '../native/behavior.dart';
+import '../native/js.dart';
 import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart';
@@ -1326,7 +1328,6 @@
     if (functionNode != null) {
       _potentiallyAddFunctionParameterTypeChecks(functionNode, checks);
     }
-    _insertTraceCall(member);
     _insertCoverageCall(member);
   }
 
@@ -2485,7 +2486,7 @@
         js.Template code = js.js.parseForeignJS('#');
         push(new HForeignCode(code, abstractValueDomain.boolType,
             [localsHandler.readLocal(switchTarget)],
-            nativeBehavior: native.NativeBehavior.PURE));
+            nativeBehavior: NativeBehavior.PURE));
       }
 
       handleIf(
@@ -3395,7 +3396,7 @@
         lengthInput = conversion;
       }
       js.Template code = js.js.parseForeignJS('new Array(#)');
-      var behavior = new native.NativeBehavior();
+      var behavior = new NativeBehavior();
 
       var expectedType =
           _elementMap.getDartType(invocation.getStaticType(null));
@@ -3418,9 +3419,8 @@
       HForeignCode foreign = new HForeignCode(
           code, resultType, <HInstruction>[lengthInput],
           nativeBehavior: behavior,
-          throwBehavior: canThrow
-              ? native.NativeThrowBehavior.MAY
-              : native.NativeThrowBehavior.NEVER)
+          throwBehavior:
+              canThrow ? NativeThrowBehavior.MAY : NativeThrowBehavior.NEVER)
         ..sourceInformation = sourceInformation;
       push(foreign);
       // TODO(redemption): Global type analysis tracing may have determined that
@@ -3431,7 +3431,7 @@
         // We set the instruction as [canThrow] to avoid it being dead code.
         // We need a finer grained side effect.
         add(new HForeignCode(code, abstractValueDomain.nullType, [stack.last],
-            throwBehavior: native.NativeThrowBehavior.MAY));
+            throwBehavior: NativeThrowBehavior.MAY));
       }
     } else if (isGrowableListConstructorCall) {
       push(buildLiteralList(<HInstruction>[]));
@@ -3613,13 +3613,13 @@
     Name memberName = new Name(name, _currentFrame.member.library);
     Selector selector;
     switch (kindLiteral.value) {
-      case Selector.invocationMirrorGetterKind:
+      case invocationMirrorGetterKind:
         selector = new Selector.getter(memberName);
         break;
-      case Selector.invocationMirrorSetterKind:
+      case invocationMirrorSetterKind:
         selector = new Selector.setter(memberName);
         break;
-      case Selector.invocationMirrorMethodKind:
+      case invocationMirrorMethodKind:
         if (memberName == Names.INDEX_NAME) {
           selector = new Selector.index();
         } else if (memberName == Names.INDEX_SET_NAME) {
@@ -3812,7 +3812,7 @@
                     .staticFunctionAccess(_elementMap.getMethod(staticTarget))),
                 abstractValueDomain.dynamicType,
                 <HInstruction>[],
-                nativeBehavior: native.NativeBehavior.PURE,
+                nativeBehavior: NativeBehavior.PURE,
                 foreignFunction: _elementMap.getMethod(staticTarget)));
             return;
           }
@@ -3844,8 +3844,7 @@
     sideEffects.setAllSideEffects();
     push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"),
         abstractValueDomain.dynamicType, inputs,
-        nativeBehavior: native.NativeBehavior.CHANGES_OTHER,
-        effects: sideEffects));
+        nativeBehavior: NativeBehavior.CHANGES_OTHER, effects: sideEffects));
   }
 
   void handleForeignJsGetStaticState(ir.StaticInvocation invocation) {
@@ -3858,7 +3857,7 @@
 
     push(new HForeignCode(js.js.parseForeignJS(namer.staticStateHolder),
         abstractValueDomain.dynamicType, <HInstruction>[],
-        nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
+        nativeBehavior: NativeBehavior.DEPENDS_OTHER));
   }
 
   void handleForeignJsGetName(ir.StaticInvocation invocation) {
@@ -3900,7 +3899,7 @@
     js.Template expr = js.js.expressionTemplateYielding(
         emitter.generateEmbeddedGlobalAccess(globalName));
 
-    native.NativeBehavior nativeBehavior =
+    NativeBehavior nativeBehavior =
         _elementMap.getNativeBehaviorForJsEmbeddedGlobalCall(invocation);
     assert(
         nativeBehavior != null,
@@ -3947,7 +3946,7 @@
       inputs.add(pop());
     }
 
-    native.NativeBehavior nativeBehavior =
+    NativeBehavior nativeBehavior =
         _elementMap.getNativeBehaviorForJsBuiltinCall(invocation);
     assert(
         nativeBehavior != null,
@@ -4038,7 +4037,7 @@
       return;
     }
 
-    native.NativeBehavior nativeBehavior =
+    NativeBehavior nativeBehavior =
         _elementMap.getNativeBehaviorForJsCall(invocation);
     assert(
         nativeBehavior != null,
@@ -4063,7 +4062,7 @@
       return;
     }
 
-    if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) {
+    if (HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) {
       reporter.reportErrorMessage(
           _elementMap.getSpannable(targetElement, invocation),
           MessageKind.JS_PLACEHOLDER_CAPTURE);
@@ -4257,8 +4256,7 @@
       var codeTemplate =
           new js.Template(null, js.objectLiteral(parameterNameMap));
 
-      var nativeBehavior = new native.NativeBehavior()
-        ..codeTemplate = codeTemplate;
+      var nativeBehavior = new NativeBehavior()..codeTemplate = codeTemplate;
       if (options.trustJSInteropTypeAnnotations) {
         InterfaceType thisType = _elementMap.elementEnvironment
             .getThisType(constructor.enclosingClass);
@@ -4283,8 +4281,7 @@
     arguments = arguments.where((arg) => arg != null).toList();
     var inputs = <HInstruction>[target]..addAll(arguments);
 
-    var nativeBehavior = new native.NativeBehavior()
-      ..sideEffects.setAllSideEffects();
+    var nativeBehavior = new NativeBehavior()..sideEffects.setAllSideEffects();
 
     DartType type = element is ConstructorEntity
         ? _elementMap.elementEnvironment.getThisType(element.enclosingClass)
@@ -5377,7 +5374,6 @@
         _elementMap.elementEnvironment.getFunctionType(function).returnType;
     stack = <HInstruction>[];
 
-    _insertTraceCall(function);
     _insertCoverageCall(function);
   }
 
@@ -5521,35 +5517,20 @@
     return _allInlinedFunctionsCalledOnce && _isFunctionCalledOnce(element);
   }
 
-  void _insertTraceCall(MemberEntity element) {
-    if (JavaScriptBackend.TRACE_METHOD == 'console') {
-      if (element == commonElements.traceHelper) return;
-      n(e) => e == null ? '' : e.name;
-      String name = "${n(element.library)}:${n(element.enclosingClass)}."
-          "${n(element)}";
-      HConstant nameConstant = graph.addConstantString(name, closedWorld);
-      add(new HInvokeStatic(
-          commonElements.traceHelper,
-          <HInstruction>[nameConstant],
-          abstractValueDomain.dynamicType,
-          const <DartType>[]));
-    }
-  }
-
   void _insertCoverageCall(MemberEntity element) {
-    if (JavaScriptBackend.TRACE_METHOD == 'post') {
-      if (element == commonElements.traceHelper) return;
-      // TODO(sigmund): create a better uuid for elements.
-      HConstant idConstant =
-          graph.addConstantInt(element.hashCode, closedWorld);
-      HConstant nameConstant =
-          graph.addConstantString(element.name, closedWorld);
-      add(new HInvokeStatic(
-          commonElements.traceHelper,
-          <HInstruction>[idConstant, nameConstant],
-          abstractValueDomain.dynamicType,
-          const <DartType>[]));
-    }
+    if (!options.experimentCallInstrumentation) return;
+    if (element == commonElements.traceHelper) return;
+    // TODO(sigmund): create a better uuid for elements.
+    HConstant idConstant = graph.addConstantInt(element.hashCode, closedWorld);
+    n(e) => e == null ? '' : e.name;
+    String name = "${n(element.library)}:${n(element.enclosingClass)}."
+        "${n(element)}";
+    HConstant nameConstant = graph.addConstantString(name, closedWorld);
+    add(new HInvokeStatic(
+        commonElements.traceHelper,
+        <HInstruction>[idConstant, nameConstant],
+        abstractValueDomain.dynamicType,
+        const <DartType>[]));
   }
 }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index bcfe386..c6f57d2 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -27,7 +27,8 @@
 import '../js_backend/runtime_types.dart';
 import '../js_emitter/code_emitter_task.dart';
 import '../js_model/elements.dart' show JGeneratorBody;
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
+import '../native/enqueue.dart';
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
 import '../universe/call_structure.dart' show CallStructure;
@@ -157,7 +158,7 @@
 
   final CompilerOptions _options;
   final CodeEmitterTask _emitter;
-  final native.NativeCodegenEnqueuer _nativeEnqueuer;
+  final NativeCodegenEnqueuer _nativeEnqueuer;
   final CheckedModeHelpers _checkedModeHelpers;
   final OneShotInterceptorData _oneShotInterceptorData;
   final RuntimeTypesSubstitutions _rtiSubstitutions;
@@ -2215,7 +2216,7 @@
   }
 
   void registerForeignTypes(HForeign node) {
-    native.NativeBehavior nativeBehavior = node.nativeBehavior;
+    NativeBehavior nativeBehavior = node.nativeBehavior;
     if (nativeBehavior == null) return;
     _nativeEnqueuer.registerNativeBehavior(
         _registry.worldImpact, nativeBehavior, node);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index b3c93c2..222f33d 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -16,7 +16,7 @@
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/js_backend.dart';
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../types/abstract_value_domain.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
@@ -2055,7 +2055,7 @@
   HForeign(AbstractValue type, List<HInstruction> inputs) : super(inputs, type);
 
   bool get isStatement => false;
-  native.NativeBehavior get nativeBehavior => null;
+  NativeBehavior get nativeBehavior => null;
 
   bool canThrow(AbstractValueDomain domain) {
     return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
@@ -2065,15 +2065,15 @@
 class HForeignCode extends HForeign {
   final js.Template codeTemplate;
   final bool isStatement;
-  final native.NativeBehavior nativeBehavior;
-  native.NativeThrowBehavior throwBehavior;
+  final NativeBehavior nativeBehavior;
+  NativeThrowBehavior throwBehavior;
   final FunctionEntity foreignFunction;
 
   HForeignCode(this.codeTemplate, AbstractValue type, List<HInstruction> inputs,
       {this.isStatement: false,
       SideEffects effects,
-      native.NativeBehavior nativeBehavior,
-      native.NativeThrowBehavior throwBehavior,
+      NativeBehavior nativeBehavior,
+      NativeThrowBehavior throwBehavior,
       this.foreignFunction})
       : this.nativeBehavior = nativeBehavior,
         this.throwBehavior = throwBehavior,
@@ -2084,7 +2084,7 @@
     }
     if (this.throwBehavior == null) {
       this.throwBehavior = (nativeBehavior == null)
-          ? native.NativeThrowBehavior.MAY
+          ? NativeThrowBehavior.MAY
           : nativeBehavior.throwBehavior;
     }
     assert(this.throwBehavior != null);
@@ -2095,12 +2095,8 @@
     }
   }
 
-  HForeignCode.statement(
-      js.Template codeTemplate,
-      List<HInstruction> inputs,
-      SideEffects effects,
-      native.NativeBehavior nativeBehavior,
-      AbstractValue type)
+  HForeignCode.statement(js.Template codeTemplate, List<HInstruction> inputs,
+      SideEffects effects, NativeBehavior nativeBehavior, AbstractValue type)
       : this(codeTemplate, type, inputs,
             isStatement: true,
             effects: effects,
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 67455a8..e4b5eab 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -16,7 +16,7 @@
 import '../js_backend/backend.dart';
 import '../js_backend/native_data.dart' show NativeData;
 import '../js_backend/runtime_types.dart';
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
@@ -770,8 +770,7 @@
 
     // Strengthen instruction type from annotations to help optimize
     // dependent instructions.
-    native.NativeBehavior nativeBehavior =
-        _nativeData.getNativeMethodBehavior(method);
+    NativeBehavior nativeBehavior = _nativeData.getNativeMethodBehavior(method);
     AbstractValue returnType =
         AbstractValueFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
     HInvokeDynamicMethod result = new HInvokeDynamicMethod(
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index 39fd61c..8519ee9 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -4,7 +4,7 @@
 
 import '../common_elements.dart' show CommonElements;
 import '../elements/entities.dart';
-import '../native/native.dart' as native;
+import '../native/behavior.dart';
 import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
@@ -36,7 +36,7 @@
   }
 
   static AbstractValue fromNativeBehavior(
-      native.NativeBehavior nativeBehavior, JClosedWorld closedWorld) {
+      NativeBehavior nativeBehavior, JClosedWorld closedWorld) {
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
     var typesReturned = nativeBehavior.typesReturned;
     if (typesReturned.isEmpty) return abstractValueDomain.dynamicType;
@@ -46,7 +46,7 @@
     // [type] is either an instance of [DartType] or special objects
     // like [native.SpecialType.JsObject].
     AbstractValue fromNativeType(dynamic type) {
-      if (type == native.SpecialType.JsObject) {
+      if (type == SpecialType.JsObject) {
         return abstractValueDomain
             .createNonNullExact(commonElements.objectClass);
       } else if (type.isVoid) {
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index 7032550..181714f 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -571,9 +571,9 @@
 class ClassHierarchyBuilder {
   // 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, ClassHierarchyNode> _classHierarchyNodes =
       <ClassEntity, ClassHierarchyNode>{};
-  final Map<ClassEntity, ClassSet> classSets = <ClassEntity, ClassSet>{};
+  final Map<ClassEntity, ClassSet> _classSets = <ClassEntity, ClassSet>{};
   final Map<ClassEntity, Set<ClassEntity>> mixinUses =
       new Map<ClassEntity, Set<ClassEntity>>();
 
@@ -582,12 +582,22 @@
 
   ClassHierarchyBuilder(this._commonElements, this._classQueries);
 
+  ClassHierarchy close() {
+    assert(
+        _classHierarchyNodes.length == _classSets.length,
+        "ClassHierarchyNode/ClassSet mismatch: "
+        "${_classHierarchyNodes} vs "
+        "${_classSets}");
+    return new ClassHierarchyImpl(
+        _commonElements, _classHierarchyNodes, _classSets);
+  }
+
   void registerClass(ClassEntity cls) {
     _ensureClassSet(_classQueries.getDeclaration(cls));
   }
 
   ClassHierarchyNode _ensureClassHierarchyNode(ClassEntity cls) {
-    return classHierarchyNodes.putIfAbsent(cls, () {
+    return _classHierarchyNodes.putIfAbsent(cls, () {
       ClassHierarchyNode parentNode;
       ClassEntity superclass = _classQueries.getSuperClass(cls);
       if (superclass != null) {
@@ -599,7 +609,7 @@
   }
 
   ClassSet _ensureClassSet(ClassEntity cls) {
-    return classSets.putIfAbsent(cls, () {
+    return _classSets.putIfAbsent(cls, () {
       ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
       ClassSet classSet = new ClassSet(node);
 
@@ -665,55 +675,170 @@
   }
 
   bool _isSubtypeOf(ClassEntity x, ClassEntity y) {
-    assert(
-        classSets.containsKey(x), "ClassSet for $x has not been computed yet.");
-    ClassSet classSet = classSets[y];
+    assert(_classSets.containsKey(x),
+        "ClassSet for $x has not been computed yet.");
+    ClassSet classSet = _classSets[y];
     assert(classSet != null,
-        failedAt(y, "No ClassSet for $y (${y.runtimeType}): ${classSets}"));
-    ClassHierarchyNode classHierarchyNode = classHierarchyNodes[x];
+        failedAt(y, "No ClassSet for $y (${y.runtimeType}): ${_classSets}"));
+    ClassHierarchyNode classHierarchyNode = _classHierarchyNodes[x];
     assert(classHierarchyNode != null,
         failedAt(x, "No ClassHierarchyNode for $x"));
     return classSet.hasSubtype(classHierarchyNode);
   }
 
-  Map<ClassEntity, _InheritedCache> _inheritedCacheMap = {};
+  /// Returns `true` if a dynamic access on an instance of [exactClass] can
+  /// target a member declared in [memberHoldingClass].
+  bool isInheritedInExactClass(
+      ClassEntity memberHoldingClass, ClassEntity exactClass) {
+    ClassHierarchyNode exactClassNode = _classHierarchyNodes[exactClass];
+    if (!exactClassNode.isAbstractlyInstantiated &&
+        !exactClassNode.isDirectlyInstantiated) {
+      // No instances of [thisClass] are live.
+      return false;
+    }
+    ClassSet memberHoldingClassSet = _classSets[memberHoldingClass];
+    if (memberHoldingClassSet.hasSubclass(exactClassNode)) {
+      /// A member from a super class can be accessed.
+      return true;
+    }
+    for (ClassHierarchyNode mixinApplication
+        in memberHoldingClassSet.mixinApplicationNodes) {
+      if (mixinApplication.hasSubclass(exactClassNode)) {
+        /// A member from a mixed in class can be accessed.
+        return true;
+      }
+    }
+    return false;
+  }
+
+  Map<ClassEntity, _InheritedInThisClassCache> _inheritedInThisClassCacheMap =
+      {};
+
+  /// Returns `true` if a `this` expression in [thisClass] can target a member
+  /// declared in [memberHoldingClass].
+  bool isInheritedInThisClass(
+      ClassEntity memberHoldingClass, ClassEntity thisClass) {
+    _InheritedInThisClassCache cache =
+        _inheritedInThisClassCacheMap[memberHoldingClass] ??=
+            new _InheritedInThisClassCache();
+    return cache.isInheritedInThisClassOf(this, memberHoldingClass, thisClass);
+  }
+
+  Map<ClassEntity, _InheritedInSubtypeCache> _inheritedInSubtypeCacheMap = {};
 
   bool isInheritedInSubtypeOf(ClassEntity x, ClassEntity y) {
-    _InheritedCache cache = _inheritedCacheMap[x] ??= new _InheritedCache();
+    _InheritedInSubtypeCache cache =
+        _inheritedInSubtypeCacheMap[x] ??= new _InheritedInSubtypeCache();
     return cache.isInheritedInSubtypeOf(this, x, y);
   }
 }
 
+/// Cache used for computing when a member of a given class, the so-called
+/// member holding class, can be inherited into a live class.
+class _InheritedInThisClassCache {
+  /// Set of classes that inherits members from the member holding class.
+  Set<ClassEntity> _inheritingClasses;
+
+  /// Cache for liveness computation for a `this` expressions of a given class.
+  Map<ClassEntity, _LiveSet> _map;
+
+  /// Returns `true` if members of [memberHoldingClass] can be inherited into
+  /// a live class that can be the target of a `this` expression in [thisClass].
+  bool isInheritedInThisClassOf(ClassHierarchyBuilder builder,
+      ClassEntity memberHoldingClass, ClassEntity thisClass) {
+    _LiveSet set;
+    if (_map == null) {
+      _map = {};
+    } else {
+      set = _map[thisClass];
+    }
+    if (set == null) {
+      set = _map[thisClass] = _computeInheritingInThisClassSet(
+          builder, memberHoldingClass, thisClass);
+    }
+    return set.hasLiveClass(builder);
+  }
+
+  _LiveSet _computeInheritingInThisClassSet(ClassHierarchyBuilder builder,
+      ClassEntity memberHoldingClass, ClassEntity thisClass) {
+    ClassHierarchyNode memberHoldingClassNode =
+        builder._classHierarchyNodes[memberHoldingClass];
+
+    if (_inheritingClasses == null) {
+      _inheritingClasses = new Set<ClassEntity>();
+      _inheritingClasses.addAll(memberHoldingClassNode
+          .subclassesByMask(ClassHierarchyNode.ALL, strict: false));
+      for (ClassHierarchyNode mixinApplication
+          in builder._classSets[memberHoldingClass].mixinApplicationNodes) {
+        _inheritingClasses.addAll(mixinApplication
+            .subclassesByMask(ClassHierarchyNode.ALL, strict: false));
+      }
+    }
+
+    Set<ClassEntity> validatingSet = new Set<ClassEntity>();
+
+    void processHierarchy(ClassHierarchyNode mixerNode) {
+      for (ClassEntity inheritingClass in _inheritingClasses) {
+        ClassHierarchyNode inheritingClassNode =
+            builder._classHierarchyNodes[inheritingClass];
+        if (!validatingSet.contains(mixerNode.cls) &&
+            inheritingClassNode.hasSubclass(mixerNode)) {
+          // If [mixerNode.cls] is live then a `this` expression can target
+          // members inherited from [memberHoldingClass] into [inheritingClass].
+          validatingSet.add(mixerNode.cls);
+        }
+        if (mixerNode.hasSubclass(inheritingClassNode)) {
+          // If [inheritingClass] is live then a `this` expression can target
+          // members inherited from [memberHoldingClass] into `inheritingClass`
+          // into a subclass of [mixerNode.cls].
+          validatingSet.add(inheritingClass);
+        }
+      }
+    }
+
+    ClassSet thisClassSet = builder._classSets[thisClass];
+
+    processHierarchy(thisClassSet.node);
+
+    for (ClassHierarchyNode mixinApplication
+        in thisClassSet.mixinApplicationNodes) {
+      processHierarchy(mixinApplication);
+    }
+
+    return new _LiveSet(validatingSet);
+  }
+}
+
 /// A cache object used for [ClassHierarchyBuilder.isInheritedInSubtypeOf].
-class _InheritedCache {
-  Map<ClassEntity, _InheritingSet> _map;
+class _InheritedInSubtypeCache {
+  Map<ClassEntity, _LiveSet> _map;
 
   /// Returns whether a live class currently known to inherit from [x] and
   /// implement [y].
   bool isInheritedInSubtypeOf(
       ClassHierarchyBuilder builder, ClassEntity x, ClassEntity y) {
-    _InheritingSet set;
+    _LiveSet set;
     if (_map == null) {
       _map = {};
     } else {
       set = _map[y];
     }
     if (set == null) {
-      set = _map[y] = _computeInheritingSet(builder, x, y);
+      set = _map[y] = _computeInheritingInSubtypeSet(builder, x, y);
     }
     return set.hasLiveClass(builder);
   }
 
-  /// Creates an [_InheritingSet] of classes that inherit members of a class [x]
+  /// Creates an [_LiveSet] of classes that inherit members of a class [x]
   /// while implementing class [y].
-  _InheritingSet _computeInheritingSet(
+  _LiveSet _computeInheritingInSubtypeSet(
       ClassHierarchyBuilder builder, ClassEntity x, ClassEntity y) {
-    ClassSet classSet = builder.classSets[x];
+    ClassSet classSet = builder._classSets[x];
 
     assert(
         classSet != null,
         failedAt(
-            x, "No ClassSet for $x (${x.runtimeType}): ${builder.classSets}"));
+            x, "No ClassSet for $x (${x.runtimeType}): ${builder._classSets}"));
 
     Set<ClassEntity> classes = new Set<ClassEntity>();
 
@@ -740,16 +865,16 @@
       subclassImplements(mixinApplication, strict: false);
     }
 
-    return new _InheritingSet(classes);
+    return new _LiveSet(classes);
   }
 }
 
-/// A set of classes that inherit members of a class 'x' while implementing
-/// class 'y'.
+/// A set of potentially live classes.
 ///
-/// The set is used [ClassHierarchyBuilder.isInheritedInSubtypeOf] to determine
+/// The set is used [ClassHierarchyBuilder.isInheritedInSubtypeOf] and
+/// [ClassHierarchyBuilder.isInheritedInThisClassOf] to determine
 /// when members of a class is live.
-class _InheritingSet {
+class _LiveSet {
   /// If `true` the set of classes is known to contain a live class. In this
   /// case [_classes] is `null`. If `false` the set of classes is empty and
   /// therefore known never to contain live classes. In this case [_classes]
@@ -758,7 +883,7 @@
   bool _result;
   Set<ClassEntity> _classes;
 
-  _InheritingSet(Set<ClassEntity> classes)
+  _LiveSet(Set<ClassEntity> classes)
       : _result = classes.isEmpty ? false : null,
         _classes = classes.isNotEmpty ? classes : null;
 
@@ -777,7 +902,7 @@
   bool hasLiveClass(ClassHierarchyBuilder builder) {
     if (_result != null) return _result;
     for (ClassEntity cls in _classes) {
-      if (builder.classHierarchyNodes[cls].isInstantiated) {
+      if (builder._classHierarchyNodes[cls].isInstantiated) {
         // We now know this set contains a live class and done need to remember
         // that set of classes anymore.
         _result = true;
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 85d96a2..fa29bf7 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -612,10 +612,16 @@
     return true;
   }
 
+  /// Returns an [Iterable] of the classes that implement [cls] directly or
+  /// through supertypes.
+  ///
+  /// A class that implements [cls] through its superclasses is not included in
+  /// the iterable.
   Iterable<ClassHierarchyNode> get subtypeNodes {
     return _subtypes ?? const <ClassHierarchyNode>[];
   }
 
+  /// Returns an [Iterable] of the classes that mix in [cls] directly.
   Iterable<ClassHierarchyNode> get mixinApplicationNodes {
     return _mixinApplications ?? const <ClassHierarchyNode>[];
   }
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 88cee2e..e396467 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -8,6 +8,7 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/static_type.dart';
 import '../js_backend/annotations.dart';
 import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
 import '../js_backend/backend_usage.dart'
@@ -970,11 +971,28 @@
     _classHierarchyBuilder.registerClass(cls);
   }
 
-  bool isInheritedInSubtypeOf(MemberEntity member, ClassEntity type) {
+  @override
+  bool isInheritedIn(
+      MemberEntity member, ClassEntity type, ClassRelation relation) {
     // TODO(johnniwinther): Use the [member] itself to avoid enqueueing members
     // that are overridden.
-    return _classHierarchyBuilder.isInheritedInSubtypeOf(
-        member.enclosingClass, type);
+    return isInheritedInClass(member.enclosingClass, type, relation);
+  }
+
+  bool isInheritedInClass(ClassEntity memberHoldingClass, ClassEntity type,
+      ClassRelation relation) {
+    switch (relation) {
+      case ClassRelation.exact:
+        return _classHierarchyBuilder.isInheritedInExactClass(
+            memberHoldingClass, type);
+      case ClassRelation.thisExpression:
+        return _classHierarchyBuilder.isInheritedInThisClass(
+            memberHoldingClass, type);
+      case ClassRelation.subtype:
+        return _classHierarchyBuilder.isInheritedInSubtypeOf(
+            memberHoldingClass, type);
+    }
+    throw new UnsupportedError("Unexpected ClassRelation $relation.");
   }
 
   @override
@@ -1000,12 +1018,6 @@
 
     BackendUsage backendUsage = _backendUsageBuilder.close();
     _closed = true;
-    assert(
-        _classHierarchyBuilder.classHierarchyNodes.length ==
-            _classHierarchyBuilder.classSets.length,
-        "ClassHierarchyNode/ClassSet mismatch: "
-        "${_classHierarchyBuilder.classHierarchyNodes} vs "
-        "${_classHierarchyBuilder.classSets}");
 
     AnnotationsData annotationsData = processAnnotations(
         reporter, _commonElements, _elementEnvironment, _processedMembers);
@@ -1029,8 +1041,7 @@
         processedMembers: _processedMembers,
         mixinUses: _classHierarchyBuilder.mixinUses,
         typesImplementedBySubclasses: typesImplementedBySubclasses,
-        classHierarchyNodes: _classHierarchyBuilder.classHierarchyNodes,
-        classSets: _classHierarchyBuilder.classSets,
+        classHierarchy: _classHierarchyBuilder.close(),
         annotationsData: annotationsData);
     if (retainDataForTesting) {
       _closedWorldCache = closedWorld;
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index acc7100..42cac09 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -10,6 +10,7 @@
 import '../elements/entity_utils.dart' as utils;
 import '../elements/names.dart';
 import '../elements/operators.dart';
+import '../kernel/invocation_mirror_constants.dart';
 import '../serialization/serialization.dart';
 import '../util/util.dart' show Hashing;
 import 'call_structure.dart' show CallStructure;
@@ -237,10 +238,6 @@
    */
   String get invocationMirrorMemberName => isSetter ? '$name=' : name;
 
-  static const int invocationMirrorMethodKind = 0;
-  static const int invocationMirrorGetterKind = 1;
-  static const int invocationMirrorSetterKind = 2;
-
   int get invocationMirrorKind {
     int kind = invocationMirrorMethodKind;
     if (isGetter) {
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 5e7b719..a5e2b41 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -46,6 +46,11 @@
     if (receiverConstraint != null) {
       var constraint = receiverConstraint;
       if (constraint is StrongModeConstraint) {
+        if (constraint.isThis) {
+          sb.write('<');
+        } else if (constraint.isExact) {
+          sb.write('=');
+        }
         sb.write(constraint.cls.name);
       } else {
         sb.write(constraint);
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 31838fc..9eb4560 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -7,6 +7,7 @@
 import '../common_elements.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/static_type.dart';
 import '../js_backend/native_data.dart' show NativeBasicData;
 import '../world.dart' show World, JClosedWorld, OpenWorld;
 import 'selector.dart' show Selector;
@@ -158,34 +159,42 @@
 
 class StrongModeConstraint {
   final ClassEntity cls;
+  final ClassRelation relation;
 
   factory StrongModeConstraint(CommonElements commonElements,
-      NativeBasicData nativeBasicData, ClassEntity cls) {
+      NativeBasicData nativeBasicData, ClassEntity cls,
+      [ClassRelation relation = ClassRelation.subtype]) {
     if (nativeBasicData.isJsInteropClass(cls)) {
       // We can not tell js-interop classes apart, so we just assume the
       // receiver could be any js-interop class.
       cls = commonElements.jsJavaScriptObjectClass;
+      relation = ClassRelation.subtype;
     }
-    return new StrongModeConstraint.internal(cls);
+    return new StrongModeConstraint.internal(cls, relation);
   }
 
-  const StrongModeConstraint.internal(this.cls);
+  const StrongModeConstraint.internal(this.cls, this.relation);
 
   bool needsNoSuchMethodHandling(Selector selector, World world) => true;
 
   bool canHit(MemberEntity element, Selector selector, OpenWorld world) {
-    return world.isInheritedInSubtypeOf(element, cls);
+    return world.isInheritedIn(element, cls, relation);
   }
 
-  bool operator ==(other) {
+  bool get isExact => relation == ClassRelation.exact;
+
+  bool get isThis => relation == ClassRelation.thisExpression;
+
+  bool operator ==(Object other) {
     if (identical(this, other)) return true;
-    if (other is! StrongModeConstraint) return false;
-    return cls == other.cls;
+    return other is StrongModeConstraint &&
+        cls == other.cls &&
+        relation == other.relation;
   }
 
   int get hashCode => cls.hashCode * 13;
 
-  String toString() => 'StrongModeConstraint($cls)';
+  String toString() => 'StrongModeConstraint($cls,$relation)';
 }
 
 /// The [WorldBuilder] is an auxiliary class used in the process of computing
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 01ba8f9..6a0fd25 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -17,6 +17,7 @@
 import 'diagnostics/diagnostic_listener.dart';
 import 'elements/entities.dart';
 import 'elements/types.dart';
+import 'ir/static_type.dart';
 import 'js_backend/annotations.dart';
 import 'js_backend/allocator_analysis.dart'
     show JAllocatorAnalysis, KAllocatorAnalysis;
@@ -225,10 +226,11 @@
   ///     abstract class I { m(); }
   ///     abstract class J implements A { }
   ///
-  /// Here `A.m` is inherited into `A`, `B`, and `C`. Becausec `B` and
-  /// `C` implement `I`, `isInheritedInSubtypeOf(A.M, I)` is true, but
-  /// `isInheritedInSubtypeOf(A.M, J)` is false.
-  bool isInheritedInSubtypeOf(MemberEntity member, ClassEntity type);
+  /// Here `A.m` is inherited into `A`, `B`, and `C`. Because `B` and
+  /// `C` implement `I`, `isInheritedInSubtypeOf(A.m, I)` is true, but
+  /// `isInheritedInSubtypeOf(A.m, J)` is false.
+  bool isInheritedIn(
+      MemberEntity member, ClassEntity type, ClassRelation relation);
 }
 
 abstract class KClosedWorld {
diff --git a/pkg/dev_compiler/bin/dartdevc.dart b/pkg/dev_compiler/bin/dartdevc.dart
index 28b950d..10b1dd6 100755
--- a/pkg/dev_compiler/bin/dartdevc.dart
+++ b/pkg/dev_compiler/bin/dartdevc.dart
@@ -38,7 +38,6 @@
 class _CompilerWorker extends AsyncWorkerLoop {
   /// The original args supplied to the executable.
   final ParsedArguments _startupArgs;
-  CompilerResult _result;
 
   _CompilerWorker(this._startupArgs, AsyncWorkerConnection workerConnection)
       : super(connection: workerConnection);
@@ -47,13 +46,12 @@
   Future<WorkResponse> performRequest(WorkRequest request) async {
     var args = _startupArgs.merge(request.arguments);
     var output = StringBuffer();
-    _result = await runZoned(() => compile(args, previousResult: _result),
-        zoneSpecification:
-            ZoneSpecification(print: (self, parent, zone, message) {
+    var result = await runZoned(() => compile(args), zoneSpecification:
+        ZoneSpecification(print: (self, parent, zone, message) {
       output.writeln(message.toString());
     }));
     return WorkResponse()
-      ..exitCode = _result.success ? 0 : 1
+      ..exitCode = result.success ? 0 : 1
       ..output = output.toString();
   }
 }
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index e247077..32f7d96 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -65,7 +65,7 @@
 // expressions (which result in JS.Expression) and statements
 // (which result in (JS.Statement).
 class CodeGenerator extends Object
-    with NullableTypeInference, SharedCompiler<LibraryElement>
+    with NullableTypeInference, SharedCompiler<LibraryElement, ClassElement>
     implements AstVisitor<JS.Node> {
   final SummaryDataStore summaryData;
 
@@ -1318,8 +1318,8 @@
           ctorBody
               .add(_emitSuperConstructorCall(className, ctor.name, jsParams));
         }
-        body.add(_addConstructorToClass(
-            className, ctor.name, JS.Fun(jsParams, JS.Block(ctorBody))));
+        body.add(_addConstructorToClass(classElem, className, ctor.name,
+            JS.Fun(jsParams, JS.Block(ctorBody))));
       }
     }
 
@@ -1879,7 +1879,7 @@
     }
 
     addConstructor(String name, JS.Expression jsCtor) {
-      body.add(_addConstructorToClass(className, name, jsCtor));
+      body.add(_addConstructorToClass(classElem, className, name, jsCtor));
     }
 
     if (classElem.isEnum) {
@@ -1943,12 +1943,31 @@
             c.isSynthetic && c.name != '' || c.isFactory || c.isExternal);
   }
 
-  JS.Statement _addConstructorToClass(
-      JS.Expression className, String name, JS.Expression jsCtor) {
-    jsCtor = defineValueOnClass(className, _constructorName(name), jsCtor);
+  JS.Statement _addConstructorToClass(ClassElement c, JS.Expression className,
+      String name, JS.Expression jsCtor) {
+    jsCtor = defineValueOnClass(c, className, _constructorName(name), jsCtor);
     return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
   }
 
+  @override
+  bool superclassHasStatic(ClassElement c, String name) {
+    // Note: because we're only considering statics, we can ignore mixins.
+    // We're only trying to find conflicts due to JS inheriting statics.
+    var library = c.library;
+    while (true) {
+      var supertype = c.supertype;
+      if (supertype == null) return false;
+      c = supertype.element;
+      for (var members in [c.methods, c.accessors]) {
+        for (var m in members) {
+          if (m.isStatic && m.name == name && m.isAccessibleIn(library)) {
+            return true;
+          }
+        }
+      }
+    }
+  }
+
   /// Emits static fields for a class, and initialize them eagerly if possible,
   /// otherwise define them as lazy properties.
   void _emitStaticFields(ClassElement classElem,
@@ -1957,7 +1976,7 @@
       // Emit enum static fields
       var type = classElem.type;
       void addField(FieldElement e, JS.Expression value) {
-        body.add(defineValueOnClass(_emitStaticClassName(classElem),
+        body.add(defineValueOnClass(classElem, _emitStaticClassName(classElem),
                 _declareMemberName(e.getter), value)
             .toStatement());
       }
@@ -2252,8 +2271,8 @@
     var parameters = element.parameters
         .map((p) => ParameterElementImpl.synthetic(
             p.name,
-            // ignore: deprecated_member_use
             _isCovariant(p) ? objectClass.type : p.type,
+            // ignore: deprecated_member_use
             p.parameterKind))
         .toList();
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index f3cca4f..63d1223 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -216,14 +216,6 @@
       prepareUnlinkedUnit(sourcesToProcess.removeFirst());
     }
 
-    /// Gets the URIs to link.
-    ///
-    /// Unlike analyzer_cli, this only includes library URIs, not all
-    /// compilation units. This appears to be what [summary_link.link] wants as
-    /// input. If all units are passed in, the resulting summary has extra data
-    /// in the linkedLibraries list, which appears to be unnecessary.
-    var unlinkedUris = Set<String>.from(summaryData.uriToSummaryPath.keys)
-      ..addAll(libraryUris);
     var declaredVariables = DeclaredVariables.fromMap(
         Map.of(options.declaredVariables)..addAll(sdkLibraryVariables));
 
@@ -232,7 +224,7 @@
     /// TODO(jmesserly): can we pass in `getAst` to reuse existing ASTs we
     /// created when we did `file.parse()` in [prepareUnlinkedUnit]?
     var linkResult = summary_link.link(
-        unlinkedUris,
+        libraryUris.toSet(),
         (uri) => summaryData.linkedMap[uri],
         (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
         declaredVariables.get);
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index ddb903c..2112e0f 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -466,7 +466,11 @@
       var arg = args[i];
       var isLastArg = i == len - 1;
       if (isLastArg && arg.startsWith('@')) {
-        newArgs.addAll(_readLines(arg.substring(1)));
+        var extra = _readLines(arg.substring(1)).toList();
+        if (extra.remove('--kernel') || extra.remove('-k')) {
+          isKernel = true;
+        }
+        newArgs.addAll(extra);
       } else if (arg == '--persistent_worker') {
         isWorker = true;
       } else if (isLastArg && arg == '--batch') {
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index f9b5c0c..a39888c 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -13,7 +13,7 @@
 ///
 /// This class should only implement functionality that depends purely on JS
 /// classes, rather than on Analyzer/Kernel types.
-abstract class SharedCompiler<Library> {
+abstract class SharedCompiler<Library, Class> {
   /// When inside a `[]=` operator, this will be a non-null value that should be
   /// returned by any `return;` statement.
   ///
@@ -141,21 +141,26 @@
     });
   }
 
-  /// Emits an expression to set the property [name] on the class [className],
+  /// Emits an expression to set the property [nameExpr] on the class [className],
   /// with [value].
   ///
   /// This will use `className.name = value` if possible, otherwise it will use
   /// `dart.defineValue(className, name, value)`. This is required when
   /// `Function.prototype` already defins a getters with the same name.
-  JS.Expression defineValueOnClass(
-      JS.Expression className, JS.Expression name, JS.Expression value) {
-    var args = [className, name, value];
-    if (name is JS.LiteralString &&
-        JS.isFunctionPrototypeGetter(name.valueWithoutQuotes)) {
-      return runtimeCall('defineValue(#, #, #)', args);
+  JS.Expression defineValueOnClass(Class c, JS.Expression className,
+      JS.Expression nameExpr, JS.Expression value) {
+    var args = [className, nameExpr, value];
+    if (nameExpr is JS.LiteralString) {
+      var name = nameExpr.valueWithoutQuotes;
+      if (JS.isFunctionPrototypeGetter(name) || superclassHasStatic(c, name)) {
+        return runtimeCall('defineValue(#, #, #)', args);
+      }
     }
     return js.call('#.# = #', args);
   }
+
+  /// Whether any superclass of [c] defines a static [name].
+  bool superclassHasStatic(Class c, String name);
 }
 
 /// Whether a variable with [name] is referenced in the [node].
diff --git a/pkg/dev_compiler/lib/src/js_ast/builder.dart b/pkg/dev_compiler/lib/src/js_ast/builder.dart
index 6520afc..d81f7e3 100644
--- a/pkg/dev_compiler/lib/src/js_ast/builder.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/builder.dart
@@ -663,7 +663,7 @@
 
   void getToken() {
     skippedNewline = false;
-    for (;;) {
+    while (true) {
       if (position >= src.length) break;
       int code = src.codeUnitAt(position);
       //  Skip '//' and '/*' style comments.
@@ -990,7 +990,7 @@
 
     expectCategory(LPAREN);
     if (!acceptCategory(RPAREN)) {
-      for (;;) {
+      while (true) {
         if (acceptCategory(ELLIPSIS)) {
           params.add(RestParameter(parseParameter()));
           expectCategory(RPAREN);
@@ -1039,7 +1039,7 @@
 
   Expression parseObjectInitializer() {
     List<Property> properties = <Property>[];
-    for (;;) {
+    while (true) {
       if (acceptCategory(RBRACE)) break;
       // Limited subset of ES6 object initializers.
       //
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index 56f032c..bdd29bd 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -402,7 +402,7 @@
         newInForInit: true, newAtStatementBegin: false);
     out(" of");
     pendingSpace = true;
-    visitNestedExpression(loop.iterable, EXPRESSION,
+    visitNestedExpression(loop.iterable, ASSIGNMENT,
         newInForInit: false, newAtStatementBegin: false);
     out(")");
     blockBody(loop.body, needsSeparation: false, needsNewline: true);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 6351180..2617516 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -32,7 +32,7 @@
 import 'type_table.dart';
 
 class ProgramCompiler extends Object
-    with SharedCompiler<Library>
+    with SharedCompiler<Library, Class>
     implements
         StatementVisitor<JS.Statement>,
         ExpressionVisitor<JS.Expression>,
@@ -773,7 +773,7 @@
           ctorBody.add(_emitSuperConstructorCall(className, name, jsParams));
         }
         body.add(_addConstructorToClass(
-            className, name, JS.Fun(jsParams, JS.Block(ctorBody))));
+            c, className, name, JS.Fun(jsParams, JS.Block(ctorBody))));
       }
     }
 
@@ -877,7 +877,7 @@
     }
 
     addConstructor(String name, JS.Expression jsCtor) {
-      body.add(_addConstructorToClass(className, name, jsCtor));
+      body.add(_addConstructorToClass(c, className, name, jsCtor));
     }
 
     var fields = c.fields;
@@ -1141,6 +1141,7 @@
       for (var f in fields) {
         assert(f.isConst);
         body.add(defineValueOnClass(
+                c,
                 classRef,
                 _emitStaticMemberName(f.name.name),
                 _visitInitializer(f.initializer, f.annotations))
@@ -1600,11 +1601,28 @@
   }
 
   JS.Statement _addConstructorToClass(
-      JS.Expression className, String name, JS.Expression jsCtor) {
-    jsCtor = defineValueOnClass(className, _constructorName(name), jsCtor);
+      Class c, JS.Expression className, String name, JS.Expression jsCtor) {
+    jsCtor = defineValueOnClass(c, className, _constructorName(name), jsCtor);
     return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
   }
 
+  @override
+  bool superclassHasStatic(Class c, String memberName) {
+    // Note: because we're only considering statics, we can ignore mixins.
+    // We're only trying to find conflicts due to JS inheriting statics.
+    var name = Name(memberName, c.enclosingLibrary);
+    while (true) {
+      c = c.superclass;
+      if (c == null) return false;
+      for (var m in c.members) {
+        if (m.name == name &&
+            (m is Procedure && m.isStatic || m is Field && m.isStatic)) {
+          return true;
+        }
+      }
+    }
+  }
+
   List<JS.Method> _emitClassMethods(Class c) {
     var virtualFields = _classProperties.virtualFields;
 
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart
index cfaa3fc..787c677 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/convert_patch.dart
@@ -495,3 +495,13 @@
     return null;
   }();
 }
+
+@patch
+int _scanOneByteCharacters(List<int> units, int from, int endIndex) {
+  final to = endIndex;
+  for (var i = from; i < to; i++) {
+    final unit = units[i];
+    if ((unit & _ONE_BYTE_LIMIT) != unit) return i - from;
+  }
+  return to - from;
+}
diff --git a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
index 5be815e..bdd78ad 100644
--- a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
@@ -63,7 +63,7 @@
   Future<List<int>> readAsBytes() async {
     try {
       CompilerContext.recordDependency(uri);
-      return await new io.File.fromUri(uri).readAsBytes();
+      return new io.File.fromUri(uri).readAsBytesSync();
     } on io.FileSystemException catch (exception) {
       throw _toFileSystemException(exception);
     }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index d033d7d..2a4eb8d 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -11,6 +11,8 @@
 import '../fasta_codes.dart'
     show SummaryTemplate, Template, templateDillOutlineSummary;
 
+import '../compiler_context.dart' show CompilerContext;
+
 import '../kernel/kernel_builder.dart' show LibraryBuilder;
 
 import '../loader.dart' show Loader;
@@ -26,9 +28,11 @@
   final libraries = <Library>[];
 
   /// Sources for all appended components.
-  final Map<Uri, Source> uriToSource = <Uri, Source>{};
+  final Map<Uri, Source> uriToSource;
 
-  DillLoader(TargetImplementation target) : super(target);
+  DillLoader(TargetImplementation target)
+      : uriToSource = CompilerContext.current.uriToSource,
+        super(target);
 
   Template<SummaryTemplate> get outlineSummaryTemplate =>
       templateDillOutlineSummary;
diff --git a/pkg/front_end/lib/src/fasta/get_dependencies.dart b/pkg/front_end/lib/src/fasta/get_dependencies.dart
index e4aacb2..abd9879 100644
--- a/pkg/front_end/lib/src/fasta/get_dependencies.dart
+++ b/pkg/front_end/lib/src/fasta/get_dependencies.dart
@@ -49,9 +49,8 @@
       var platformComponent = loadComponentFromBytes(bytes);
       dillTarget.loader.appendLibraries(platformComponent);
     }
-    KernelTarget kernelTarget = new KernelTarget(
-        fileSystem, false, dillTarget, uriTranslator,
-        uriToSource: c.uriToSource);
+    KernelTarget kernelTarget =
+        new KernelTarget(fileSystem, false, dillTarget, uriTranslator);
 
     kernelTarget.setEntryPoints(<Uri>[script]);
     await dillTarget.buildOutlines();
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 2565d7e..2ba7eb7 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -81,7 +81,6 @@
   Set<Uri> invalidatedUris = new Set<Uri>();
 
   DillTarget dillLoadedData;
-  Map<Uri, Source> dillLoadedDataUriToSource = <Uri, Source>{};
   List<LibraryBuilder> platformBuilders;
   Map<Uri, LibraryBuilder> userBuilders;
   final Uri initializeFromDillUri;
@@ -206,7 +205,6 @@
       for (Uri uri in new Set<Uri>.from(dillLoadedData.loader.builders.keys)
         ..removeAll(reusedLibraryUris)) {
         dillLoadedData.loader.builders.remove(uri);
-        dillLoadedDataUriToSource.remove(uri);
         userBuilders?.remove(uri);
       }
 
@@ -234,8 +232,7 @@
               c.fileSystem),
           false,
           dillLoadedData,
-          uriTranslator,
-          uriToSource: c.uriToSource);
+          uriTranslator);
       userCode.loader.hierarchy = hierarchy;
 
       for (LibraryBuilder library in reusedLibraries) {
@@ -265,9 +262,6 @@
 
       List<Library> compiledLibraries =
           new List<Library>.from(userCode.loader.libraries);
-      Map<Uri, Source> uriToSource =
-          new Map<Uri, Source>.from(dillLoadedDataUriToSource);
-      uriToSource.addAll(userCode.uriToSource);
       Procedure mainMethod = componentWithDill == null
           ? data.userLoadedUriMain
           : componentWithDill.mainMethod;
@@ -287,13 +281,10 @@
         userCode = userCodeOld;
       }
 
-      Map<Uri, Source> optionalUriToSource = context.options.embedSourceText
-          ? uriToSource
-          : uriToSource.map((uri, source) => MapEntry<Uri, Source>(
-              uri, new Source(source.lineStarts, const <int>[])));
       // This is the incremental component.
       return context.options.target.configureComponent(new Component(
-          libraries: outputLibraries, uriToSource: optionalUriToSource))
+          libraries: outputLibraries,
+          uriToSource: componentWithDill.uriToSource))
         ..mainMethod = mainMethod;
     });
   }
@@ -347,7 +338,6 @@
         Library lib = builder.target;
         removedLibraries.add(lib);
         dillLoadedData.loader.builders.remove(uri);
-        dillLoadedDataUriToSource.remove(uri);
         userBuilders?.remove(uri);
       }
     }
@@ -387,8 +377,6 @@
       if (initializationBytes != null) {
         ticker.logMs("Read $initializeFromDillUri");
 
-        Set<Uri> sdkUris = data.component.uriToSource.keys.toSet();
-
         // We're going to output all we read here so lazy loading it
         // doesn't make sense.
         new BinaryBuilder(initializationBytes, disableLazyReading: true)
@@ -412,10 +400,6 @@
         bytesLength += initializationBytes.length;
         data.userLoadedUriMain = data.component.mainMethod;
         data.includeUserLoadedLibraries = true;
-        for (Uri uri in data.component.uriToSource.keys) {
-          if (sdkUris.contains(uri)) continue;
-          dillLoadedDataUriToSource[uri] = data.component.uriToSource[uri];
-        }
       }
     }
     return bytesLength;
@@ -622,6 +606,12 @@
         for (LibraryPart part in library.target.parts) {
           Uri partUri = library.uri.resolve(part.partUri);
           Uri fileUri = library.library.fileUri.resolve(part.partUri);
+          if (fileUri.scheme == "package") {
+            // Part was specified via package URI and the resolve above thus
+            // did not go as expected. Translate the package URI to get the
+            // actual file URI.
+            fileUri = uriTranslator.translate(partUri, false);
+          }
           if (isInvalidated(partUri, fileUri)) {
             invalidatedImportUris.add(partUri);
             builders[partUri] = library;
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 3358be6..8d44dc6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2328,7 +2328,7 @@
   }
 
   @override
-  void endLiteralMapEntry(Token colon, Token endToken) {
+  void handleLiteralMapEntry(Token colon, Token endToken) {
     debugEvent("LiteralMapEntry");
     Expression value = popForValue();
     Expression key = popForValue();
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
index fd26c01..87fbc5b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
@@ -5,8 +5,7 @@
 /// This library exports all API from Kernel that can be used throughout fasta.
 library fasta.kernel_api;
 
-export 'package:kernel/type_algebra.dart'
-    show Substitution, instantiateToBounds, substitute;
+export 'package:kernel/type_algebra.dart' show Substitution, substitute;
 
 export 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -20,6 +19,8 @@
 
 export 'package:kernel/type_environment.dart' show TypeEnvironment;
 
+export 'package:kernel/src/bounds_checks.dart' show instantiateToBounds;
+
 import 'package:kernel/text/ast_to_text.dart' show NameSystem, Printer;
 
 import 'package:kernel/ast.dart' show Class, Member, Node;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart
index b76dbae..f7b56a8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart
@@ -13,7 +13,8 @@
         FormalParameterBuilder,
         KernelLibraryBuilder,
         KernelTypeBuilder,
-        MetadataBuilder;
+        MetadataBuilder,
+        TypeBuilder;
 
 import 'kernel_shadow_ast.dart' show VariableDeclarationJudgment;
 
@@ -48,6 +49,14 @@
     return declaration;
   }
 
+  KernelFormalParameterBuilder clone(List<TypeBuilder> newTypes) {
+    // TODO(dmitryas):  It's not clear how [metadata] is used currently, and
+    // how it should be cloned.  Consider cloning it instead of reusing it.
+    return new KernelFormalParameterBuilder(metadata, modifiers,
+        type?.clone(newTypes), name, hasThis, parent, charOffset)
+      ..kind = kind;
+  }
+
   @override
   FormalParameterBuilder forFormalParameterInitializerScope() {
     assert(declaration != null);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
index edebe4a..916dc20d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
@@ -91,18 +91,23 @@
   }
 
   KernelFunctionTypeBuilder clone(List<TypeBuilder> newTypes) {
-    List<TypeVariableBuilder> clonedTypeVariables =
-        new List<TypeVariableBuilder>(typeVariables.length);
-    for (int i = 0; i < clonedTypeVariables.length; i++) {
-      clonedTypeVariables[i] = typeVariables[i].clone(newTypes);
+    List<TypeVariableBuilder> clonedTypeVariables;
+    if (typeVariables != null) {
+      clonedTypeVariables = new List<TypeVariableBuilder>(typeVariables.length);
+      for (int i = 0; i < clonedTypeVariables.length; i++) {
+        clonedTypeVariables[i] = typeVariables[i].clone(newTypes);
+      }
     }
-    List<FormalParameterBuilder> clonedFormals =
-        new List<FormalParameterBuilder>(formals.length);
-    for (int i = 0; i < clonedFormals.length; i++) {
-      clonedFormals[i] = formals[i].clone(newTypes);
+    List<FormalParameterBuilder> clonedFormals;
+    if (formals != null) {
+      clonedFormals = new List<FormalParameterBuilder>(formals.length);
+      for (int i = 0; i < clonedFormals.length; i++) {
+        KernelFormalParameterBuilder formal = formals[i];
+        clonedFormals[i] = formal.clone(newTypes);
+      }
     }
     KernelFunctionTypeBuilder newType = new KernelFunctionTypeBuilder(
-        returnType.clone(newTypes), clonedTypeVariables, clonedFormals);
+        returnType?.clone(newTypes), clonedTypeVariables, clonedFormals);
     newTypes.add(newType);
     return newType;
   }
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 ffd5b41..7660133 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
@@ -420,16 +420,29 @@
 
       /// Helper function that returns `true` if a type variable with a name
       /// from [typeVariableNames] is referenced in [type].
-      bool usesTypeVariables(KernelNamedTypeBuilder type) {
-        List<KernelTypeBuilder> typeArguments = type.arguments;
-        if (typeArguments != null && typeVariables != null) {
-          for (KernelTypeBuilder argument in typeArguments) {
-            if (typeVariableNames.contains(argument.name)) {
-              return true;
-            } else if (argument is KernelNamedTypeBuilder) {
-              if (usesTypeVariables(argument)) return true;
+      bool usesTypeVariables(KernelTypeBuilder type) {
+        if (type is KernelNamedTypeBuilder) {
+          if (type.declaration is KernelTypeVariableBuilder) {
+            return typeVariableNames.contains(type.declaration.name);
+          }
+
+          List<KernelTypeBuilder> typeArguments = type.arguments;
+          if (typeArguments != null && typeVariables != null) {
+            for (KernelTypeBuilder argument in typeArguments) {
+              if (usesTypeVariables(argument)) {
+                return true;
+              }
             }
           }
+        } else if (type is KernelFunctionTypeBuilder) {
+          if (type.formals != null) {
+            for (FormalParameterBuilder formal in type.formals) {
+              if (usesTypeVariables(formal.type)) {
+                return true;
+              }
+            }
+          }
+          return usesTypeVariables(type.returnType);
         }
         return false;
       }
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 1342714..ee564d1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -133,9 +133,9 @@
 
   KernelTarget(this.fileSystem, this.includeComments, DillTarget dillTarget,
       UriTranslator uriTranslator,
-      {Map<Uri, Source> uriToSource, MetadataCollector metadataCollector})
+      {MetadataCollector metadataCollector})
       : dillTarget = dillTarget,
-        uriToSource = uriToSource ?? CompilerContext.current.uriToSource,
+        uriToSource = CompilerContext.current.uriToSource,
         metadataCollector = metadataCollector,
         super(dillTarget.ticker, uriTranslator, dillTarget.backendTarget) {
     loader = createLoader();
@@ -350,7 +350,6 @@
     }
 
     this.uriToSource.forEach(copySource);
-    dillTarget.loader.uriToSource.forEach(copySource);
 
     Component component = CompilerContext.current.options.target
         .configureComponent(new Component(
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 5e15224..166d266 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -254,11 +254,6 @@
   }
 
   @override
-  void beginLiteralMapEntry(Token token) {
-    listener?.beginLiteralMapEntry(token);
-  }
-
-  @override
   void beginLiteralString(Token token) {
     listener?.beginLiteralString(token);
   }
@@ -686,8 +681,8 @@
   }
 
   @override
-  void endLiteralMapEntry(Token colon, Token endToken) {
-    listener?.endLiteralMapEntry(colon, endToken);
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    listener?.handleLiteralMapEntry(colon, endToken);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 9078ced..457928d 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -678,9 +678,7 @@
     logEvent("LibraryName");
   }
 
-  void beginLiteralMapEntry(Token token) {}
-
-  void endLiteralMapEntry(Token colon, Token endToken) {
+  void handleLiteralMapEntry(Token colon, Token endToken) {
     logEvent("LiteralMapEntry");
   }
 
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 2617420..bc96678 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -263,7 +263,15 @@
 
   /// Experimental flag for enabling set literal support.
   /// See https://github.com/dart-lang/sdk/issues/35121
-  bool parseSetLiterals = false;
+  bool enableSetLiterals = false;
+
+  /// Obsolete experimental flag for enabling set literal support.
+  /// Use enableSetLiterals instead.
+  /// TODO(danrubel): Remove this once this has been merged into the analyzer
+  /// branch and the references to this have been cleaned up.
+  set parseSetLiterals(bool value) {
+    enableSetLiterals = value;
+  }
 
   /// Represents parser state: what asynchronous syntax is allowed in the
   /// function being currently parsed. In rare situations, this can be set by
@@ -1208,8 +1216,10 @@
           } else if (next.kind == IDENTIFIER_TOKEN &&
               next.next.kind == IDENTIFIER_TOKEN) {
             // Looks like a missing comma
-            Token comma = new SyntheticToken(TokenType.COMMA, next.charOffset);
-            token = rewriter.insertToken(token, comma);
+            token = rewriteAndRecover(
+                token,
+                fasta.templateExpectedButGot.withArguments(','),
+                new SyntheticToken(TokenType.COMMA, next.charOffset));
             continue;
           } else {
             token = ensureCloseParen(token, begin);
@@ -4196,9 +4206,9 @@
   }
 
   /// This method parses the portion of a set or map literal that starts with
-  /// the left curly brace.
+  /// the left curly brace when there are no leading type arguments.
   Token parseLiteralSetOrMapSuffix(final Token start, Token constKeyword) {
-    if (!parseSetLiterals) {
+    if (!enableSetLiterals) {
       // TODO(danrubel): remove this once set literals are permanent
       return parseLiteralMapSuffix(start, constKeyword);
     }
@@ -4211,30 +4221,29 @@
       return rightBrace;
     }
 
-    final old = mayParseFunctionExpressions;
+    bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
-    final originalListener = listener;
-    listener = new ForwardingListener();
-
-    // Skip over the first expression to determine if this is a set or map.
-    // TODO(danrubel): Consider removing listener.beginLiteralMapEntry
-    // so that the expression could be parsed without lookahead
-    // regardless of whether this is a set or map literal.
     Token token = parseExpression(leftBrace);
-    Token next = token.next;
-
-    listener = originalListener;
     mayParseFunctionExpressions = old;
 
-    if (optional(',', next) || optional('}', next)) {
-      return parseLiteralSetSuffix(start, constKeyword);
-    } else if (optional(':', next)) {
-      return parseLiteralMapSuffix(start, constKeyword);
+    Token next = token.next;
+    if (optional('}', next)) {
+      listener.handleLiteralSet(1, leftBrace, constKeyword, next);
+      return next;
+    } else if (optional(',', next)) {
+      return parseLiteralSetRest(next, constKeyword, leftBrace);
     } else {
-      // Recovery: This could be either a literal set or a literal map
       // TODO(danrubel): Consider better recovery
-      // rather than just assuming this is a malformed literal map.
-      return parseLiteralMapSuffix(start, constKeyword);
+      // rather than just assuming this is a literal map.
+      Token colon = ensureColon(next);
+
+      final old = mayParseFunctionExpressions;
+      mayParseFunctionExpressions = true;
+      token = parseExpression(colon);
+      mayParseFunctionExpressions = old;
+
+      listener.handleLiteralMapEntry(colon, token.next);
+      return parseLiteralMapRest(token, constKeyword, leftBrace);
     }
   }
 
@@ -4253,27 +4262,42 @@
   Token parseLiteralMapSuffix(Token token, Token constKeyword) {
     Token beginToken = token = token.next;
     assert(optional('{', beginToken));
-    int count = 0;
+    if (optional('}', token.next)) {
+      token = token.next;
+      listener.handleLiteralMap(0, beginToken, constKeyword, token);
+      return token;
+    }
+
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    token = parseMapLiteralEntry(token);
+    mayParseFunctionExpressions = old;
+
+    return parseLiteralMapRest(token, constKeyword, beginToken);
+  }
+
+  /// Parse a literal map after the first entry.
+  Token parseLiteralMapRest(Token token, Token constKeyword, Token beginToken) {
+    int count = 1;
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
     while (true) {
-      if (optional('}', token.next)) {
-        token = token.next;
+      Token next = token.next;
+      Token comma;
+      if (optional(',', next)) {
+        comma = token = next;
+        next = token.next;
+      }
+      if (optional('}', next)) {
+        token = next;
         break;
       }
-      token = parseMapLiteralEntry(token);
-      Token next = token.next;
-      ++count;
-      if (!optional(',', next)) {
-        if (optional('}', next)) {
-          token = next;
-          break;
-        }
+      if (comma == null) {
         // Recovery
         if (looksLikeExpressionStart(next)) {
           // If this looks like the start of an expression,
           // then report an error, insert the comma, and continue parsing.
-          next = rewriteAndRecover(
+          token = rewriteAndRecover(
               token,
               fasta.templateExpectedButGot.withArguments(','),
               new SyntheticToken(TokenType.COMMA, next.offset));
@@ -4285,7 +4309,8 @@
           break;
         }
       }
-      token = next;
+      token = parseMapLiteralEntry(token);
+      ++count;
     }
     assert(optional('}', token));
     mayParseFunctionExpressions = old;
@@ -4306,34 +4331,49 @@
   /// if not. This is a suffix parser because it is assumed that type arguments
   /// have been parsed, or `listener.handleNoTypeArguments` has been executed.
   Token parseLiteralSetSuffix(Token token, Token constKeyword) {
-    if (!parseSetLiterals) {
+    if (!enableSetLiterals) {
       // TODO(danrubel): remove this once set literals are permanent
       return parseLiteralMapSuffix(token, constKeyword);
     }
 
     Token beginToken = token = token.next;
     assert(optional('{', beginToken));
-    int count = 0;
+    if (optional('}', token.next)) {
+      token = token.next;
+      listener.handleLiteralSet(0, beginToken, constKeyword, token);
+      return token;
+    }
+
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    token = parseExpression(token);
+    mayParseFunctionExpressions = old;
+
+    return parseLiteralSetRest(token, constKeyword, beginToken);
+  }
+
+  /// Parse a literal set after the first expression.
+  Token parseLiteralSetRest(Token token, Token constKeyword, Token beginToken) {
+    int count = 1;
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
     while (true) {
-      if (optional('}', token.next)) {
-        token = token.next;
+      Token next = token.next;
+      Token comma;
+      if (optional(',', next)) {
+        comma = token = next;
+        next = token.next;
+      }
+      if (optional('}', next)) {
+        token = next;
         break;
       }
-      token = parseExpression(token);
-      Token next = token.next;
-      ++count;
-      if (!optional(',', next)) {
-        if (optional('}', next)) {
-          token = next;
-          break;
-        }
+      if (comma == null) {
         // Recovery
         if (looksLikeExpressionStart(next)) {
           // If this looks like the start of an expression,
           // then report an error, insert the comma, and continue parsing.
-          next = rewriteAndRecover(
+          token = rewriteAndRecover(
               token,
               fasta.templateExpectedButGot.withArguments(','),
               new SyntheticToken(TokenType.COMMA, next.offset));
@@ -4345,7 +4385,8 @@
           break;
         }
       }
-      token = next;
+      token = parseExpression(token);
+      ++count;
     }
     assert(optional('}', token));
     mayParseFunctionExpressions = old;
@@ -4424,14 +4465,13 @@
   /// ;
   /// ```
   Token parseMapLiteralEntry(Token token) {
-    listener.beginLiteralMapEntry(token.next);
     // Assume the listener rejects non-string keys.
     // TODO(brianwilkerson): Change the assumption above by moving error
     // checking into the parser, making it possible to recover.
     token = parseExpression(token);
     Token colon = ensureColon(token);
     token = parseExpression(colon);
-    listener.endLiteralMapEntry(colon, token.next);
+    listener.handleLiteralMapEntry(colon, token.next);
     return token;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index 9e43321..585fedf3 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -26,27 +26,27 @@
   /// Call this function when the token after [token] must be a type (not void).
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the type, inserting a synthetic type reference if
-  /// necessary. This may modify the token stream when parsing `>>` in valid
-  /// code or during recovery.
+  /// necessary. This may modify the token stream when parsing `>>` or `>>>`
+  /// in valid code or during recovery.
   Token ensureTypeNotVoid(Token token, Parser parser);
 
   /// Call this function when the token after [token] must be a type or void.
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the type, inserting a synthetic type reference if
-  /// necessary. This may modify the token stream when parsing `>>` in valid
-  /// code or during recovery.
+  /// necessary. This may modify the token stream when parsing `>>` or `>>>`
+  /// in valid code or during recovery.
   Token ensureTypeOrVoid(Token token, Parser parser);
 
   /// Call this function to parse an optional type (not void) after [token].
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the type. This may modify the token stream
-  /// when parsing `>>` in valid code or during recovery.
+  /// when parsing `>>` or `>>>` in valid code or during recovery.
   Token parseTypeNotVoid(Token token, Parser parser);
 
   /// Call this function to parse an optional type or void after [token].
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the type. This may modify the token stream
-  /// when parsing `>>` in valid code or during recovery.
+  /// when parsing `>>` or `>>>` in valid code or during recovery.
   Token parseType(Token token, Parser parser);
 
   /// Call this function with the [token] before the type to obtain
@@ -76,14 +76,14 @@
   /// Call this function to parse optional type arguments after [token].
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the arguments. This may modify the token stream
-  /// when parsing `>>` in valid code or during recovery.
+  /// when parsing `>>` or `>>>` in valid code or during recovery.
   Token parseArguments(Token token, Parser parser);
 
   /// Call this function to parse optional type parameters
   /// (also known as type variables) after [token].
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the parameters. This may modify the token stream
-  /// when parsing `>>` in valid code or during recovery.
+  /// when parsing `>>` or `>>>` in valid code or during recovery.
   Token parseVariables(Token token, Parser parser);
 
   /// Call this function with the [token] before the type var to obtain
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 7f959e9..f46d819 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
@@ -30,6 +30,7 @@
         skipMetadata,
         splitGtEq,
         splitGtFromGtGtEq,
+        splitGtFromGtGtGt,
         splitGtGt,
         syntheticGt;
 
@@ -990,16 +991,17 @@
   }
 }
 
-/// Return `true` if [token] is one of `>`, `>>`, `>=', or `>>=`.
+/// Return `true` if [token] is one of `>`, `>>`, `>=`, `>>>`, or `>>=`.
 bool isCloser(Token token) {
   final value = token.stringValue;
   return identical(value, '>') ||
       identical(value, '>>') ||
       identical(value, '>=') ||
+      identical(value, '>>>') ||
       identical(value, '>>=');
 }
 
-/// If [beforeCloser].next is one of `>`, `>>`, `>=', or `>>=`,
+/// If [beforeCloser].next is one of `>`, `>>`, `>=`, `>>>`, or `>>=`,
 /// then update the token stream and return `true`.
 bool parseCloser(Token beforeCloser) {
   Token unsplit = beforeCloser.next;
@@ -1015,7 +1017,7 @@
 }
 
 /// If [closer] is `>` then return it.
-/// If [closer] is one of `>>`, `>=', or `>>=` then split then token
+/// If [closer] is one of `>>`, `>=`, `>>>`, or `>>=` then split then token
 /// and return the leading `>` without updating the token stream.
 /// If [closer] is none of the above, then return null;
 Token splitCloser(Token closer) {
@@ -1026,6 +1028,8 @@
     return splitGtGt(closer);
   } else if (identical(value, '>=')) {
     return splitGtEq(closer);
+  } else if (identical(value, '>>>')) {
+    return splitGtFromGtGtGt(closer);
   } else if (identical(value, '>>=')) {
     return splitGtFromGtGtEq(closer);
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/util.dart b/pkg/front_end/lib/src/fasta/parser/util.dart
index 50937cb6..e02385f 100644
--- a/pkg/front_end/lib/src/fasta/parser/util.dart
+++ b/pkg/front_end/lib/src/fasta/parser/util.dart
@@ -178,6 +178,18 @@
       ..next = token.next);
 }
 
+/// Split `>>>` into two separate tokens... `>` followed by `>>`.
+/// Call [Token.setNext] to add the token to the stream.
+Token splitGtFromGtGtGt(Token token) {
+  assert(optional('>>>', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.GT_GT, token.charOffset + 1)
+      // Set next rather than calling Token.setNext
+      // so that the previous token is not set.
+      ..next = token.next);
+}
+
 /// Return a synthetic `<` followed by [next].
 /// Call [Token.setNext] to add the token to the stream.
 Token syntheticGt(Token next) {
diff --git a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
index 55266e8..6ac7640 100644
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
@@ -44,6 +44,11 @@
 
   final bool includeComments;
 
+  /// Experimental flag for enabling parsing of `>>>`.
+  /// See https://github.com/dart-lang/language/issues/61
+  /// and https://github.com/dart-lang/language/issues/60
+  bool enableGtGtGt = false;
+
   /**
    * The string offset for the next token that will be created.
    *
@@ -638,7 +643,7 @@
   }
 
   int tokenizeGreaterThan(int next) {
-    // > >= >> >>=
+    // > >= >> >>= >>>
     next = advance();
     if (identical($EQ, next)) {
       appendPrecedenceToken(TokenType.GT_EQ);
@@ -648,6 +653,9 @@
       if (identical($EQ, next)) {
         appendPrecedenceToken(TokenType.GT_GT_EQ);
         return advance();
+      } else if (enableGtGtGt && identical($GT, next)) {
+        appendPrecedenceToken(TokenType.GT_GT_GT);
+        return advance();
       } else {
         appendGtGt(TokenType.GT_GT);
         return next;
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index 3b60139..3778a4c 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -844,7 +844,7 @@
   }
 
   @override
-  void endLiteralMapEntry(Token colon, Token endToken) {
+  void handleLiteralMapEntry(Token colon, Token endToken) {
     debugEvent("LiteralMapEntry", colon);
     state.pop(); // Value.
     state.popPushNull("%LiteralMapEntry%", colon); // Key.
diff --git a/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart b/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
index 5e2944d..fbfe897 100644
--- a/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
+++ b/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
@@ -128,7 +128,8 @@
 
   Future<Result<Component>> run(Component component, dynamic context) async {
     StringBuffer messages = context.componentToDiagnostics[component];
-    Uri uri = component.uriToSource.keys.first;
+    Uri uri = component.uriToSource.keys
+        .firstWhere((uri) => uri != null && uri.scheme == "file");
     Library library = component.libraries
         .firstWhere((Library library) => library.importUri.scheme != "dart");
     Uri base = uri.resolve(".");
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 50223d0..bb76249 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
@@ -54,7 +54,9 @@
 import 'package:kernel/core_types.dart' show CoreTypes;
 
 import 'package:kernel/type_algebra.dart'
-    show calculateBounds, getFreshTypeParameters, Substitution;
+    show getFreshTypeParameters, Substitution;
+
+import 'package:kernel/src/bounds_checks.dart' show calculateBounds;
 
 import '../../base/instrumentation.dart'
     show
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 f3f7c2c..975eda8 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -2,11 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:convert';
+
 import 'package:front_end/src/fasta/messages.dart';
 import 'package:front_end/src/fasta/parser.dart';
 import 'package:front_end/src/fasta/parser/type_info.dart';
 import 'package:front_end/src/fasta/parser/type_info_impl.dart';
-import 'package:front_end/src/fasta/scanner.dart';
+import 'package:front_end/src/fasta/scanner.dart' hide scanString;
+import 'package:front_end/src/fasta/scanner/recover.dart'
+    show defaultRecoveryStrategy;
 import 'package:front_end/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -26,6 +30,35 @@
   });
 }
 
+/// TODO(danrubel): Remove this and use scanner.dart scanString
+/// once support for `>>>` is permanently enabled.
+///
+/// Scan/tokenize the given [source].
+/// If [recover] is null, then the [defaultRecoveryStrategy] is used.
+ScannerResult scanString(String source,
+    {bool includeComments: false,
+    bool scanLazyAssignmentOperators: false,
+    Recover recover}) {
+  assert(source != null, 'source must not be null');
+  StringScanner scanner =
+      new StringScanner(source, includeComments: includeComments)
+        ..enableGtGtGt = true;
+  return _tokenizeAndRecover(scanner, recover, source: source);
+}
+
+/// TODO(danrubel): Remove this once support for `>>>` is permanently enabled.
+ScannerResult _tokenizeAndRecover(Scanner scanner, Recover recover,
+    {List<int> bytes, String source}) {
+  Token tokens = scanner.tokenize();
+  if (scanner.hasErrors) {
+    if (bytes == null) bytes = utf8.encode(source);
+    recover ??= defaultRecoveryStrategy;
+    tokens = recover(bytes, tokens, scanner.lineStarts);
+  }
+  return new ScannerResult(
+      tokens, scanner.lineStarts, scanner.hasErrors, scanner.errors);
+}
+
 @reflectiveTest
 class NoTypeInfoTest {
   void test_basic() {
@@ -1250,6 +1283,39 @@
           'handleType S',
           'endTypeArguments 1 < >'
         ]);
+    expectComplexTypeArg('<S<T<U>>>', typeArgumentCount: 1, expectedCalls: [
+      'beginTypeArguments <',
+      'handleIdentifier S typeReference',
+      'beginTypeArguments <',
+      'handleIdentifier T typeReference',
+      'beginTypeArguments <',
+      'handleIdentifier U typeReference',
+      'handleNoTypeArguments >>>',
+      'handleType U',
+      'endTypeArguments 1 < >',
+      'handleType T',
+      'endTypeArguments 1 < >',
+      'handleType S',
+      'endTypeArguments 1 < >'
+    ]);
+    expectComplexTypeArg('<S<T<U,V>>>', typeArgumentCount: 1, expectedCalls: [
+      'beginTypeArguments <',
+      'handleIdentifier S typeReference',
+      'beginTypeArguments <',
+      'handleIdentifier T typeReference',
+      'beginTypeArguments <',
+      'handleIdentifier U typeReference',
+      'handleNoTypeArguments ,',
+      'handleType U',
+      'handleIdentifier V typeReference',
+      'handleNoTypeArguments >>>',
+      'handleType V',
+      'endTypeArguments 2 < >',
+      'handleType T',
+      'endTypeArguments 1 < >',
+      'handleType S',
+      'endTypeArguments 1 < >'
+    ]);
     expectComplexTypeArg('<S<Function()>>',
         typeArgumentCount: 1,
         expectedCalls: [
@@ -1299,6 +1365,26 @@
           'handleType S',
           'endTypeArguments 1 < >'
         ]);
+    expectComplexTypeArg('<S<T<void Function()>>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'beginTypeArguments <',
+          'handleNoTypeVariables (',
+          'beginFunctionType void', // was 'beginFunctionType Function'
+          'handleVoidKeyword void', // was 'handleNoType <'
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeArguments 1 < >',
+          'handleType T',
+          'endTypeArguments 1 < >',
+          'handleType S',
+          'endTypeArguments 1 < >'
+        ]);
   }
 
   void test_computeTypeArg_complex_recovery() {
@@ -1751,7 +1837,7 @@
           'handleIdentifier List typeReference',
           'beginTypeArguments <',
           'handleIdentifier T typeReference',
-          'handleNoTypeArguments >',
+          'handleNoTypeArguments >>>',
           'handleType T',
           'endTypeArguments 1 < >',
           'handleType List',
@@ -1760,6 +1846,32 @@
           'endTypeVariable > 0 extends',
           'endTypeVariables < >'
         ]);
+    expectComplexTypeParam('<T extends List<Map<S, T>>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'handleTypeVariablesDefined > 1',
+          'handleIdentifier List typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier Map typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments ,',
+          'handleType S',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >>>',
+          'handleType T',
+          'endTypeArguments 2 < >',
+          'handleType Map',
+          'endTypeArguments 1 < >',
+          'handleType List',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >'
+        ]);
   }
 
   void test_computeTypeParam_34850() {
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
index ea0190d..9ae979a 100644
--- a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -6,6 +6,10 @@
 import 'dart:io' show Directory, File;
 
 import 'package:expect/expect.dart' show Expect;
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+import 'package:kernel/kernel.dart' show Component;
 
 import 'incremental_load_from_dill_test.dart'
     show normalCompile, initializedCompile, checkIsEqual;
@@ -35,6 +39,30 @@
   Stopwatch stopwatch = new Stopwatch()..start();
   await normalCompile(dart2jsUrl, normalDill);
   print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
+  {
+    // Check that we don't include the source from files from the sdk.
+    final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+    Uri platformUri = sdkRoot.resolve("vm_platform.dill");
+    Component cSdk = new Component();
+    new BinaryBuilder(new File.fromUri(platformUri).readAsBytesSync(),
+            disableLazyReading: false)
+        .readComponent(cSdk);
+
+    Component c = new Component();
+    new BinaryBuilder(new File.fromUri(normalDill).readAsBytesSync(),
+            disableLazyReading: false)
+        .readComponent(c);
+    for (Uri uri in c.uriToSource.keys) {
+      if (cSdk.uriToSource.containsKey(uri)) {
+        if ((c.uriToSource[uri].source?.length ?? 0) != 0) {
+          throw "Compile contained sources for the sdk $uri";
+        }
+        if ((c.uriToSource[uri].lineStarts?.length ?? 0) != 0) {
+          throw "Compile contained line starts for the sdk $uri";
+        }
+      }
+    }
+  }
 
   // Compile dart2js, initializing from the just-compiled dill,
   // a nonexisting file and a dill file that isn't valid.
diff --git a/pkg/front_end/testcases/bug34511.dart b/pkg/front_end/testcases/bug34511.dart
new file mode 100644
index 0000000..d8ad848
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// See http://dartbug.com/34511 for details.
+
+class A<X> {}
+
+class B<Z> extends Object with A<Z Function()> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/bug34511.dart.legacy.expect b/pkg/front_end/testcases/bug34511.dart.legacy.expect
new file mode 100644
index 0000000..ebad4e6
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.legacy.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> = core::Object with self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug34511.dart.legacy.transformed.expect b/pkg/front_end/testcases/bug34511.dart.legacy.transformed.expect
new file mode 100644
index 0000000..739a1e4
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.legacy.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> extends core::Object implements self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug34511.dart.outline.expect b/pkg/front_end/testcases/bug34511.dart.outline.expect
new file mode 100644
index 0000000..0291dc5
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> = core::Object with self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/bug34511.dart.strong.expect b/pkg/front_end/testcases/bug34511.dart.strong.expect
new file mode 100644
index 0000000..ebad4e6
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.strong.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> = core::Object with self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug34511.dart.strong.transformed.expect b/pkg/front_end/testcases/bug34511.dart.strong.transformed.expect
new file mode 100644
index 0000000..739a1e4
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> extends core::Object implements self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/clone_function_type.dart b/pkg/front_end/testcases/clone_function_type.dart
new file mode 100644
index 0000000..fd1d81e
--- /dev/null
+++ b/pkg/front_end/testcases/clone_function_type.dart
@@ -0,0 +1,258 @@
+// 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.
+
+// In the classes below the function type is cloned when the anonymous mixin
+// application is desugared into a named mixin application, in order to re-bind
+// the type builders for its subterms.
+
+// The case 'm1' covers function types with some missing parts.
+
+class Am1<X, Y> {}
+
+class Bm1<Z> extends Object with Am1<Function(int), Z> {}
+
+class Cm1<Z> extends Object with Am1<Function(int x), Z> {}
+
+class Dm1<Z> extends Object with Am1<int Function(), Z> {}
+
+class Em1<Z> extends Object with Am1<Function(), Z> {}
+
+// Compile-time error: Named parameters should have names.
+class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+
+class Gm1<Z> extends Object with Am1<Function({int x}), Z> {}
+
+class Hm1<Z> extends Object with Am1<Function([int]), Z> {}
+
+class Im1<Z> extends Object with Am1<Function([int x]), Z> {}
+
+class Jm1<Z> extends Object with Am1<Function, Z> {}
+
+class Km1<Z> extends Object with Am1<Function(Function Function), Z> {}
+
+class Lm1<Z> extends Object
+    with Am1<Function(Function Function() Function) Function(), Z> {}
+
+class Mm1<Z> = Object with Am1<Function(int), Z>;
+
+class Nm1<Z> = Object with Am1<Function(int x), Z>;
+
+class Om1<Z> = Object with Am1<int Function(), Z>;
+
+class Pm1<Z> = Object with Am1<Function(), Z>;
+
+// Compile-time error: Named parameters should have names.
+class Qm1<Z> = Object with Am1<Function({int}), Z>;
+
+class Rm1<Z> = Object with Am1<Function({int x}), Z>;
+
+class Sm1<Z> = Object with Am1<Function([int]), Z>;
+
+class Tm1<Z> = Object with Am1<Function([int x]), Z>;
+
+class Um1<Z> = Object with Am1<Function, Z>;
+
+class Vm1<Z> = Object with Am1<Function(Function Function), Z>;
+
+class Wm1<Z> = Object
+    with Am1<Function(Function Function() Function) Function(), Z>;
+
+// The case 'm2' covers function types with some missing parts that should be
+// checked against a bound.
+
+class Am2<X extends Function(), Y> {}
+
+// Compile-time error: type argument is not a subtype.
+class Bm2<Z> extends Object with Am2<Function(int), Z> {}
+
+// Compile-time error: type argument is not a subtype.
+class Cm2<Z> extends Object with Am2<Function(int x), Z> {}
+
+class Dm2<Z> extends Object with Am2<int Function(), Z> {}
+
+class Em2<Z> extends Object with Am2<Function(), Z> {}
+
+// Compile-time error: Named parameters should have names.
+class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+
+class Gm2<Z> extends Object with Am2<Function({int x}), Z> {}
+
+class Hm2<Z> extends Object with Am2<Function([int]), Z> {}
+
+class Im2<Z> extends Object with Am2<Function([int x]), Z> {}
+
+// Compile-time error: type argument is not a subtype.
+class Jm2<Z> extends Object with Am2<Function, Z> {}
+
+// Compile-time error: type argument is not a subtype.
+class Km2<Z> extends Object with Am2<Function(Function Function), Z> {}
+
+class Lm2<Z> extends Object
+    with Am2<Function(Function Function() Function) Function(), Z> {}
+
+// Compile-time error: type argument is not a subtype.
+class Mm2<Z> = Object with Am2<Function(int), Z>;
+
+// Compile-time error: type argument is not a subtype.
+class Nm2<Z> = Object with Am2<Function(int x), Z>;
+
+class Om2<Z> = Object with Am2<int Function(), Z>;
+
+class Pm2<Z> = Object with Am2<Function(), Z>;
+
+// Compile-time error: Named parameters should have names.
+class Qm2<Z> = Object with Am2<Function({int}), Z>;
+
+class Rm2<Z> = Object with Am2<Function({int x}), Z>;
+
+class Sm2<Z> = Object with Am2<Function([int]), Z>;
+
+class Tm2<Z> = Object with Am2<Function([int x]), Z>;
+
+// Compile-time error: type argument is not a subtype.
+class Um2<Z> = Object with Am2<Function, Z>;
+
+// Compile-time error: type argument is not a subtype.
+class Vm2<Z> = Object with Am2<Function(Function Function), Z>;
+
+class Wm2<Z> = Object
+    with Am2<Function(Function Function() Function) Function(), Z>;
+
+// The case 'm3' covers function types with some missing parts defined via
+// typedefs.
+
+typedef TdB = Function(int);
+
+typedef TdC = Function(int x);
+
+typedef TdD = int Function();
+
+typedef TdE = Function();
+
+// Compile-time error: Named parameters should have names.
+typedef TdF = Function({int});
+
+typedef TdG = Function({int x});
+
+typedef TdH = Function([int]);
+
+typedef TdI = Function([int x]);
+
+typedef TdJ = Function(Function Function);
+
+typedef TdK = Function(Function Function() Function) Function();
+
+class Am3<L, Y> {}
+
+class Bm3<Z> extends Object with Am3<TdB, Z> {}
+
+class Cm3<Z> extends Object with Am3<TdC, Z> {}
+
+class Dm3<Z> extends Object with Am3<TdD, Z> {}
+
+class Em3<Z> extends Object with Am3<TdE, Z> {}
+
+class Fm3<Z> extends Object with Am3<TdF, Z> {}
+
+class Gm3<Z> extends Object with Am3<TdG, Z> {}
+
+class Hm3<Z> extends Object with Am3<TdH, Z> {}
+
+class Im3<Z> extends Object with Am3<TdI, Z> {}
+
+class Jm3<Z> extends Object with Am3<TdJ, Z> {}
+
+class Km3<Z> extends Object with Am3<TdK, Z> {}
+
+// In case cloning will not be used in the examples above, here are some
+// examples that should utilize cloning of type builders and that should cover
+// some of the cases above.  Here, type variables of the class are cloned for
+// its factories, including the bounds that are type builders.
+
+class Af1<X extends Function(int)> {
+  factory Af1.foo() => null;
+}
+
+class Bf1<X extends Function(int x)> {
+  factory Bf1.foo() => null;
+}
+
+class Cf1<X extends int Function()> {
+  factory Cf1.foo() => null;
+}
+
+class Df1<X extends Function()> {
+  factory Df1.foo() => null;
+}
+
+// Compile-time error: Named parameters should have names.
+class Ef1<X extends Function({int})> {
+  factory Ef1.foo() => null;
+}
+
+class Ff1<X extends Function({int x})> {
+  factory Ff1.foo() => null;
+}
+
+class Gf1<X extends Function([int])> {
+  factory Gf1.foo() => null;
+}
+
+class Hf1<X extends Function([int x])> {
+  factory Hf1.foo() => null;
+}
+
+class If1<X extends Function> {
+  factory If1.foo() => null;
+}
+
+class Jf1<X extends Function(Function Function)> {
+  factory Jf1.foo() => null;
+}
+
+class Kf1<X extends Function(Function Function() Function) Function()> {
+  factory Kf1.foo() => null;
+}
+
+class Bf2<X extends TdB> {
+  factory Bf2.foo() => null;
+}
+
+class Cf2<X extends TdC> {
+  factory Cf2.foo() => null;
+}
+
+class Df2<X extends TdD> {
+  factory Df2.foo() => null;
+}
+
+class Ef2<X extends TdE> {
+  factory Ef2.foo() => null;
+}
+
+class Ff2<X extends TdF> {
+  factory Ff2.foo() => null;
+}
+
+class Gf2<X extends TdG> {
+  factory Gf2.foo() => null;
+}
+
+class Hf2<X extends TdH> {
+  factory Hf2.foo() => null;
+}
+
+class If2<X extends TdI> {
+  factory If2.foo() => null;
+}
+
+class Jf2<X extends TdJ> {
+  factory Jf2.foo() => null;
+}
+
+class Kf2<X extends TdK> {
+  factory Kf2.foo() => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/clone_function_type.dart.legacy.expect b/pkg/front_end/testcases/clone_function_type.dart.legacy.expect
new file mode 100644
index 0000000..a1b55e6
--- /dev/null
+++ b/pkg/front_end/testcases/clone_function_type.dart.legacy.expect
@@ -0,0 +1,596 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TdB = (core::int) → dynamic;
+typedef TdC = (core::int) → dynamic;
+typedef TdD = () → core::int;
+typedef TdE = () → dynamic;
+typedef TdF = () → dynamic;
+typedef TdG = ({x: core::int}) → dynamic;
+typedef TdH = ([core::int]) → dynamic;
+typedef TdI = ([core::int]) → dynamic;
+typedef TdJ = (core::Function) → dynamic;
+typedef TdK = () → (() → core::Function) → dynamic;
+class Am1<X extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am1<self::Am1::X, self::Am1::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::_Bm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm1<Z extends core::Object = dynamic> extends self::_Bm1&Object&Am1<self::Bm1::Z> {
+  synthetic constructor •() → self::Bm1<self::Bm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::_Cm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm1<Z extends core::Object = dynamic> extends self::_Cm1&Object&Am1<self::Cm1::Z> {
+  synthetic constructor •() → self::Cm1<self::Cm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → core::int, self::_Dm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm1<Z extends core::Object = dynamic> extends self::_Dm1&Object&Am1<self::Dm1::Z> {
+  synthetic constructor •() → self::Dm1<self::Dm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::_Em1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Em1<Z extends core::Object = dynamic> extends self::_Em1&Object&Am1<self::Em1::Z> {
+  synthetic constructor •() → self::Em1<self::Em1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::_Fm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm1<Z extends core::Object = dynamic> extends self::_Fm1&Object&Am1<self::Fm1::Z> {
+  synthetic constructor •() → self::Fm1<self::Fm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<({x: core::int}) → dynamic, self::_Gm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm1<Z extends core::Object = dynamic> extends self::_Gm1&Object&Am1<self::Gm1::Z> {
+  synthetic constructor •() → self::Gm1<self::Gm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::_Hm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm1<Z extends core::Object = dynamic> extends self::_Hm1&Object&Am1<self::Hm1::Z> {
+  synthetic constructor •() → self::Hm1<self::Hm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::_Im1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Im1<Z extends core::Object = dynamic> extends self::_Im1&Object&Am1<self::Im1::Z> {
+  synthetic constructor •() → self::Im1<self::Im1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<core::Function, self::_Jm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm1<Z extends core::Object = dynamic> extends self::_Jm1&Object&Am1<self::Jm1::Z> {
+  synthetic constructor •() → self::Jm1<self::Jm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::Function) → dynamic, self::_Km1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Km1<Z extends core::Object = dynamic> extends self::_Km1&Object&Am1<self::Km1::Z> {
+  synthetic constructor •() → self::Km1<self::Km1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → (() → core::Function) → dynamic, self::_Lm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm1<Z extends core::Object = dynamic> extends self::_Lm1&Object&Am1<self::Lm1::Z> {
+  synthetic constructor •() → self::Lm1<self::Lm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::Mm1::Z> {
+  synthetic constructor •() → self::Mm1<self::Mm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::Nm1::Z> {
+  synthetic constructor •() → self::Nm1<self::Nm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Om1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → core::int, self::Om1::Z> {
+  synthetic constructor •() → self::Om1<self::Om1::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::Pm1::Z> {
+  synthetic constructor •() → self::Pm1<self::Pm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::Qm1::Z> {
+  synthetic constructor •() → self::Qm1<self::Qm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm1<Z extends core::Object = dynamic> = core::Object with self::Am1<({x: core::int}) → dynamic, self::Rm1::Z> {
+  synthetic constructor •() → self::Rm1<self::Rm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::Sm1::Z> {
+  synthetic constructor •() → self::Sm1<self::Sm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::Tm1::Z> {
+  synthetic constructor •() → self::Tm1<self::Tm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Um1<Z extends core::Object = dynamic> = core::Object with self::Am1<core::Function, self::Um1::Z> {
+  synthetic constructor •() → self::Um1<self::Um1::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::Function) → dynamic, self::Vm1::Z> {
+  synthetic constructor •() → self::Vm1<self::Vm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → (() → core::Function) → dynamic, self::Wm1::Z> {
+  synthetic constructor •() → self::Wm1<self::Wm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Am2<X extends () → dynamic = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am2<self::Am2::X, self::Am2::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::_Bm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm2<Z extends core::Object = dynamic> extends self::_Bm2&Object&Am2<self::Bm2::Z> {
+  synthetic constructor •() → self::Bm2<self::Bm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::_Cm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm2<Z extends core::Object = dynamic> extends self::_Cm2&Object&Am2<self::Cm2::Z> {
+  synthetic constructor •() → self::Cm2<self::Cm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → core::int, self::_Dm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm2<Z extends core::Object = dynamic> extends self::_Dm2&Object&Am2<self::Dm2::Z> {
+  synthetic constructor •() → self::Dm2<self::Dm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::_Em2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Em2<Z extends core::Object = dynamic> extends self::_Em2&Object&Am2<self::Em2::Z> {
+  synthetic constructor •() → self::Em2<self::Em2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::_Fm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm2<Z extends core::Object = dynamic> extends self::_Fm2&Object&Am2<self::Fm2::Z> {
+  synthetic constructor •() → self::Fm2<self::Fm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<({x: core::int}) → dynamic, self::_Gm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm2<Z extends core::Object = dynamic> extends self::_Gm2&Object&Am2<self::Gm2::Z> {
+  synthetic constructor •() → self::Gm2<self::Gm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::_Hm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm2<Z extends core::Object = dynamic> extends self::_Hm2&Object&Am2<self::Hm2::Z> {
+  synthetic constructor •() → self::Hm2<self::Hm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::_Im2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Im2<Z extends core::Object = dynamic> extends self::_Im2&Object&Am2<self::Im2::Z> {
+  synthetic constructor •() → self::Im2<self::Im2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<core::Function, self::_Jm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm2<Z extends core::Object = dynamic> extends self::_Jm2&Object&Am2<self::Jm2::Z> {
+  synthetic constructor •() → self::Jm2<self::Jm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::Function) → dynamic, self::_Km2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Km2<Z extends core::Object = dynamic> extends self::_Km2&Object&Am2<self::Km2::Z> {
+  synthetic constructor •() → self::Km2<self::Km2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → (() → core::Function) → dynamic, self::_Lm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm2<Z extends core::Object = dynamic> extends self::_Lm2&Object&Am2<self::Lm2::Z> {
+  synthetic constructor •() → self::Lm2<self::Lm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::Mm2::Z> {
+  synthetic constructor •() → self::Mm2<self::Mm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::Nm2::Z> {
+  synthetic constructor •() → self::Nm2<self::Nm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Om2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → core::int, self::Om2::Z> {
+  synthetic constructor •() → self::Om2<self::Om2::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::Pm2::Z> {
+  synthetic constructor •() → self::Pm2<self::Pm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::Qm2::Z> {
+  synthetic constructor •() → self::Qm2<self::Qm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm2<Z extends core::Object = dynamic> = core::Object with self::Am2<({x: core::int}) → dynamic, self::Rm2::Z> {
+  synthetic constructor •() → self::Rm2<self::Rm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::Sm2::Z> {
+  synthetic constructor •() → self::Sm2<self::Sm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::Tm2::Z> {
+  synthetic constructor •() → self::Tm2<self::Tm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Um2<Z extends core::Object = dynamic> = core::Object with self::Am2<core::Function, self::Um2::Z> {
+  synthetic constructor •() → self::Um2<self::Um2::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::Function) → dynamic, self::Vm2::Z> {
+  synthetic constructor •() → self::Vm2<self::Vm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → (() → core::Function) → dynamic, self::Wm2::Z> {
+  synthetic constructor •() → self::Wm2<self::Wm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Am3<L extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am3<self::Am3::L, self::Am3::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::int) → dynamic, self::_Bm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm3<Z extends core::Object = dynamic> extends self::_Bm3&Object&Am3<self::Bm3::Z> {
+  synthetic constructor •() → self::Bm3<self::Bm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::int) → dynamic, self::_Cm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm3<Z extends core::Object = dynamic> extends self::_Cm3&Object&Am3<self::Cm3::Z> {
+  synthetic constructor •() → self::Cm3<self::Cm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → core::int, self::_Dm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm3<Z extends core::Object = dynamic> extends self::_Dm3&Object&Am3<self::Dm3::Z> {
+  synthetic constructor •() → self::Dm3<self::Dm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → dynamic, self::_Em3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Em3<Z extends core::Object = dynamic> extends self::_Em3&Object&Am3<self::Em3::Z> {
+  synthetic constructor •() → self::Em3<self::Em3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → dynamic, self::_Fm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm3<Z extends core::Object = dynamic> extends self::_Fm3&Object&Am3<self::Fm3::Z> {
+  synthetic constructor •() → self::Fm3<self::Fm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<({x: core::int}) → dynamic, self::_Gm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm3<Z extends core::Object = dynamic> extends self::_Gm3&Object&Am3<self::Gm3::Z> {
+  synthetic constructor •() → self::Gm3<self::Gm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<([core::int]) → dynamic, self::_Hm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm3<Z extends core::Object = dynamic> extends self::_Hm3&Object&Am3<self::Hm3::Z> {
+  synthetic constructor •() → self::Hm3<self::Hm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<([core::int]) → dynamic, self::_Im3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Im3<Z extends core::Object = dynamic> extends self::_Im3&Object&Am3<self::Im3::Z> {
+  synthetic constructor •() → self::Im3<self::Im3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::Function) → dynamic, self::_Jm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm3<Z extends core::Object = dynamic> extends self::_Jm3&Object&Am3<self::Jm3::Z> {
+  synthetic constructor •() → self::Jm3<self::Jm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → (() → core::Function) → dynamic, self::_Km3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Km3<Z extends core::Object = dynamic> extends self::_Km3&Object&Am3<self::Km3::Z> {
+  synthetic constructor •() → self::Km3<self::Km3::Z>
+    : super core::Object::•()
+    ;
+}
+class Af1<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Af1<self::Af1::foo::X>
+    return null;
+}
+class Bf1<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X>
+    return null;
+}
+class Cf1<X extends () → core::int = dynamic> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Cf1<self::Cf1::foo::X>
+    return null;
+}
+class Df1<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Df1<self::Df1::foo::X>
+    return null;
+}
+class Ef1<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X>
+    return null;
+}
+class Ff1<X extends ({x: core::int}) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X>
+    return null;
+}
+class Gf1<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X>
+    return null;
+}
+class Hf1<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X>
+    return null;
+}
+class If1<X extends core::Function = dynamic> extends core::Object {
+  static factory foo<X extends core::Function = dynamic>() → self::If1<self::If1::foo::X>
+    return null;
+}
+class Jf1<X extends (core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X>
+    return null;
+}
+class Kf1<X extends () → (() → core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X>
+    return null;
+}
+class Bf2<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X>
+    return null;
+}
+class Cf2<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X>
+    return null;
+}
+class Df2<X extends () → core::int = dynamic> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Df2<self::Df2::foo::X>
+    return null;
+}
+class Ef2<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X>
+    return null;
+}
+class Ff2<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X>
+    return null;
+}
+class Gf2<X extends ({x: core::int}) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X>
+    return null;
+}
+class Hf2<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X>
+    return null;
+}
+class If2<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::If2<self::If2::foo::X>
+    return null;
+}
+class Jf2<X extends (core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X>
+    return null;
+}
+class Kf2<X extends () → (() → core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X>
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/clone_function_type.dart.legacy.transformed.expect b/pkg/front_end/testcases/clone_function_type.dart.legacy.transformed.expect
new file mode 100644
index 0000000..8508c16
--- /dev/null
+++ b/pkg/front_end/testcases/clone_function_type.dart.legacy.transformed.expect
@@ -0,0 +1,570 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TdB = (core::int) → dynamic;
+typedef TdC = (core::int) → dynamic;
+typedef TdD = () → core::int;
+typedef TdE = () → dynamic;
+typedef TdF = () → dynamic;
+typedef TdG = ({x: core::int}) → dynamic;
+typedef TdH = ([core::int]) → dynamic;
+typedef TdI = ([core::int]) → dynamic;
+typedef TdJ = (core::Function) → dynamic;
+typedef TdK = () → (() → core::Function) → dynamic;
+class Am1<X extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am1<self::Am1::X, self::Am1::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::_Bm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm1<Z extends core::Object = dynamic> extends self::_Bm1&Object&Am1<self::Bm1::Z> {
+  synthetic constructor •() → self::Bm1<self::Bm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::_Cm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm1<Z extends core::Object = dynamic> extends self::_Cm1&Object&Am1<self::Cm1::Z> {
+  synthetic constructor •() → self::Cm1<self::Cm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → core::int, self::_Dm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm1<Z extends core::Object = dynamic> extends self::_Dm1&Object&Am1<self::Dm1::Z> {
+  synthetic constructor •() → self::Dm1<self::Dm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::_Em1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Em1<Z extends core::Object = dynamic> extends self::_Em1&Object&Am1<self::Em1::Z> {
+  synthetic constructor •() → self::Em1<self::Em1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::_Fm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm1<Z extends core::Object = dynamic> extends self::_Fm1&Object&Am1<self::Fm1::Z> {
+  synthetic constructor •() → self::Fm1<self::Fm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<({x: core::int}) → dynamic, self::_Gm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm1<Z extends core::Object = dynamic> extends self::_Gm1&Object&Am1<self::Gm1::Z> {
+  synthetic constructor •() → self::Gm1<self::Gm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::_Hm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm1<Z extends core::Object = dynamic> extends self::_Hm1&Object&Am1<self::Hm1::Z> {
+  synthetic constructor •() → self::Hm1<self::Hm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::_Im1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Im1<Z extends core::Object = dynamic> extends self::_Im1&Object&Am1<self::Im1::Z> {
+  synthetic constructor •() → self::Im1<self::Im1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<core::Function, self::_Jm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm1<Z extends core::Object = dynamic> extends self::_Jm1&Object&Am1<self::Jm1::Z> {
+  synthetic constructor •() → self::Jm1<self::Jm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::Function) → dynamic, self::_Km1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Km1<Z extends core::Object = dynamic> extends self::_Km1&Object&Am1<self::Km1::Z> {
+  synthetic constructor •() → self::Km1<self::Km1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → (() → core::Function) → dynamic, self::_Lm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm1<Z extends core::Object = dynamic> extends self::_Lm1&Object&Am1<self::Lm1::Z> {
+  synthetic constructor •() → self::Lm1<self::Lm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::Mm1::Z> {
+  synthetic constructor •() → self::Mm1<self::Mm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::Nm1::Z> {
+  synthetic constructor •() → self::Nm1<self::Nm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Om1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → core::int, self::Om1::Z> {
+  synthetic constructor •() → self::Om1<self::Om1::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::Pm1::Z> {
+  synthetic constructor •() → self::Pm1<self::Pm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::Qm1::Z> {
+  synthetic constructor •() → self::Qm1<self::Qm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<({x: core::int}) → dynamic, self::Rm1::Z> {
+  synthetic constructor •() → self::Rm1<self::Rm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::Sm1::Z> {
+  synthetic constructor •() → self::Sm1<self::Sm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::Tm1::Z> {
+  synthetic constructor •() → self::Tm1<self::Tm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Um1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<core::Function, self::Um1::Z> {
+  synthetic constructor •() → self::Um1<self::Um1::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::Function) → dynamic, self::Vm1::Z> {
+  synthetic constructor •() → self::Vm1<self::Vm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → (() → core::Function) → dynamic, self::Wm1::Z> {
+  synthetic constructor •() → self::Wm1<self::Wm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Am2<X extends () → dynamic = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am2<self::Am2::X, self::Am2::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::_Bm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm2<Z extends core::Object = dynamic> extends self::_Bm2&Object&Am2<self::Bm2::Z> {
+  synthetic constructor •() → self::Bm2<self::Bm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::_Cm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm2<Z extends core::Object = dynamic> extends self::_Cm2&Object&Am2<self::Cm2::Z> {
+  synthetic constructor •() → self::Cm2<self::Cm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → core::int, self::_Dm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm2<Z extends core::Object = dynamic> extends self::_Dm2&Object&Am2<self::Dm2::Z> {
+  synthetic constructor •() → self::Dm2<self::Dm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::_Em2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Em2<Z extends core::Object = dynamic> extends self::_Em2&Object&Am2<self::Em2::Z> {
+  synthetic constructor •() → self::Em2<self::Em2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::_Fm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm2<Z extends core::Object = dynamic> extends self::_Fm2&Object&Am2<self::Fm2::Z> {
+  synthetic constructor •() → self::Fm2<self::Fm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<({x: core::int}) → dynamic, self::_Gm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm2<Z extends core::Object = dynamic> extends self::_Gm2&Object&Am2<self::Gm2::Z> {
+  synthetic constructor •() → self::Gm2<self::Gm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::_Hm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm2<Z extends core::Object = dynamic> extends self::_Hm2&Object&Am2<self::Hm2::Z> {
+  synthetic constructor •() → self::Hm2<self::Hm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::_Im2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Im2<Z extends core::Object = dynamic> extends self::_Im2&Object&Am2<self::Im2::Z> {
+  synthetic constructor •() → self::Im2<self::Im2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<core::Function, self::_Jm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm2<Z extends core::Object = dynamic> extends self::_Jm2&Object&Am2<self::Jm2::Z> {
+  synthetic constructor •() → self::Jm2<self::Jm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::Function) → dynamic, self::_Km2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Km2<Z extends core::Object = dynamic> extends self::_Km2&Object&Am2<self::Km2::Z> {
+  synthetic constructor •() → self::Km2<self::Km2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → (() → core::Function) → dynamic, self::_Lm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm2<Z extends core::Object = dynamic> extends self::_Lm2&Object&Am2<self::Lm2::Z> {
+  synthetic constructor •() → self::Lm2<self::Lm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::Mm2::Z> {
+  synthetic constructor •() → self::Mm2<self::Mm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::Nm2::Z> {
+  synthetic constructor •() → self::Nm2<self::Nm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Om2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → core::int, self::Om2::Z> {
+  synthetic constructor •() → self::Om2<self::Om2::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::Pm2::Z> {
+  synthetic constructor •() → self::Pm2<self::Pm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::Qm2::Z> {
+  synthetic constructor •() → self::Qm2<self::Qm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<({x: core::int}) → dynamic, self::Rm2::Z> {
+  synthetic constructor •() → self::Rm2<self::Rm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::Sm2::Z> {
+  synthetic constructor •() → self::Sm2<self::Sm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::Tm2::Z> {
+  synthetic constructor •() → self::Tm2<self::Tm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Um2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<core::Function, self::Um2::Z> {
+  synthetic constructor •() → self::Um2<self::Um2::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::Function) → dynamic, self::Vm2::Z> {
+  synthetic constructor •() → self::Vm2<self::Vm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → (() → core::Function) → dynamic, self::Wm2::Z> {
+  synthetic constructor •() → self::Wm2<self::Wm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Am3<L extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am3<self::Am3::L, self::Am3::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<(core::int) → dynamic, self::_Bm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm3<Z extends core::Object = dynamic> extends self::_Bm3&Object&Am3<self::Bm3::Z> {
+  synthetic constructor •() → self::Bm3<self::Bm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<(core::int) → dynamic, self::_Cm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm3<Z extends core::Object = dynamic> extends self::_Cm3&Object&Am3<self::Cm3::Z> {
+  synthetic constructor •() → self::Cm3<self::Cm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → core::int, self::_Dm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm3<Z extends core::Object = dynamic> extends self::_Dm3&Object&Am3<self::Dm3::Z> {
+  synthetic constructor •() → self::Dm3<self::Dm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → dynamic, self::_Em3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Em3<Z extends core::Object = dynamic> extends self::_Em3&Object&Am3<self::Em3::Z> {
+  synthetic constructor •() → self::Em3<self::Em3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → dynamic, self::_Fm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm3<Z extends core::Object = dynamic> extends self::_Fm3&Object&Am3<self::Fm3::Z> {
+  synthetic constructor •() → self::Fm3<self::Fm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<({x: core::int}) → dynamic, self::_Gm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm3<Z extends core::Object = dynamic> extends self::_Gm3&Object&Am3<self::Gm3::Z> {
+  synthetic constructor •() → self::Gm3<self::Gm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<([core::int]) → dynamic, self::_Hm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm3<Z extends core::Object = dynamic> extends self::_Hm3&Object&Am3<self::Hm3::Z> {
+  synthetic constructor •() → self::Hm3<self::Hm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<([core::int]) → dynamic, self::_Im3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Im3<Z extends core::Object = dynamic> extends self::_Im3&Object&Am3<self::Im3::Z> {
+  synthetic constructor •() → self::Im3<self::Im3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<(core::Function) → dynamic, self::_Jm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm3<Z extends core::Object = dynamic> extends self::_Jm3&Object&Am3<self::Jm3::Z> {
+  synthetic constructor •() → self::Jm3<self::Jm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → (() → core::Function) → dynamic, self::_Km3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Km3<Z extends core::Object = dynamic> extends self::_Km3&Object&Am3<self::Km3::Z> {
+  synthetic constructor •() → self::Km3<self::Km3::Z>
+    : super core::Object::•()
+    ;
+}
+class Af1<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Af1<self::Af1::foo::X>
+    return null;
+}
+class Bf1<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X>
+    return null;
+}
+class Cf1<X extends () → core::int = dynamic> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Cf1<self::Cf1::foo::X>
+    return null;
+}
+class Df1<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Df1<self::Df1::foo::X>
+    return null;
+}
+class Ef1<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X>
+    return null;
+}
+class Ff1<X extends ({x: core::int}) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X>
+    return null;
+}
+class Gf1<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X>
+    return null;
+}
+class Hf1<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X>
+    return null;
+}
+class If1<X extends core::Function = dynamic> extends core::Object {
+  static factory foo<X extends core::Function = dynamic>() → self::If1<self::If1::foo::X>
+    return null;
+}
+class Jf1<X extends (core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X>
+    return null;
+}
+class Kf1<X extends () → (() → core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X>
+    return null;
+}
+class Bf2<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X>
+    return null;
+}
+class Cf2<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X>
+    return null;
+}
+class Df2<X extends () → core::int = dynamic> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Df2<self::Df2::foo::X>
+    return null;
+}
+class Ef2<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X>
+    return null;
+}
+class Ff2<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X>
+    return null;
+}
+class Gf2<X extends ({x: core::int}) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X>
+    return null;
+}
+class Hf2<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X>
+    return null;
+}
+class If2<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::If2<self::If2::foo::X>
+    return null;
+}
+class Jf2<X extends (core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X>
+    return null;
+}
+class Kf2<X extends () → (() → core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X>
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/clone_function_type.dart.outline.expect
new file mode 100644
index 0000000..7b8504c
--- /dev/null
+++ b/pkg/front_end/testcases/clone_function_type.dart.outline.expect
@@ -0,0 +1,536 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TdB = (core::int) → dynamic;
+typedef TdC = (core::int) → dynamic;
+typedef TdD = () → core::int;
+typedef TdE = () → dynamic;
+typedef TdF = () → dynamic;
+typedef TdG = ({x: core::int}) → dynamic;
+typedef TdH = ([core::int]) → dynamic;
+typedef TdI = ([core::int]) → dynamic;
+typedef TdJ = (core::Function) → dynamic;
+typedef TdK = () → (() → core::Function) → dynamic;
+class Am1<X extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am1<self::Am1::X, self::Am1::Y>
+    ;
+}
+abstract class _Bm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::_Bm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm1<Z extends core::Object = dynamic> extends self::_Bm1&Object&Am1<self::Bm1::Z> {
+  synthetic constructor •() → self::Bm1<self::Bm1::Z>
+    ;
+}
+abstract class _Cm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::_Cm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm1<Z extends core::Object = dynamic> extends self::_Cm1&Object&Am1<self::Cm1::Z> {
+  synthetic constructor •() → self::Cm1<self::Cm1::Z>
+    ;
+}
+abstract class _Dm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → core::int, self::_Dm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm1<Z extends core::Object = dynamic> extends self::_Dm1&Object&Am1<self::Dm1::Z> {
+  synthetic constructor •() → self::Dm1<self::Dm1::Z>
+    ;
+}
+abstract class _Em1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::_Em1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Em1<Z extends core::Object = dynamic> extends self::_Em1&Object&Am1<self::Em1::Z> {
+  synthetic constructor •() → self::Em1<self::Em1::Z>
+    ;
+}
+abstract class _Fm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::_Fm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm1<Z extends core::Object = dynamic> extends self::_Fm1&Object&Am1<self::Fm1::Z> {
+  synthetic constructor •() → self::Fm1<self::Fm1::Z>
+    ;
+}
+abstract class _Gm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<({x: core::int}) → dynamic, self::_Gm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm1<Z extends core::Object = dynamic> extends self::_Gm1&Object&Am1<self::Gm1::Z> {
+  synthetic constructor •() → self::Gm1<self::Gm1::Z>
+    ;
+}
+abstract class _Hm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::_Hm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm1<Z extends core::Object = dynamic> extends self::_Hm1&Object&Am1<self::Hm1::Z> {
+  synthetic constructor •() → self::Hm1<self::Hm1::Z>
+    ;
+}
+abstract class _Im1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::_Im1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Im1<Z extends core::Object = dynamic> extends self::_Im1&Object&Am1<self::Im1::Z> {
+  synthetic constructor •() → self::Im1<self::Im1::Z>
+    ;
+}
+abstract class _Jm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<core::Function, self::_Jm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm1<Z extends core::Object = dynamic> extends self::_Jm1&Object&Am1<self::Jm1::Z> {
+  synthetic constructor •() → self::Jm1<self::Jm1::Z>
+    ;
+}
+abstract class _Km1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::Function) → dynamic, self::_Km1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Km1<Z extends core::Object = dynamic> extends self::_Km1&Object&Am1<self::Km1::Z> {
+  synthetic constructor •() → self::Km1<self::Km1::Z>
+    ;
+}
+abstract class _Lm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → (() → core::Function) → dynamic, self::_Lm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm1<Z extends core::Object = dynamic> extends self::_Lm1&Object&Am1<self::Lm1::Z> {
+  synthetic constructor •() → self::Lm1<self::Lm1::Z>
+    ;
+}
+class Mm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::Mm1::Z> {
+  synthetic constructor •() → self::Mm1<self::Mm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::Nm1::Z> {
+  synthetic constructor •() → self::Nm1<self::Nm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Om1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → core::int, self::Om1::Z> {
+  synthetic constructor •() → self::Om1<self::Om1::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::Pm1::Z> {
+  synthetic constructor •() → self::Pm1<self::Pm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::Qm1::Z> {
+  synthetic constructor •() → self::Qm1<self::Qm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm1<Z extends core::Object = dynamic> = core::Object with self::Am1<({x: core::int}) → dynamic, self::Rm1::Z> {
+  synthetic constructor •() → self::Rm1<self::Rm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::Sm1::Z> {
+  synthetic constructor •() → self::Sm1<self::Sm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::Tm1::Z> {
+  synthetic constructor •() → self::Tm1<self::Tm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Um1<Z extends core::Object = dynamic> = core::Object with self::Am1<core::Function, self::Um1::Z> {
+  synthetic constructor •() → self::Um1<self::Um1::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::Function) → dynamic, self::Vm1::Z> {
+  synthetic constructor •() → self::Vm1<self::Vm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → (() → core::Function) → dynamic, self::Wm1::Z> {
+  synthetic constructor •() → self::Wm1<self::Wm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Am2<X extends () → dynamic = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am2<self::Am2::X, self::Am2::Y>
+    ;
+}
+abstract class _Bm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::_Bm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm2<Z extends core::Object = dynamic> extends self::_Bm2&Object&Am2<self::Bm2::Z> {
+  synthetic constructor •() → self::Bm2<self::Bm2::Z>
+    ;
+}
+abstract class _Cm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::_Cm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm2<Z extends core::Object = dynamic> extends self::_Cm2&Object&Am2<self::Cm2::Z> {
+  synthetic constructor •() → self::Cm2<self::Cm2::Z>
+    ;
+}
+abstract class _Dm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → core::int, self::_Dm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm2<Z extends core::Object = dynamic> extends self::_Dm2&Object&Am2<self::Dm2::Z> {
+  synthetic constructor •() → self::Dm2<self::Dm2::Z>
+    ;
+}
+abstract class _Em2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::_Em2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Em2<Z extends core::Object = dynamic> extends self::_Em2&Object&Am2<self::Em2::Z> {
+  synthetic constructor •() → self::Em2<self::Em2::Z>
+    ;
+}
+abstract class _Fm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::_Fm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm2<Z extends core::Object = dynamic> extends self::_Fm2&Object&Am2<self::Fm2::Z> {
+  synthetic constructor •() → self::Fm2<self::Fm2::Z>
+    ;
+}
+abstract class _Gm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<({x: core::int}) → dynamic, self::_Gm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm2<Z extends core::Object = dynamic> extends self::_Gm2&Object&Am2<self::Gm2::Z> {
+  synthetic constructor •() → self::Gm2<self::Gm2::Z>
+    ;
+}
+abstract class _Hm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::_Hm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm2<Z extends core::Object = dynamic> extends self::_Hm2&Object&Am2<self::Hm2::Z> {
+  synthetic constructor •() → self::Hm2<self::Hm2::Z>
+    ;
+}
+abstract class _Im2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::_Im2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Im2<Z extends core::Object = dynamic> extends self::_Im2&Object&Am2<self::Im2::Z> {
+  synthetic constructor •() → self::Im2<self::Im2::Z>
+    ;
+}
+abstract class _Jm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<core::Function, self::_Jm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm2<Z extends core::Object = dynamic> extends self::_Jm2&Object&Am2<self::Jm2::Z> {
+  synthetic constructor •() → self::Jm2<self::Jm2::Z>
+    ;
+}
+abstract class _Km2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::Function) → dynamic, self::_Km2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Km2<Z extends core::Object = dynamic> extends self::_Km2&Object&Am2<self::Km2::Z> {
+  synthetic constructor •() → self::Km2<self::Km2::Z>
+    ;
+}
+abstract class _Lm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → (() → core::Function) → dynamic, self::_Lm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm2<Z extends core::Object = dynamic> extends self::_Lm2&Object&Am2<self::Lm2::Z> {
+  synthetic constructor •() → self::Lm2<self::Lm2::Z>
+    ;
+}
+class Mm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::Mm2::Z> {
+  synthetic constructor •() → self::Mm2<self::Mm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::Nm2::Z> {
+  synthetic constructor •() → self::Nm2<self::Nm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Om2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → core::int, self::Om2::Z> {
+  synthetic constructor •() → self::Om2<self::Om2::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::Pm2::Z> {
+  synthetic constructor •() → self::Pm2<self::Pm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::Qm2::Z> {
+  synthetic constructor •() → self::Qm2<self::Qm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm2<Z extends core::Object = dynamic> = core::Object with self::Am2<({x: core::int}) → dynamic, self::Rm2::Z> {
+  synthetic constructor •() → self::Rm2<self::Rm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::Sm2::Z> {
+  synthetic constructor •() → self::Sm2<self::Sm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::Tm2::Z> {
+  synthetic constructor •() → self::Tm2<self::Tm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Um2<Z extends core::Object = dynamic> = core::Object with self::Am2<core::Function, self::Um2::Z> {
+  synthetic constructor •() → self::Um2<self::Um2::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::Function) → dynamic, self::Vm2::Z> {
+  synthetic constructor •() → self::Vm2<self::Vm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → (() → core::Function) → dynamic, self::Wm2::Z> {
+  synthetic constructor •() → self::Wm2<self::Wm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Am3<L extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am3<self::Am3::L, self::Am3::Y>
+    ;
+}
+abstract class _Bm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::int) → dynamic, self::_Bm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm3<Z extends core::Object = dynamic> extends self::_Bm3&Object&Am3<self::Bm3::Z> {
+  synthetic constructor •() → self::Bm3<self::Bm3::Z>
+    ;
+}
+abstract class _Cm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::int) → dynamic, self::_Cm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm3<Z extends core::Object = dynamic> extends self::_Cm3&Object&Am3<self::Cm3::Z> {
+  synthetic constructor •() → self::Cm3<self::Cm3::Z>
+    ;
+}
+abstract class _Dm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → core::int, self::_Dm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm3<Z extends core::Object = dynamic> extends self::_Dm3&Object&Am3<self::Dm3::Z> {
+  synthetic constructor •() → self::Dm3<self::Dm3::Z>
+    ;
+}
+abstract class _Em3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → dynamic, self::_Em3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Em3<Z extends core::Object = dynamic> extends self::_Em3&Object&Am3<self::Em3::Z> {
+  synthetic constructor •() → self::Em3<self::Em3::Z>
+    ;
+}
+abstract class _Fm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → dynamic, self::_Fm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm3<Z extends core::Object = dynamic> extends self::_Fm3&Object&Am3<self::Fm3::Z> {
+  synthetic constructor •() → self::Fm3<self::Fm3::Z>
+    ;
+}
+abstract class _Gm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<({x: core::int}) → dynamic, self::_Gm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm3<Z extends core::Object = dynamic> extends self::_Gm3&Object&Am3<self::Gm3::Z> {
+  synthetic constructor •() → self::Gm3<self::Gm3::Z>
+    ;
+}
+abstract class _Hm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<([core::int]) → dynamic, self::_Hm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm3<Z extends core::Object = dynamic> extends self::_Hm3&Object&Am3<self::Hm3::Z> {
+  synthetic constructor •() → self::Hm3<self::Hm3::Z>
+    ;
+}
+abstract class _Im3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<([core::int]) → dynamic, self::_Im3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Im3<Z extends core::Object = dynamic> extends self::_Im3&Object&Am3<self::Im3::Z> {
+  synthetic constructor •() → self::Im3<self::Im3::Z>
+    ;
+}
+abstract class _Jm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::Function) → dynamic, self::_Jm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm3<Z extends core::Object = dynamic> extends self::_Jm3&Object&Am3<self::Jm3::Z> {
+  synthetic constructor •() → self::Jm3<self::Jm3::Z>
+    ;
+}
+abstract class _Km3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → (() → core::Function) → dynamic, self::_Km3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Km3<Z extends core::Object = dynamic> extends self::_Km3&Object&Am3<self::Km3::Z> {
+  synthetic constructor •() → self::Km3<self::Km3::Z>
+    ;
+}
+class Af1<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Af1<self::Af1::foo::X>
+    ;
+}
+class Bf1<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X>
+    ;
+}
+class Cf1<X extends () → core::int = dynamic> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Cf1<self::Cf1::foo::X>
+    ;
+}
+class Df1<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Df1<self::Df1::foo::X>
+    ;
+}
+class Ef1<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X>
+    ;
+}
+class Ff1<X extends ({x: core::int}) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X>
+    ;
+}
+class Gf1<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X>
+    ;
+}
+class Hf1<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X>
+    ;
+}
+class If1<X extends core::Function = dynamic> extends core::Object {
+  static factory foo<X extends core::Function = dynamic>() → self::If1<self::If1::foo::X>
+    ;
+}
+class Jf1<X extends (core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X>
+    ;
+}
+class Kf1<X extends () → (() → core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X>
+    ;
+}
+class Bf2<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X>
+    ;
+}
+class Cf2<X extends (core::int) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X>
+    ;
+}
+class Df2<X extends () → core::int = dynamic> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Df2<self::Df2::foo::X>
+    ;
+}
+class Ef2<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X>
+    ;
+}
+class Ff2<X extends () → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X>
+    ;
+}
+class Gf2<X extends ({x: core::int}) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X>
+    ;
+}
+class Hf2<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X>
+    ;
+}
+class If2<X extends ([core::int]) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::If2<self::If2::foo::X>
+    ;
+}
+class Jf2<X extends (core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X>
+    ;
+}
+class Kf2<X extends () → (() → core::Function) → dynamic = dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/clone_function_type.dart.strong.expect
new file mode 100644
index 0000000..f2b11be
--- /dev/null
+++ b/pkg/front_end/testcases/clone_function_type.dart.strong.expect
@@ -0,0 +1,700 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:67:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bm2<Z> extends Object with Am2<Function(int), Z> {}
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:70:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Cm2<Z> extends Object with Am2<Function(int x), Z> {}
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:86:7: Error: Type argument 'dart.core::Function' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Jm2<Z> extends Object with Am2<Function, Z> {}
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:89:7: Error: Type argument '(dart.core::Function) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Km2<Z> extends Object with Am2<Function(Function Function), Z> {}
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:95:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Mm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Mm2<Z> = Object with Am2<Function(int), Z>;
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:98:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Nm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Nm2<Z> = Object with Am2<Function(int x), Z>;
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:114:7: Error: Type argument 'dart.core::Function' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Um2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Um2<Z> = Object with Am2<Function, Z>;
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:117:7: Error: Type argument '(dart.core::Function) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Vm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Vm2<Z> = Object with Am2<Function(Function Function), Z>;
+//       ^
+// pkg/front_end/testcases/clone_function_type.dart:64:11: Context: Bound of this variable is violated.
+// class Am2<X extends Function(), Y> {}
+//           ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:67:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bm2<Z> extends Object with Am2<Function(int), Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:70:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Cm2<Z> extends Object with Am2<Function(int x), Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:86:7: Error: Type argument 'dart.core::Function' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Jm2<Z> extends Object with Am2<Function, Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:89:7: Error: Type argument '(dart.core::Function) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Km2<Z> extends Object with Am2<Function(Function Function), Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:95:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Mm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Mm2<Z> = Object with Am2<Function(int), Z>;
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:98:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Nm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Nm2<Z> = Object with Am2<Function(int x), Z>;
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:114:7: Error: Type argument 'dart.core::Function' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Um2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Um2<Z> = Object with Am2<Function, Z>;
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:117:7: Error: Type argument '(dart.core::Function) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Vm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Vm2<Z> = Object with Am2<Function(Function Function), Z>;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TdB = (core::int) → dynamic;
+typedef TdC = (core::int) → dynamic;
+typedef TdD = () → core::int;
+typedef TdE = () → dynamic;
+typedef TdF = () → dynamic;
+typedef TdG = ({x: core::int}) → dynamic;
+typedef TdH = ([core::int]) → dynamic;
+typedef TdI = ([core::int]) → dynamic;
+typedef TdJ = (core::Function) → dynamic;
+typedef TdK = () → (() → core::Function) → dynamic;
+class Am1<X extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am1<self::Am1::X, self::Am1::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::_Bm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm1<Z extends core::Object = dynamic> extends self::_Bm1&Object&Am1<self::Bm1::Z> {
+  synthetic constructor •() → self::Bm1<self::Bm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::_Cm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm1<Z extends core::Object = dynamic> extends self::_Cm1&Object&Am1<self::Cm1::Z> {
+  synthetic constructor •() → self::Cm1<self::Cm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → core::int, self::_Dm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm1<Z extends core::Object = dynamic> extends self::_Dm1&Object&Am1<self::Dm1::Z> {
+  synthetic constructor •() → self::Dm1<self::Dm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::_Em1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Em1<Z extends core::Object = dynamic> extends self::_Em1&Object&Am1<self::Em1::Z> {
+  synthetic constructor •() → self::Em1<self::Em1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::_Fm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm1<Z extends core::Object = dynamic> extends self::_Fm1&Object&Am1<self::Fm1::Z> {
+  synthetic constructor •() → self::Fm1<self::Fm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<({x: core::int}) → dynamic, self::_Gm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm1<Z extends core::Object = dynamic> extends self::_Gm1&Object&Am1<self::Gm1::Z> {
+  synthetic constructor •() → self::Gm1<self::Gm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::_Hm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm1<Z extends core::Object = dynamic> extends self::_Hm1&Object&Am1<self::Hm1::Z> {
+  synthetic constructor •() → self::Hm1<self::Hm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::_Im1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Im1<Z extends core::Object = dynamic> extends self::_Im1&Object&Am1<self::Im1::Z> {
+  synthetic constructor •() → self::Im1<self::Im1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<core::Function, self::_Jm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm1<Z extends core::Object = dynamic> extends self::_Jm1&Object&Am1<self::Jm1::Z> {
+  synthetic constructor •() → self::Jm1<self::Jm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::Function) → dynamic, self::_Km1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Km1<Z extends core::Object = dynamic> extends self::_Km1&Object&Am1<self::Km1::Z> {
+  synthetic constructor •() → self::Km1<self::Km1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm1&Object&Am1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → (() → core::Function) → dynamic, self::_Lm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm1<Z extends core::Object = dynamic> extends self::_Lm1&Object&Am1<self::Lm1::Z> {
+  synthetic constructor •() → self::Lm1<self::Lm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::Mm1::Z> {
+  synthetic constructor •() → self::Mm1<self::Mm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::int) → dynamic, self::Nm1::Z> {
+  synthetic constructor •() → self::Nm1<self::Nm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Om1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → core::int, self::Om1::Z> {
+  synthetic constructor •() → self::Om1<self::Om1::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::Pm1::Z> {
+  synthetic constructor •() → self::Pm1<self::Pm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → dynamic, self::Qm1::Z> {
+  synthetic constructor •() → self::Qm1<self::Qm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm1<Z extends core::Object = dynamic> = core::Object with self::Am1<({x: core::int}) → dynamic, self::Rm1::Z> {
+  synthetic constructor •() → self::Rm1<self::Rm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::Sm1::Z> {
+  synthetic constructor •() → self::Sm1<self::Sm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm1<Z extends core::Object = dynamic> = core::Object with self::Am1<([core::int]) → dynamic, self::Tm1::Z> {
+  synthetic constructor •() → self::Tm1<self::Tm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Um1<Z extends core::Object = dynamic> = core::Object with self::Am1<core::Function, self::Um1::Z> {
+  synthetic constructor •() → self::Um1<self::Um1::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm1<Z extends core::Object = dynamic> = core::Object with self::Am1<(core::Function) → dynamic, self::Vm1::Z> {
+  synthetic constructor •() → self::Vm1<self::Vm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm1<Z extends core::Object = dynamic> = core::Object with self::Am1<() → (() → core::Function) → dynamic, self::Wm1::Z> {
+  synthetic constructor •() → self::Wm1<self::Wm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Am2<X extends () → dynamic = () → dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am2<self::Am2::X, self::Am2::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::_Bm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm2<Z extends core::Object = dynamic> extends self::_Bm2&Object&Am2<self::Bm2::Z> {
+  synthetic constructor •() → self::Bm2<self::Bm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::_Cm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm2<Z extends core::Object = dynamic> extends self::_Cm2&Object&Am2<self::Cm2::Z> {
+  synthetic constructor •() → self::Cm2<self::Cm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → core::int, self::_Dm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm2<Z extends core::Object = dynamic> extends self::_Dm2&Object&Am2<self::Dm2::Z> {
+  synthetic constructor •() → self::Dm2<self::Dm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::_Em2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Em2<Z extends core::Object = dynamic> extends self::_Em2&Object&Am2<self::Em2::Z> {
+  synthetic constructor •() → self::Em2<self::Em2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::_Fm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm2<Z extends core::Object = dynamic> extends self::_Fm2&Object&Am2<self::Fm2::Z> {
+  synthetic constructor •() → self::Fm2<self::Fm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<({x: core::int}) → dynamic, self::_Gm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm2<Z extends core::Object = dynamic> extends self::_Gm2&Object&Am2<self::Gm2::Z> {
+  synthetic constructor •() → self::Gm2<self::Gm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::_Hm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm2<Z extends core::Object = dynamic> extends self::_Hm2&Object&Am2<self::Hm2::Z> {
+  synthetic constructor •() → self::Hm2<self::Hm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::_Im2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Im2<Z extends core::Object = dynamic> extends self::_Im2&Object&Am2<self::Im2::Z> {
+  synthetic constructor •() → self::Im2<self::Im2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<core::Function, self::_Jm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm2<Z extends core::Object = dynamic> extends self::_Jm2&Object&Am2<self::Jm2::Z> {
+  synthetic constructor •() → self::Jm2<self::Jm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::Function) → dynamic, self::_Km2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Km2<Z extends core::Object = dynamic> extends self::_Km2&Object&Am2<self::Km2::Z> {
+  synthetic constructor •() → self::Km2<self::Km2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm2&Object&Am2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → (() → core::Function) → dynamic, self::_Lm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm2<Z extends core::Object = dynamic> extends self::_Lm2&Object&Am2<self::Lm2::Z> {
+  synthetic constructor •() → self::Lm2<self::Lm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::Mm2::Z> {
+  synthetic constructor •() → self::Mm2<self::Mm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::int) → dynamic, self::Nm2::Z> {
+  synthetic constructor •() → self::Nm2<self::Nm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Om2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → core::int, self::Om2::Z> {
+  synthetic constructor •() → self::Om2<self::Om2::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::Pm2::Z> {
+  synthetic constructor •() → self::Pm2<self::Pm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → dynamic, self::Qm2::Z> {
+  synthetic constructor •() → self::Qm2<self::Qm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm2<Z extends core::Object = dynamic> = core::Object with self::Am2<({x: core::int}) → dynamic, self::Rm2::Z> {
+  synthetic constructor •() → self::Rm2<self::Rm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::Sm2::Z> {
+  synthetic constructor •() → self::Sm2<self::Sm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm2<Z extends core::Object = dynamic> = core::Object with self::Am2<([core::int]) → dynamic, self::Tm2::Z> {
+  synthetic constructor •() → self::Tm2<self::Tm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Um2<Z extends core::Object = dynamic> = core::Object with self::Am2<core::Function, self::Um2::Z> {
+  synthetic constructor •() → self::Um2<self::Um2::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm2<Z extends core::Object = dynamic> = core::Object with self::Am2<(core::Function) → dynamic, self::Vm2::Z> {
+  synthetic constructor •() → self::Vm2<self::Vm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm2<Z extends core::Object = dynamic> = core::Object with self::Am2<() → (() → core::Function) → dynamic, self::Wm2::Z> {
+  synthetic constructor •() → self::Wm2<self::Wm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Am3<L extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am3<self::Am3::L, self::Am3::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::int) → dynamic, self::_Bm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm3<Z extends core::Object = dynamic> extends self::_Bm3&Object&Am3<self::Bm3::Z> {
+  synthetic constructor •() → self::Bm3<self::Bm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::int) → dynamic, self::_Cm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm3<Z extends core::Object = dynamic> extends self::_Cm3&Object&Am3<self::Cm3::Z> {
+  synthetic constructor •() → self::Cm3<self::Cm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → core::int, self::_Dm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm3<Z extends core::Object = dynamic> extends self::_Dm3&Object&Am3<self::Dm3::Z> {
+  synthetic constructor •() → self::Dm3<self::Dm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → dynamic, self::_Em3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Em3<Z extends core::Object = dynamic> extends self::_Em3&Object&Am3<self::Em3::Z> {
+  synthetic constructor •() → self::Em3<self::Em3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → dynamic, self::_Fm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm3<Z extends core::Object = dynamic> extends self::_Fm3&Object&Am3<self::Fm3::Z> {
+  synthetic constructor •() → self::Fm3<self::Fm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<({x: core::int}) → dynamic, self::_Gm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm3<Z extends core::Object = dynamic> extends self::_Gm3&Object&Am3<self::Gm3::Z> {
+  synthetic constructor •() → self::Gm3<self::Gm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<([core::int]) → dynamic, self::_Hm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm3<Z extends core::Object = dynamic> extends self::_Hm3&Object&Am3<self::Hm3::Z> {
+  synthetic constructor •() → self::Hm3<self::Hm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<([core::int]) → dynamic, self::_Im3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Im3<Z extends core::Object = dynamic> extends self::_Im3&Object&Am3<self::Im3::Z> {
+  synthetic constructor •() → self::Im3<self::Im3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<(core::Function) → dynamic, self::_Jm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm3<Z extends core::Object = dynamic> extends self::_Jm3&Object&Am3<self::Jm3::Z> {
+  synthetic constructor •() → self::Jm3<self::Jm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km3&Object&Am3<Z extends core::Object = dynamic> = core::Object with self::Am3<() → (() → core::Function) → dynamic, self::_Km3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Km3<Z extends core::Object = dynamic> extends self::_Km3&Object&Am3<self::Km3::Z> {
+  synthetic constructor •() → self::Km3<self::Km3::Z>
+    : super core::Object::•()
+    ;
+}
+class Af1<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Af1<self::Af1::foo::X>
+    return null;
+}
+class Bf1<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X>
+    return null;
+}
+class Cf1<X extends () → core::int = () → core::int> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Cf1<self::Cf1::foo::X>
+    return null;
+}
+class Df1<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Df1<self::Df1::foo::X>
+    return null;
+}
+class Ef1<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X>
+    return null;
+}
+class Ff1<X extends ({x: core::int}) → dynamic = ({x: core::int}) → dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X>
+    return null;
+}
+class Gf1<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X>
+    return null;
+}
+class Hf1<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X>
+    return null;
+}
+class If1<X extends core::Function = core::Function> extends core::Object {
+  static factory foo<X extends core::Function = dynamic>() → self::If1<self::If1::foo::X>
+    return null;
+}
+class Jf1<X extends (core::Function) → dynamic = (core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X>
+    return null;
+}
+class Kf1<X extends () → (() → core::Function) → dynamic = () → (() → core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X>
+    return null;
+}
+class Bf2<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X>
+    return null;
+}
+class Cf2<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X>
+    return null;
+}
+class Df2<X extends () → core::int = () → core::int> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Df2<self::Df2::foo::X>
+    return null;
+}
+class Ef2<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X>
+    return null;
+}
+class Ff2<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X>
+    return null;
+}
+class Gf2<X extends ({x: core::int}) → dynamic = ({x: core::int}) → dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X>
+    return null;
+}
+class Hf2<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X>
+    return null;
+}
+class If2<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::If2<self::If2::foo::X>
+    return null;
+}
+class Jf2<X extends (core::Function) → dynamic = (core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X>
+    return null;
+}
+class Kf2<X extends () → (() → core::Function) → dynamic = () → (() → core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X>
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/clone_function_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..c0e8444
--- /dev/null
+++ b/pkg/front_end/testcases/clone_function_type.dart.strong.transformed.expect
@@ -0,0 +1,610 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// class Qm1<Z> = Object with Am1<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
+//                                                   ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// class Qm2<Z> = Object with Am2<Function({int}), Z>;
+//                                             ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// typedef TdF = Function({int});
+//                            ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// class Ef1<X extends Function({int})> {
+//                                  ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:67:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bm2<Z> extends Object with Am2<Function(int), Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:70:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Cm2<Z> extends Object with Am2<Function(int x), Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:86:7: Error: Type argument 'dart.core::Function' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Jm2<Z> extends Object with Am2<Function, Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:89:7: Error: Type argument '(dart.core::Function) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Object with Am2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Km2<Z> extends Object with Am2<Function(Function Function), Z> {}
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:95:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Mm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Mm2<Z> = Object with Am2<Function(int), Z>;
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:98:7: Error: Type argument '(dart.core::int) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Nm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Nm2<Z> = Object with Am2<Function(int x), Z>;
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:114:7: Error: Type argument 'dart.core::Function' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Um2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Um2<Z> = Object with Am2<Function, Z>;
+//       ^
+//
+// pkg/front_end/testcases/clone_function_type.dart:117:7: Error: Type argument '(dart.core::Function) → dynamic' violates the corresponding type variable bound of 'Am2' in the supertype 'Am2' of class 'Vm2'.
+// Try changing type arguments so that they conform to the bounds.
+// class Vm2<Z> = Object with Am2<Function(Function Function), Z>;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TdB = (core::int) → dynamic;
+typedef TdC = (core::int) → dynamic;
+typedef TdD = () → core::int;
+typedef TdE = () → dynamic;
+typedef TdF = () → dynamic;
+typedef TdG = ({x: core::int}) → dynamic;
+typedef TdH = ([core::int]) → dynamic;
+typedef TdI = ([core::int]) → dynamic;
+typedef TdJ = (core::Function) → dynamic;
+typedef TdK = () → (() → core::Function) → dynamic;
+class Am1<X extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am1<self::Am1::X, self::Am1::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::_Bm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm1<Z extends core::Object = dynamic> extends self::_Bm1&Object&Am1<self::Bm1::Z> {
+  synthetic constructor •() → self::Bm1<self::Bm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::_Cm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm1<Z extends core::Object = dynamic> extends self::_Cm1&Object&Am1<self::Cm1::Z> {
+  synthetic constructor •() → self::Cm1<self::Cm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → core::int, self::_Dm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm1<Z extends core::Object = dynamic> extends self::_Dm1&Object&Am1<self::Dm1::Z> {
+  synthetic constructor •() → self::Dm1<self::Dm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::_Em1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Em1<Z extends core::Object = dynamic> extends self::_Em1&Object&Am1<self::Em1::Z> {
+  synthetic constructor •() → self::Em1<self::Em1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::_Fm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm1<Z extends core::Object = dynamic> extends self::_Fm1&Object&Am1<self::Fm1::Z> {
+  synthetic constructor •() → self::Fm1<self::Fm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<({x: core::int}) → dynamic, self::_Gm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm1<Z extends core::Object = dynamic> extends self::_Gm1&Object&Am1<self::Gm1::Z> {
+  synthetic constructor •() → self::Gm1<self::Gm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::_Hm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm1<Z extends core::Object = dynamic> extends self::_Hm1&Object&Am1<self::Hm1::Z> {
+  synthetic constructor •() → self::Hm1<self::Hm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::_Im1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Im1<Z extends core::Object = dynamic> extends self::_Im1&Object&Am1<self::Im1::Z> {
+  synthetic constructor •() → self::Im1<self::Im1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<core::Function, self::_Jm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm1<Z extends core::Object = dynamic> extends self::_Jm1&Object&Am1<self::Jm1::Z> {
+  synthetic constructor •() → self::Jm1<self::Jm1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::Function) → dynamic, self::_Km1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Km1<Z extends core::Object = dynamic> extends self::_Km1&Object&Am1<self::Km1::Z> {
+  synthetic constructor •() → self::Km1<self::Km1::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm1&Object&Am1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → (() → core::Function) → dynamic, self::_Lm1&Object&Am1::Z> {
+  synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm1<Z extends core::Object = dynamic> extends self::_Lm1&Object&Am1<self::Lm1::Z> {
+  synthetic constructor •() → self::Lm1<self::Lm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::Mm1::Z> {
+  synthetic constructor •() → self::Mm1<self::Mm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::int) → dynamic, self::Nm1::Z> {
+  synthetic constructor •() → self::Nm1<self::Nm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Om1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → core::int, self::Om1::Z> {
+  synthetic constructor •() → self::Om1<self::Om1::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::Pm1::Z> {
+  synthetic constructor •() → self::Pm1<self::Pm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → dynamic, self::Qm1::Z> {
+  synthetic constructor •() → self::Qm1<self::Qm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<({x: core::int}) → dynamic, self::Rm1::Z> {
+  synthetic constructor •() → self::Rm1<self::Rm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::Sm1::Z> {
+  synthetic constructor •() → self::Sm1<self::Sm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<([core::int]) → dynamic, self::Tm1::Z> {
+  synthetic constructor •() → self::Tm1<self::Tm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Um1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<core::Function, self::Um1::Z> {
+  synthetic constructor •() → self::Um1<self::Um1::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<(core::Function) → dynamic, self::Vm1::Z> {
+  synthetic constructor •() → self::Vm1<self::Vm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm1<Z extends core::Object = dynamic> extends core::Object implements self::Am1<() → (() → core::Function) → dynamic, self::Wm1::Z> {
+  synthetic constructor •() → self::Wm1<self::Wm1::Z>
+    : super core::Object::•()
+    ;
+}
+class Am2<X extends () → dynamic = () → dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am2<self::Am2::X, self::Am2::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::_Bm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm2<Z extends core::Object = dynamic> extends self::_Bm2&Object&Am2<self::Bm2::Z> {
+  synthetic constructor •() → self::Bm2<self::Bm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::_Cm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm2<Z extends core::Object = dynamic> extends self::_Cm2&Object&Am2<self::Cm2::Z> {
+  synthetic constructor •() → self::Cm2<self::Cm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → core::int, self::_Dm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm2<Z extends core::Object = dynamic> extends self::_Dm2&Object&Am2<self::Dm2::Z> {
+  synthetic constructor •() → self::Dm2<self::Dm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::_Em2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Em2<Z extends core::Object = dynamic> extends self::_Em2&Object&Am2<self::Em2::Z> {
+  synthetic constructor •() → self::Em2<self::Em2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::_Fm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm2<Z extends core::Object = dynamic> extends self::_Fm2&Object&Am2<self::Fm2::Z> {
+  synthetic constructor •() → self::Fm2<self::Fm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<({x: core::int}) → dynamic, self::_Gm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm2<Z extends core::Object = dynamic> extends self::_Gm2&Object&Am2<self::Gm2::Z> {
+  synthetic constructor •() → self::Gm2<self::Gm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::_Hm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm2<Z extends core::Object = dynamic> extends self::_Hm2&Object&Am2<self::Hm2::Z> {
+  synthetic constructor •() → self::Hm2<self::Hm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::_Im2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Im2<Z extends core::Object = dynamic> extends self::_Im2&Object&Am2<self::Im2::Z> {
+  synthetic constructor •() → self::Im2<self::Im2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<core::Function, self::_Jm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm2<Z extends core::Object = dynamic> extends self::_Jm2&Object&Am2<self::Jm2::Z> {
+  synthetic constructor •() → self::Jm2<self::Jm2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::Function) → dynamic, self::_Km2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Km2<Z extends core::Object = dynamic> extends self::_Km2&Object&Am2<self::Km2::Z> {
+  synthetic constructor •() → self::Km2<self::Km2::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Lm2&Object&Am2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → (() → core::Function) → dynamic, self::_Lm2&Object&Am2::Z> {
+  synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z>
+    : super core::Object::•()
+    ;
+}
+class Lm2<Z extends core::Object = dynamic> extends self::_Lm2&Object&Am2<self::Lm2::Z> {
+  synthetic constructor •() → self::Lm2<self::Lm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Mm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::Mm2::Z> {
+  synthetic constructor •() → self::Mm2<self::Mm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Nm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::int) → dynamic, self::Nm2::Z> {
+  synthetic constructor •() → self::Nm2<self::Nm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Om2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → core::int, self::Om2::Z> {
+  synthetic constructor •() → self::Om2<self::Om2::Z>
+    : super core::Object::•()
+    ;
+}
+class Pm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::Pm2::Z> {
+  synthetic constructor •() → self::Pm2<self::Pm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Qm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → dynamic, self::Qm2::Z> {
+  synthetic constructor •() → self::Qm2<self::Qm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Rm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<({x: core::int}) → dynamic, self::Rm2::Z> {
+  synthetic constructor •() → self::Rm2<self::Rm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Sm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::Sm2::Z> {
+  synthetic constructor •() → self::Sm2<self::Sm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Tm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<([core::int]) → dynamic, self::Tm2::Z> {
+  synthetic constructor •() → self::Tm2<self::Tm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Um2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<core::Function, self::Um2::Z> {
+  synthetic constructor •() → self::Um2<self::Um2::Z>
+    : super core::Object::•()
+    ;
+}
+class Vm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<(core::Function) → dynamic, self::Vm2::Z> {
+  synthetic constructor •() → self::Vm2<self::Vm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Wm2<Z extends core::Object = dynamic> extends core::Object implements self::Am2<() → (() → core::Function) → dynamic, self::Wm2::Z> {
+  synthetic constructor •() → self::Wm2<self::Wm2::Z>
+    : super core::Object::•()
+    ;
+}
+class Am3<L extends core::Object = dynamic, Y extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Am3<self::Am3::L, self::Am3::Y>
+    : super core::Object::•()
+    ;
+}
+abstract class _Bm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<(core::int) → dynamic, self::_Bm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Bm3<Z extends core::Object = dynamic> extends self::_Bm3&Object&Am3<self::Bm3::Z> {
+  synthetic constructor •() → self::Bm3<self::Bm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Cm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<(core::int) → dynamic, self::_Cm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Cm3<Z extends core::Object = dynamic> extends self::_Cm3&Object&Am3<self::Cm3::Z> {
+  synthetic constructor •() → self::Cm3<self::Cm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Dm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → core::int, self::_Dm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Dm3<Z extends core::Object = dynamic> extends self::_Dm3&Object&Am3<self::Dm3::Z> {
+  synthetic constructor •() → self::Dm3<self::Dm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Em3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → dynamic, self::_Em3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Em3<Z extends core::Object = dynamic> extends self::_Em3&Object&Am3<self::Em3::Z> {
+  synthetic constructor •() → self::Em3<self::Em3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Fm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → dynamic, self::_Fm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Fm3<Z extends core::Object = dynamic> extends self::_Fm3&Object&Am3<self::Fm3::Z> {
+  synthetic constructor •() → self::Fm3<self::Fm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Gm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<({x: core::int}) → dynamic, self::_Gm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Gm3<Z extends core::Object = dynamic> extends self::_Gm3&Object&Am3<self::Gm3::Z> {
+  synthetic constructor •() → self::Gm3<self::Gm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Hm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<([core::int]) → dynamic, self::_Hm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Hm3<Z extends core::Object = dynamic> extends self::_Hm3&Object&Am3<self::Hm3::Z> {
+  synthetic constructor •() → self::Hm3<self::Hm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Im3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<([core::int]) → dynamic, self::_Im3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Im3<Z extends core::Object = dynamic> extends self::_Im3&Object&Am3<self::Im3::Z> {
+  synthetic constructor •() → self::Im3<self::Im3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Jm3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<(core::Function) → dynamic, self::_Jm3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Jm3<Z extends core::Object = dynamic> extends self::_Jm3&Object&Am3<self::Jm3::Z> {
+  synthetic constructor •() → self::Jm3<self::Jm3::Z>
+    : super core::Object::•()
+    ;
+}
+abstract class _Km3&Object&Am3<Z extends core::Object = dynamic> extends core::Object implements self::Am3<() → (() → core::Function) → dynamic, self::_Km3&Object&Am3::Z> {
+  synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z>
+    : super core::Object::•()
+    ;
+}
+class Km3<Z extends core::Object = dynamic> extends self::_Km3&Object&Am3<self::Km3::Z> {
+  synthetic constructor •() → self::Km3<self::Km3::Z>
+    : super core::Object::•()
+    ;
+}
+class Af1<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Af1<self::Af1::foo::X>
+    return null;
+}
+class Bf1<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf1<self::Bf1::foo::X>
+    return null;
+}
+class Cf1<X extends () → core::int = () → core::int> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Cf1<self::Cf1::foo::X>
+    return null;
+}
+class Df1<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Df1<self::Df1::foo::X>
+    return null;
+}
+class Ef1<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef1<self::Ef1::foo::X>
+    return null;
+}
+class Ff1<X extends ({x: core::int}) → dynamic = ({x: core::int}) → dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Ff1<self::Ff1::foo::X>
+    return null;
+}
+class Gf1<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Gf1<self::Gf1::foo::X>
+    return null;
+}
+class Hf1<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf1<self::Hf1::foo::X>
+    return null;
+}
+class If1<X extends core::Function = core::Function> extends core::Object {
+  static factory foo<X extends core::Function = dynamic>() → self::If1<self::If1::foo::X>
+    return null;
+}
+class Jf1<X extends (core::Function) → dynamic = (core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf1<self::Jf1::foo::X>
+    return null;
+}
+class Kf1<X extends () → (() → core::Function) → dynamic = () → (() → core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf1<self::Kf1::foo::X>
+    return null;
+}
+class Bf2<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Bf2<self::Bf2::foo::X>
+    return null;
+}
+class Cf2<X extends (core::int) → dynamic = (core::int) → dynamic> extends core::Object {
+  static factory foo<X extends (core::int) → dynamic = dynamic>() → self::Cf2<self::Cf2::foo::X>
+    return null;
+}
+class Df2<X extends () → core::int = () → core::int> extends core::Object {
+  static factory foo<X extends () → core::int = dynamic>() → self::Df2<self::Df2::foo::X>
+    return null;
+}
+class Ef2<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ef2<self::Ef2::foo::X>
+    return null;
+}
+class Ff2<X extends () → dynamic = () → dynamic> extends core::Object {
+  static factory foo<X extends () → dynamic = dynamic>() → self::Ff2<self::Ff2::foo::X>
+    return null;
+}
+class Gf2<X extends ({x: core::int}) → dynamic = ({x: core::int}) → dynamic> extends core::Object {
+  static factory foo<X extends ({x: core::int}) → dynamic = dynamic>() → self::Gf2<self::Gf2::foo::X>
+    return null;
+}
+class Hf2<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::Hf2<self::Hf2::foo::X>
+    return null;
+}
+class If2<X extends ([core::int]) → dynamic = ([core::int]) → dynamic> extends core::Object {
+  static factory foo<X extends ([core::int]) → dynamic = dynamic>() → self::If2<self::If2::foo::X>
+    return null;
+}
+class Jf2<X extends (core::Function) → dynamic = (core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends (core::Function) → dynamic = dynamic>() → self::Jf2<self::Jf2::foo::X>
+    return null;
+}
+class Kf2<X extends () → (() → core::Function) → dynamic = () → (() → core::Function) → dynamic> extends core::Object {
+  static factory foo<X extends () → (() → core::Function) → dynamic = dynamic>() → self::Kf2<self::Kf2::foo::X>
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_from_package_url_as_file.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_from_package_url_as_file.yaml
new file mode 100644
index 0000000..d5a757b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_from_package_url_as_file.yaml
@@ -0,0 +1,25 @@
+# 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.md file.
+
+# Test that invalidating a part of a package works with package URI when the
+# part file was referenced via a package URI
+
+type: basic
+entry: "package:example/main.dart"
+strong: false
+invalidate:
+  - pkg/example/b.dart
+sources:
+  pkg/example/main.dart: |
+    part "package:example/b.dart";
+    main() {
+      print("hello");
+      b();
+    }
+  pkg/example/b.dart: |
+    part of "package:example/main.dart";
+    b() {
+      print("b1");
+    }
+  .packages: example:pkg/example
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_from_package_url_as_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_from_package_url_as_package.yaml
new file mode 100644
index 0000000..149b1ae
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_from_package_url_as_package.yaml
@@ -0,0 +1,25 @@
+# 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.md file.
+
+# Test that invalidating a part of a package works with package URI when the
+# part file was referenced via a package URI
+
+type: basic
+entry: "package:example/main.dart"
+strong: false
+invalidate:
+  - "package:example/b.dart"
+sources:
+  pkg/example/main.dart: |
+    part "package:example/b.dart";
+    main() {
+      print("hello");
+      b();
+    }
+  pkg/example/b.dart: |
+    part of "package:example/main.dart";
+    b() {
+      print("b1");
+    }
+  .packages: example:pkg/example
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml
new file mode 100644
index 0000000..5fd397a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/regress_35215.yaml
@@ -0,0 +1,44 @@
+# 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.md file.
+
+# Load from a dill file, update a file in the dill that is the context of an
+# error in such a way that the position in the newly compiled procedure doesn't
+# exist in the old library.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+        main() {
+          b(42);
+        }
+      b.dart: |
+        b({int named}) {
+          print("b");
+        }
+    expectedLibraryCount: 2
+    errors: true
+  - entry: main.dart
+    worldTypex: updated
+    invalidate:
+      - b.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+        main() {
+          b(42);
+        }
+      b.dart: |
+        // lots of comments
+        // forcing offsets down
+        // and also adding more lines
+        // and whatnot
+        b({int named}) {
+          print("b");
+        }
+    expectedLibraryCount: 2
+    errors: true
diff --git a/pkg/front_end/testcases/regress/issue_35213.dart b/pkg/front_end/testcases/regress/issue_35213.dart
new file mode 100644
index 0000000..37a9f1c
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35213.dart
@@ -0,0 +1,9 @@
+// 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.
+
+f(int a int b) { }
+
+main() {
+  f(2, 3);
+}
diff --git a/pkg/front_end/testcases/regress/issue_35213.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_35213.dart.legacy.expect
new file mode 100644
index 0000000..1280dd9
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35213.dart.legacy.expect
@@ -0,0 +1,21 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f(core::int a, core::int b) → dynamic {}
+static method main() → dynamic {
+  self::f(2, 3);
+}
+
diff --git a/pkg/front_end/testcases/regress/issue_35213.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_35213.dart.legacy.transformed.expect
new file mode 100644
index 0000000..a66ce9c
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35213.dart.legacy.transformed.expect
@@ -0,0 +1,15 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f(core::int a, core::int b) → dynamic {}
+static method main() → dynamic {
+  self::f(2, 3);
+}
+
diff --git a/pkg/front_end/testcases/regress/issue_35213.dart.outline.expect b/pkg/front_end/testcases/regress/issue_35213.dart.outline.expect
new file mode 100644
index 0000000..040a0f3
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35213.dart.outline.expect
@@ -0,0 +1,14 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f(core::int a, core::int b) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_35213.dart.strong.expect b/pkg/front_end/testcases/regress/issue_35213.dart.strong.expect
new file mode 100644
index 0000000..cd5fe47
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35213.dart.strong.expect
@@ -0,0 +1,20 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f(core::int a, core::int b) → dynamic {}
+static method main() → dynamic {
+  self::f(2, 3);
+}
diff --git a/pkg/front_end/testcases/regress/issue_35213.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_35213.dart.strong.transformed.expect
new file mode 100644
index 0000000..1f16d48
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35213.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_35213.dart:5:9: Error: Expected ',' before this.
+// f(int a int b) { }
+//         ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f(core::int a, core::int b) → dynamic {}
+static method main() → dynamic {
+  self::f(2, 3);
+}
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index bd473b2..22d2418 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -227,8 +227,7 @@
 
   KernelTarget createKernelTarget(
       DillTarget dillTarget, UriTranslator uriTranslator) {
-    return new KernelTarget(c.fileSystem, false, dillTarget, uriTranslator,
-        uriToSource: c.uriToSource);
+    return new KernelTarget(c.fileSystem, false, dillTarget, uriTranslator);
   }
 
   Future<KernelTarget> buildOutline([Uri output]) async {
diff --git a/pkg/kernel/bin/size_breakdown.dart b/pkg/kernel/bin/size_breakdown.dart
index a99233d..01fec0f 100755
--- a/pkg/kernel/bin/size_breakdown.dart
+++ b/pkg/kernel/bin/size_breakdown.dart
@@ -25,7 +25,9 @@
   List<int> bytes = new File(args[0]).readAsBytesSync();
   try {
     Component p = new Component();
-    new WrappedBinaryBuilder(bytes).readComponent(p);
+    new WrappedBinaryBuilder(bytes)
+      ..readComponent(p)
+      ..report();
   } catch (e) {
     print("Argument given isn't a dill file that can be loaded.");
     usage();
@@ -34,41 +36,50 @@
 
 class WrappedBinaryBuilder extends BinaryBuilder {
   WrappedBinaryBuilder(var _bytes) : super(_bytes, disableLazyReading: true);
+  int offsetsSize = 0;
+  int stringTableSize = 0;
+  int linkTableSize = 0;
+  int uriToSourceSize = 0;
+  int constantTableSize = 0;
+  Map<Uri, int> librarySizes = {};
+
+  int readOffset() {
+    offsetsSize -= byteOffset;
+    int result = super.readOffset();
+    offsetsSize += byteOffset;
+    return result;
+  }
 
   void readStringTable(List<String> table) {
-    int size = -byteOffset;
+    stringTableSize -= byteOffset;
     super.readStringTable(table);
-    size += super.byteOffset;
-    print("String table: ${_bytesToReadable(size)}.");
+    stringTableSize += byteOffset;
   }
 
   void readLinkTable(CanonicalName linkRoot) {
-    int size = -byteOffset;
+    linkTableSize -= byteOffset;
     super.readLinkTable(linkRoot);
-    size += super.byteOffset;
-    print("Link table: ${_bytesToReadable(size)}.");
+    linkTableSize += byteOffset;
   }
 
   Map<Uri, Source> readUriToSource() {
-    int size = -byteOffset;
+    uriToSourceSize -= byteOffset;
     var result = super.readUriToSource();
-    size += super.byteOffset;
-    print("URI to sources map: ${_bytesToReadable(size)}.");
+    uriToSourceSize += byteOffset;
     return result;
   }
 
   void readConstantTable() {
-    int size = -byteOffset;
+    constantTableSize -= byteOffset;
     super.readConstantTable();
-    size += super.byteOffset;
-    print("Constant table: ${_bytesToReadable(size)}.");
+    constantTableSize += byteOffset;
   }
 
   Library readLibrary(Component component, int endOffset) {
     int size = -byteOffset;
     var result = super.readLibrary(component, endOffset);
-    size += super.byteOffset;
-    print("Library '${result.importUri}': ${_bytesToReadable(size)}.");
+    size += byteOffset;
+    librarySizes[result.importUri] = size;
     return result;
   }
 
@@ -82,4 +93,16 @@
     }
     return "${dSize.toStringAsFixed(1)} ${what[idx]} ($size B)";
   }
+
+  void report() {
+    print("Offsets: ${_bytesToReadable(offsetsSize)}");
+    print("String table: ${_bytesToReadable(stringTableSize)}");
+    print("Link table: ${_bytesToReadable(linkTableSize)}");
+    print("URI to source table: ${_bytesToReadable(uriToSourceSize)}");
+    print("Constant table: ${_bytesToReadable(constantTableSize)}");
+    print("");
+    for (Uri uri in librarySizes.keys) {
+      print("Library '$uri': ${_bytesToReadable(librarySizes[uri])}.");
+    }
+  }
 }
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 7555396..3006953 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -5695,7 +5695,7 @@
   /// number. The returned line contains no line separators.
   String getTextLine(int line) {
     RangeError.checkValueInInterval(line, 1, lineStarts.length, 'line');
-    if (source == null) return null;
+    if (source == null || source.isEmpty) return null;
 
     cachedText ??= utf8.decode(source, allowMalformed: true);
     // -1 as line numbers start at 1.
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 8b591ac..c4cc243 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1155,7 +1155,10 @@
     var flags = readByte();
     var name = readName();
     var annotations = readAnnotationList(node);
-    debugPath.add(node.name?.name ?? 'redirecting-factory-constructor');
+    assert(() {
+      debugPath.add(node.name?.name ?? 'redirecting-factory-constructor');
+      return true;
+    }());
     var targetReference = readMemberReference();
     var typeArguments = readDartTypeList();
     int typeParameterStackHeight = typeParameterStack.length;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index b46a768..9143687 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -23,7 +23,8 @@
   final StringIndexer stringIndexer;
   ConstantIndexer _constantIndexer;
   final UriIndexer _sourceUriIndexer = new UriIndexer();
-  final Set<Uri> _knownSourceUri = new Set<Uri>();
+  bool _currentlyInNonimplementation = false;
+  final List<bool> _sourcesFromRealImplementation = new List<bool>();
   Map<LibraryDependency, int> _libraryDependencyIndex =
       <LibraryDependency, int>{};
 
@@ -34,6 +35,7 @@
   final BytesSink _constantsBytesSink;
   BufferedSink _constantsSink;
   BufferedSink _sink;
+  bool includeSources;
 
   List<int> libraryOffsets;
   List<int> classOffsets;
@@ -53,7 +55,8 @@
   ///
   /// The BinaryPrinter will use its own buffer, so the [sink] does not need
   /// one.
-  BinaryPrinter(Sink<List<int>> sink, {StringIndexer stringIndexer})
+  BinaryPrinter(Sink<List<int>> sink,
+      {StringIndexer stringIndexer, this.includeSources = true})
       : _mainSink = new BufferedSink(sink),
         _metadataSink = new BufferedSink(new BytesSink()),
         _constantsBytesSink = new BytesSink(),
@@ -217,15 +220,16 @@
     type.accept(this);
   }
 
-  // The currently active file uri where we are writing [TreeNode]s from.  If
-  // this is set to `null` we cannot write file offsets.  The [writeOffset]
-  // helper function will ensure this.
-  Uri _activeFileUri;
-
   // Returns the new active file uri.
   Uri writeUriReference(Uri uri) {
     final int index = _sourceUriIndexer.put(uri);
     writeUInt30(index);
+    if (!_currentlyInNonimplementation) {
+      if (_sourcesFromRealImplementation.length <= index) {
+        _sourcesFromRealImplementation.length = index + 1;
+      }
+      _sourcesFromRealImplementation[index] = true;
+    }
     return uri;
   }
 
@@ -315,7 +319,6 @@
     writeUInt32(Tag.ComponentFile);
     writeUInt32(Tag.BinaryFormatVersion);
     indexLinkTable(component);
-    indexUris(component);
     _collectMetadata(component);
     if (_metadataSubsections != null) {
       _writeNodeMetadataImpl(component, componentOffset);
@@ -487,10 +490,6 @@
     writeUInt32(getBufferOffset() + 4); // total size.
   }
 
-  void indexUris(Component component) {
-    _knownSourceUri.addAll(component.uriToSource.keys);
-  }
-
   void writeUriToSource(Map<Uri, Source> uriToSource) {
     _binaryOffsetForSourceTable = getBufferOffset();
 
@@ -503,9 +502,12 @@
     Utf8Encoder utf8Encoder = const Utf8Encoder();
     for (Uri uri in _sourceUriIndexer.index.keys) {
       index[i] = getBufferOffset();
-      Source source =
-          (_knownSourceUri.contains(uri) ? uriToSource[uri] : null) ??
-              new Source(<int>[], const <int>[]);
+      Source source = ((includeSources &&
+                  _sourcesFromRealImplementation.length > i &&
+                  _sourcesFromRealImplementation[i] == true)
+              ? uriToSource[uri]
+              : null) ??
+          new Source(<int>[], const <int>[]);
 
       writeByteList(utf8Encoder.convert(uri == null ? "" : "$uri"));
       writeByteList(source.source);
@@ -571,10 +573,6 @@
   }
 
   writeOffset(int offset) {
-    if (_activeFileUri == null) {
-      offset = TreeNode.noOffset;
-    }
-
     // TODO(jensj): Delta-encoding.
     // File offset ranges from -1 and up,
     // but is here saved as unsigned (thus the +1)
@@ -616,11 +614,7 @@
     writeByte(insideExternalLibrary ? 1 : 0);
     writeCanonicalNameReference(getCanonicalNameOfLibrary(node));
     writeStringReference(node.name ?? '');
-    // TODO(jensj): We save (almost) the same URI twice.
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeAnnotationList(node.annotations);
     writeLibraryDependencies(node);
     writeAdditionalExports(node.additionalExports);
@@ -634,8 +628,6 @@
     writeNodeList(node.procedures);
     procedureOffsets.add(getBufferOffset());
 
-    _activeFileUri = activeFileUriSaved;
-
     // Fixed-size ints at the end used as an index.
     assert(classOffsets.length > 0);
     for (int offset in classOffsets) {
@@ -705,10 +697,7 @@
   void visitTypedef(Typedef node) {
     _variableIndexer ??= new VariableIndexer();
     writeCanonicalNameReference(getCanonicalNameOfTypedef(node));
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeOffset(node.fileOffset);
     writeStringReference(node.name);
     writeAnnotationList(node.annotations);
@@ -724,8 +713,6 @@
 
     leaveScope(typeParameters: node.typeParametersOfFunctionType);
     leaveScope(typeParameters: node.typeParameters, variableScope: true);
-
-    _activeFileUri = activeFileUriSaved;
   }
 
   void writeAnnotation(Expression annotation) {
@@ -753,16 +740,15 @@
   void visitClass(Class node) {
     classOffsets.add(getBufferOffset());
 
+    if (node.isAnonymousMixin) _currentlyInNonimplementation = true;
+
     int flags = _encodeClassFlags(node.flags, node.level);
     if (node.canonicalName == null) {
       throw 'Missing canonical name for $node';
     }
     writeByte(Tag.Class);
     writeCanonicalNameReference(getCanonicalNameOfClass(node));
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeOffset(node.startFileOffset);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
@@ -784,13 +770,12 @@
     writeNodeList(node.redirectingFactoryConstructors);
     leaveScope(typeParameters: node.typeParameters);
 
-    _activeFileUri = activeFileUriSaved;
-
     assert(procedureOffsets.length > 0);
     for (int offset in procedureOffsets) {
       writeUInt32(offset);
     }
     writeUInt32(procedureOffsets.length - 1);
+    _currentlyInNonimplementation = false;
   }
 
   static final Name _emptyName = new Name('');
@@ -803,10 +788,7 @@
     enterScope(memberScope: true);
     writeByte(Tag.Constructor);
     writeCanonicalNameReference(getCanonicalNameOfMember(node));
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeOffset(node.startFileOffset);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
@@ -822,8 +804,6 @@
         node.function.namedParameters.length);
     writeNodeList(node.initializers);
 
-    _activeFileUri = activeFileUriSaved;
-
     leaveScope(memberScope: true);
   }
 
@@ -834,13 +814,17 @@
     if (node.canonicalName == null) {
       throw 'Missing canonical name for $node';
     }
+
+    final bool currentlyInNonimplementationSaved =
+        _currentlyInNonimplementation;
+    if (node.isNoSuchMethodForwarder || node.isSyntheticForwarder) {
+      _currentlyInNonimplementation = true;
+    }
+
     enterScope(memberScope: true);
     writeByte(Tag.Procedure);
     writeCanonicalNameReference(getCanonicalNameOfMember(node));
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeOffset(node.startFileOffset);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
@@ -851,11 +835,9 @@
     writeOptionalReference(node.forwardingStubSuperTargetReference);
     writeOptionalReference(node.forwardingStubInterfaceTargetReference);
     writeOptionalNode(node.function);
-
-    _activeFileUri = activeFileUriSaved;
-
     leaveScope(memberScope: true);
 
+    _currentlyInNonimplementation = currentlyInNonimplementationSaved;
     assert((node.forwardingStubSuperTarget != null) ||
         !(node.isForwardingStub && node.function.body != null));
   }
@@ -868,10 +850,7 @@
     enterScope(memberScope: true);
     writeByte(Tag.Field);
     writeCanonicalNameReference(getCanonicalNameOfMember(node));
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
     writeByte(node.flags);
@@ -879,9 +858,6 @@
     writeAnnotationList(node.annotations);
     writeNode(node.type);
     writeOptionalNode(node.initializer);
-
-    _activeFileUri = activeFileUriSaved;
-
     leaveScope(memberScope: true);
   }
 
@@ -896,10 +872,7 @@
         memberScope: true,
         variableScope: true);
     writeCanonicalNameReference(getCanonicalNameOfMember(node));
-
-    final Uri activeFileUriSaved = _activeFileUri;
-    _activeFileUri = writeUriReference(node.fileUri);
-
+    writeUriReference(node.fileUri);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
     writeByte(node.flags);
@@ -914,8 +887,6 @@
     writeVariableDeclarationList(node.positionalParameters);
     writeVariableDeclarationList(node.namedParameters);
 
-    _activeFileUri = activeFileUriSaved;
-
     leaveScope(
         typeParameters: node.typeParameters,
         memberScope: true,
diff --git a/pkg/kernel/lib/binary/limited_ast_to_binary.dart b/pkg/kernel/lib/binary/limited_ast_to_binary.dart
index 82fe07d..bd00832 100644
--- a/pkg/kernel/lib/binary/limited_ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/limited_ast_to_binary.dart
@@ -24,7 +24,7 @@
 
   LimitedBinaryPrinter(
       Sink<List<int>> sink, this.predicate, this.excludeUriToSource)
-      : super(sink);
+      : super(sink, includeSources: !excludeUriToSource);
 
   @override
   void computeCanonicalNames(Component component) {
@@ -60,13 +60,4 @@
     var librariesToWrite = libraries.where(predicate).toList();
     super.writeComponentIndex(component, librariesToWrite);
   }
-
-  @override
-  void indexUris(Component component) {
-    if (!excludeUriToSource) {
-      super.indexUris(component);
-    } else {
-      // We pretend not to know any uris, thereby excluding all sources.
-    }
-  }
 }
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index b453f06..5dc341f 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -5,19 +5,190 @@
 import '../ast.dart'
     show
         BottomType,
+        Class,
         DartType,
         DynamicType,
         FunctionType,
         InterfaceType,
+        InvalidType,
         NamedType,
         TypeParameter,
+        TypeParameterType,
         TypedefType,
         VoidType;
 
-import '../type_algebra.dart' show substitute;
+import '../type_algebra.dart' show Substitution, substitute;
 
 import '../type_environment.dart' show TypeEnvironment;
 
+import '../util/graph.dart' show Graph, computeStrongComponents;
+
+import '../visitor.dart' show DartTypeVisitor;
+
+class TypeVariableGraph extends Graph<int> {
+  List<int> vertices;
+  List<TypeParameter> typeParameters;
+  List<DartType> bounds;
+
+  // `edges[i]` is the list of indices of type variables that reference the type
+  // variable with the index `i` in their bounds.
+  List<List<int>> edges;
+
+  TypeVariableGraph(this.typeParameters, this.bounds) {
+    assert(typeParameters.length == bounds.length);
+
+    vertices = new List<int>(typeParameters.length);
+    Map<TypeParameter, int> typeParameterIndices = <TypeParameter, int>{};
+    edges = new List<List<int>>(typeParameters.length);
+    for (int i = 0; i < vertices.length; i++) {
+      vertices[i] = i;
+      typeParameterIndices[typeParameters[i]] = i;
+      edges[i] = <int>[];
+    }
+
+    for (int i = 0; i < vertices.length; i++) {
+      OccurrenceCollectorVisitor collector =
+          new OccurrenceCollectorVisitor(typeParameters.toSet());
+      collector.visit(bounds[i]);
+      for (TypeParameter typeParameter in collector.occurred) {
+        edges[typeParameterIndices[typeParameter]].add(i);
+      }
+    }
+  }
+
+  Iterable<int> neighborsOf(int index) {
+    return edges[index];
+  }
+}
+
+class OccurrenceCollectorVisitor extends DartTypeVisitor {
+  final Set<TypeParameter> typeParameters;
+  Set<TypeParameter> occurred = new Set<TypeParameter>();
+
+  OccurrenceCollectorVisitor(this.typeParameters);
+
+  visit(DartType node) => node.accept(this);
+
+  visitNamedType(NamedType node) {
+    node.type.accept(this);
+  }
+
+  visitInvalidType(InvalidType node);
+  visitDynamicType(DynamicType node);
+  visitVoidType(VoidType node);
+
+  visitInterfaceType(InterfaceType node) {
+    for (DartType argument in node.typeArguments) {
+      argument.accept(this);
+    }
+  }
+
+  visitTypedefType(TypedefType node) {
+    for (DartType argument in node.typeArguments) {
+      argument.accept(this);
+    }
+  }
+
+  visitFunctionType(FunctionType node) {
+    for (TypeParameter typeParameter in node.typeParameters) {
+      typeParameter.bound.accept(this);
+      typeParameter.defaultType?.accept(this);
+    }
+    for (DartType parameter in node.positionalParameters) {
+      parameter.accept(this);
+    }
+    for (NamedType namedParameter in node.namedParameters) {
+      namedParameter.type.accept(this);
+    }
+    node.returnType.accept(this);
+  }
+
+  visitTypeParameterType(TypeParameterType node) {
+    if (typeParameters.contains(node.parameter)) {
+      occurred.add(node.parameter);
+    }
+  }
+}
+
+DartType instantiateToBounds(DartType type, Class object) {
+  if (type is InterfaceType) {
+    for (var typeArgument in type.typeArguments) {
+      // If at least one of the arguments is not dynamic, we assume that the
+      // type is not raw and does not need instantiation of its type parameters
+      // to their bounds.
+      if (typeArgument is! DynamicType) {
+        return type;
+      }
+    }
+    return new InterfaceType.byReference(
+        type.className, calculateBounds(type.classNode.typeParameters, object));
+  }
+  if (type is TypedefType) {
+    for (var typeArgument in type.typeArguments) {
+      if (typeArgument is! DynamicType) {
+        return type;
+      }
+    }
+    return new TypedefType.byReference(type.typedefReference,
+        calculateBounds(type.typedefNode.typeParameters, object));
+  }
+  return type;
+}
+
+/// Calculates bounds to be provided as type arguments in place of missing type
+/// arguments on raw types with the given type parameters.
+///
+/// See the [description]
+/// (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/instantiate-to-bound.md)
+/// of the algorithm for details.
+List<DartType> calculateBounds(
+    List<TypeParameter> typeParameters, Class object) {
+  List<DartType> bounds = new List<DartType>(typeParameters.length);
+  for (int i = 0; i < typeParameters.length; i++) {
+    DartType bound = typeParameters[i].bound;
+    if (bound == null) {
+      bound = const DynamicType();
+    } else if (bound is InterfaceType && bound.classNode == object) {
+      DartType defaultType = typeParameters[i].defaultType;
+      if (!(defaultType is InterfaceType && defaultType.classNode == object)) {
+        bound = const DynamicType();
+      }
+    }
+    bounds[i] = bound;
+  }
+
+  TypeVariableGraph graph = new TypeVariableGraph(typeParameters, bounds);
+  List<List<int>> stronglyConnected = computeStrongComponents(graph);
+  for (List<int> component in stronglyConnected) {
+    Map<TypeParameter, DartType> upperBounds = <TypeParameter, DartType>{};
+    Map<TypeParameter, DartType> lowerBounds = <TypeParameter, DartType>{};
+    for (int typeParameterIndex in component) {
+      upperBounds[typeParameters[typeParameterIndex]] = const DynamicType();
+      lowerBounds[typeParameters[typeParameterIndex]] = const BottomType();
+    }
+    Substitution substitution =
+        Substitution.fromUpperAndLowerBounds(upperBounds, lowerBounds);
+    for (int typeParameterIndex in component) {
+      bounds[typeParameterIndex] =
+          substitution.substituteType(bounds[typeParameterIndex]);
+    }
+  }
+
+  for (int i = 0; i < typeParameters.length; i++) {
+    Map<TypeParameter, DartType> upperBounds = <TypeParameter, DartType>{};
+    Map<TypeParameter, DartType> lowerBounds = <TypeParameter, DartType>{};
+    upperBounds[typeParameters[i]] = bounds[i];
+    lowerBounds[typeParameters[i]] = const BottomType();
+    Substitution substitution =
+        Substitution.fromUpperAndLowerBounds(upperBounds, lowerBounds);
+    for (int j = 0; j < typeParameters.length; j++) {
+      bounds[j] = substitution.substituteType(bounds[j]);
+    }
+  }
+
+  return bounds;
+}
+
 class TypeArgumentIssue {
   // The type argument that violated the bound.
   final DartType argument;
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 7268136..094bd2f 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -5,8 +5,6 @@
 
 import 'ast.dart';
 
-import 'util/graph.dart';
-
 /// Returns a type where all occurrences of the given type parameters have been
 /// replaced with the corresponding types.
 ///
@@ -68,126 +66,6 @@
   return substitutor.isInfinite ? null : result;
 }
 
-/// Calculates bounds to be provided as type arguments in place of missing type
-/// arguments on raw types with the given type parameters.
-///
-/// See the [description]
-/// (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/instantiate-to-bound.md)
-/// of the algorithm for details.
-List<DartType> calculateBounds(
-    List<TypeParameter> typeParameters, Class object) {
-  List<DartType> bounds = new List<DartType>(typeParameters.length);
-  for (int i = 0; i < typeParameters.length; i++) {
-    DartType bound = typeParameters[i].bound;
-    if (bound == null) {
-      bound = const DynamicType();
-    } else if (bound is InterfaceType && bound.classNode == object) {
-      DartType defaultType = typeParameters[i].defaultType;
-      if (!(defaultType is InterfaceType && defaultType.classNode == object)) {
-        bound = const DynamicType();
-      }
-    }
-    bounds[i] = bound;
-  }
-
-  _TypeVariableGraph graph = new _TypeVariableGraph(typeParameters, bounds);
-  List<List<int>> stronglyConnected = computeStrongComponents(graph);
-  for (List<int> component in stronglyConnected) {
-    Map<TypeParameter, DartType> dynamicSubstitution =
-        <TypeParameter, DartType>{};
-    Map<TypeParameter, DartType> nullSubstitution = <TypeParameter, DartType>{};
-    for (int typeParameterIndex in component) {
-      dynamicSubstitution[typeParameters[typeParameterIndex]] =
-          const DynamicType();
-      nullSubstitution[typeParameters[typeParameterIndex]] = const BottomType();
-    }
-    _TopSubstitutor substitutor = new _TopSubstitutor(
-        Substitution.fromUpperAndLowerBounds(
-            dynamicSubstitution, nullSubstitution),
-        false);
-    for (int typeParameterIndex in component) {
-      bounds[typeParameterIndex] =
-          substitutor.visit(bounds[typeParameterIndex]);
-    }
-  }
-
-  for (int i = 0; i < typeParameters.length; i++) {
-    Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
-    Map<TypeParameter, DartType> nullSubstitution = <TypeParameter, DartType>{};
-    substitution[typeParameters[i]] = bounds[i];
-    nullSubstitution[typeParameters[i]] = const BottomType();
-    _TopSubstitutor substitutor = new _TopSubstitutor(
-        Substitution.fromUpperAndLowerBounds(substitution, nullSubstitution),
-        false);
-    for (int j = 0; j < typeParameters.length; j++) {
-      bounds[j] = substitutor.visit(bounds[j]);
-    }
-  }
-
-  return bounds;
-}
-
-class _TypeVariableGraph extends Graph<int> {
-  List<int> vertices;
-  List<TypeParameter> typeParameters;
-  List<DartType> bounds;
-
-  // `edges[i]` is the list of indices of type variables that reference the type
-  // variable with the index `i` in their bounds.
-  List<List<int>> edges;
-
-  _TypeVariableGraph(this.typeParameters, this.bounds) {
-    assert(typeParameters.length == bounds.length);
-
-    vertices = new List<int>(typeParameters.length);
-    Map<TypeParameter, int> typeParameterIndices = <TypeParameter, int>{};
-    edges = new List<List<int>>(typeParameters.length);
-    for (int i = 0; i < vertices.length; i++) {
-      vertices[i] = i;
-      typeParameterIndices[typeParameters[i]] = i;
-      edges[i] = <int>[];
-    }
-
-    for (int i = 0; i < vertices.length; i++) {
-      _OccurrenceCollectorVisitor collector =
-          new _OccurrenceCollectorVisitor(typeParameters.toSet());
-      collector.visit(bounds[i]);
-      for (TypeParameter typeParameter in collector.occurred) {
-        edges[typeParameterIndices[typeParameter]].add(i);
-      }
-    }
-  }
-
-  Iterable<int> neighborsOf(int index) {
-    return edges[index];
-  }
-}
-
-DartType instantiateToBounds(DartType type, Class object) {
-  if (type is InterfaceType) {
-    for (var typeArgument in type.typeArguments) {
-      // If at least one of the arguments is not dynamic, we assume that the
-      // type is not raw and does not need instantiation of its type parameters
-      // to their bounds.
-      if (typeArgument is! DynamicType) {
-        return type;
-      }
-    }
-    return new InterfaceType.byReference(
-        type.className, calculateBounds(type.classNode.typeParameters, object));
-  }
-  if (type is TypedefType) {
-    for (var typeArgument in type.typeArguments) {
-      if (typeArgument is! DynamicType) {
-        return type;
-      }
-    }
-    return new TypedefType.byReference(type.typedefReference,
-        calculateBounds(type.typedefNode.typeParameters, object));
-  }
-  return type;
-}
-
 /// Returns true if [type] contains a reference to any of the given [variables].
 ///
 /// It is an error to call this with a [type] that contains a [FunctionType]
@@ -854,52 +732,3 @@
     return node.defaultType.accept(this);
   }
 }
-
-class _OccurrenceCollectorVisitor extends DartTypeVisitor {
-  final Set<TypeParameter> typeParameters;
-  Set<TypeParameter> occurred = new Set<TypeParameter>();
-
-  _OccurrenceCollectorVisitor(this.typeParameters);
-
-  visit(DartType node) => node.accept(this);
-
-  visitNamedType(NamedType node) {
-    node.type.accept(this);
-  }
-
-  visitInvalidType(InvalidType node);
-  visitDynamicType(DynamicType node);
-  visitVoidType(VoidType node);
-
-  visitInterfaceType(InterfaceType node) {
-    for (DartType argument in node.typeArguments) {
-      argument.accept(this);
-    }
-  }
-
-  visitTypedefType(TypedefType node) {
-    for (DartType argument in node.typeArguments) {
-      argument.accept(this);
-    }
-  }
-
-  visitFunctionType(FunctionType node) {
-    for (TypeParameter typeParameter in node.typeParameters) {
-      typeParameter.bound.accept(this);
-      typeParameter.defaultType?.accept(this);
-    }
-    for (DartType parameter in node.positionalParameters) {
-      parameter.accept(this);
-    }
-    for (NamedType namedParameter in node.namedParameters) {
-      namedParameter.type.accept(this);
-    }
-    node.returnType.accept(this);
-  }
-
-  visitTypeParameterType(TypeParameterType node) {
-    if (typeParameters.contains(node.parameter)) {
-      occurred.add(node.parameter);
-    }
-  }
-}
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index ea0b8d1..9bd0e37 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -259,6 +259,7 @@
         useAnalyzerCfe: boolOption("use-cfe"),
         useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"),
         useBlobs: boolOption("use-blobs"),
+        keepGeneratedFiles: boolOption("keep-generated-files"),
         useDart2JSWithKernel: boolOption("dart2js-with-kernel"),
         useDart2JSOldFrontEnd: boolOption("dart2js-old-frontend"),
         useFastStartup: boolOption("fast-startup"),
@@ -314,6 +315,9 @@
   // TODO(rnystrom): What is this?
   final bool useBlobs;
 
+  // Keep generated files (instead of deleting them).
+  final bool keepGeneratedFiles;
+
   // TODO(rnystrom): Remove these when Dart 1.0 is no longer supported.
   final bool useDart2JSWithKernel;
   final bool useDart2JSOldFrontEnd;
@@ -339,6 +343,7 @@
       bool useAnalyzerCfe,
       bool useAnalyzerFastaParser,
       bool useBlobs,
+      bool keepGeneratedFiles,
       bool useDart2JSWithKernel,
       bool useDart2JSOldFrontEnd,
       bool useFastStartup,
@@ -357,6 +362,7 @@
         useAnalyzerCfe = useAnalyzerCfe ?? false,
         useAnalyzerFastaParser = useAnalyzerFastaParser ?? false,
         useBlobs = useBlobs ?? false,
+        keepGeneratedFiles = keepGeneratedFiles ?? false,
         useDart2JSWithKernel = useDart2JSWithKernel ?? false,
         useDart2JSOldFrontEnd = useDart2JSOldFrontEnd ?? false,
         useFastStartup = useFastStartup ?? false,
@@ -384,6 +390,7 @@
       useAnalyzerCfe == other.useAnalyzerCfe &&
       useAnalyzerFastaParser == other.useAnalyzerFastaParser &&
       useBlobs == other.useBlobs &&
+      keepGeneratedFiles == other.keepGeneratedFiles &&
       useDart2JSWithKernel == other.useDart2JSWithKernel &&
       useDart2JSOldFrontEnd == other.useDart2JSOldFrontEnd &&
       useFastStartup == other.useFastStartup &&
@@ -418,7 +425,8 @@
       (useFastStartup ? 2048 : 0) ^
       (useHotReload ? 4096 : 0) ^
       (useHotReloadRollback ? 8192 : 0) ^
-      (useSdk ? 16384 : 0);
+      (useSdk ? 16384 : 0) ^
+      (keepGeneratedFiles ? 32768 : 0);
 
   String toString() {
     var buffer = new StringBuffer();
@@ -444,6 +452,7 @@
     if (useAnalyzerCfe) fields.add("use-cfe");
     if (useAnalyzerFastaParser) fields.add("analyzer-use-fasta-parser");
     if (useBlobs) fields.add("use-blobs");
+    if (keepGeneratedFiles) fields.add("keep-generated-files");
     if (useDart2JSWithKernel) fields.add("dart2js-with-kernel");
     if (useDart2JSOldFrontEnd) fields.add("dart2js-old-frontend");
     if (useFastStartup) fields.add("fast-startup");
@@ -507,6 +516,10 @@
     if (useBlobs || other.useBlobs) {
       fields.add("useBlobs $useBlobs ${other.useBlobs}");
     }
+    if (keepGeneratedFiles || other.keepGeneratedFiles) {
+      fields.add(
+          "keepGeneratedFiles $keepGeneratedFiles ${other.keepGeneratedFiles}");
+    }
     if (useDart2JSWithKernel || other.useDart2JSWithKernel) {
       fields.add("useDart2JSWithKernel "
           "$useDart2JSWithKernel ${other.useDart2JSWithKernel}");
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 69c2c9f..b5d7d03 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -565,7 +565,7 @@
     1 /* isolateId chosen randomly */,
     [] /* source files */,
     false /* suppress warnings */,
-    true /* synchronous async */,
+    false /* generate bytecode */,
     null /* package_config */,
     null /* multirootFilepaths */,
     null /* multirootScheme */,
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
index 3252cc3..0ab0b88 100644
--- a/pkg/vm/lib/transformations/pragma.dart
+++ b/pkg/vm/lib/transformations/pragma.dart
@@ -9,6 +9,7 @@
 
 const kEntryPointPragmaName = "vm:entry-point";
 const kExactResultTypePragmaName = "vm:exact-result-type";
+const kNonNullableResultType = "vm:non-nullable-result-type";
 
 abstract class ParsedPragma {}
 
@@ -29,6 +30,10 @@
   ParsedResultTypeByPathPragma(this.path);
 }
 
+class ParsedNonNullableResultType extends ParsedPragma {
+  ParsedNonNullableResultType();
+}
+
 abstract class PragmaAnnotationParser {
   /// May return 'null' if the annotation does not represent a recognized
   /// @pragma.
@@ -91,6 +96,8 @@
         }
         throw "ERROR: Unsupported option to '$kExactResultTypePragmaName' "
             "pragma: $options";
+      case kNonNullableResultType:
+        return new ParsedNonNullableResultType();
       default:
         return null;
     }
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index cb6b7ce..291237b 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -159,12 +159,14 @@
   Type handleNativeProcedure(
       Member member, EntryPointsListener entryPointsListener) {
     Type returnType = null;
+    bool nullable = null;
 
     for (var annotation in member.annotations) {
       ParsedPragma pragma = _matcher.parsePragma(annotation);
       if (pragma == null) continue;
       if (pragma is ParsedResultTypeByTypePragma ||
-          pragma is ParsedResultTypeByPathPragma) {
+          pragma is ParsedResultTypeByPathPragma ||
+          pragma is ParsedNonNullableResultType) {
         // We can only use the 'vm:exact-result-type' pragma on methods in core
         // libraries for safety reasons. See 'result_type_pragma.md', detail 1.2
         // for explanation.
@@ -177,7 +179,7 @@
         var type = pragma.type;
         if (type is InterfaceType) {
           returnType = entryPointsListener.addAllocatedClass(type.classNode);
-          break;
+          continue;
         }
         throw "ERROR: Invalid return type for native method: ${pragma.type}";
       } else if (pragma is ParsedResultTypeByPathPragma) {
@@ -192,16 +194,22 @@
         // Error is thrown on the next line if the class is not found.
         Class klass = _libraryIndex.getClass(libName, klassName);
         Type concreteClass = entryPointsListener.addAllocatedClass(klass);
-
         returnType = concreteClass;
-        break;
+      } else if (pragma is ParsedNonNullableResultType) {
+        nullable = false;
       }
     }
 
+    if (returnType != null && nullable != null) {
+      throw 'ERROR: Cannot have both, @pragma("$kExactResultTypePragmaName") '
+          'and @pragma("$kNonNullableResultType"), annotating the same member.';
+    }
+
     if (returnType != null) {
       return returnType;
     } else {
-      return new Type.fromStatic(member.function.returnType);
+      final coneType = new Type.cone(member.function.returnType);
+      return nullable == false ? coneType : new Type.nullable(coneType);
     }
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 51a0d82..cf23ea8 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -96,6 +96,8 @@
     dartType = _normalizeDartType(dartType);
     if ((dartType == const DynamicType()) || (dartType == const VoidType())) {
       return const AnyType();
+    } else if (dartType == const BottomType()) {
+      return new Type.empty();
     } else {
       return new ConeType(dartType);
     }
diff --git a/pkg/vm/lib/v8_snapshot_profile.dart b/pkg/vm/lib/v8_snapshot_profile.dart
new file mode 100644
index 0000000..ec01774
--- /dev/null
+++ b/pkg/vm/lib/v8_snapshot_profile.dart
@@ -0,0 +1,239 @@
+// 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";
+import "package:dart2js_info/src/graph.dart";
+
+class _NodeInfo {
+  int type;
+  int name;
+  int id;
+  int selfSize;
+  int edgeCount;
+  _NodeInfo(
+    this.type,
+    this.name,
+    this.id,
+    this.selfSize,
+    this.edgeCount,
+  );
+}
+
+const List<String> _kRequiredNodeFields = [
+  "type",
+  "name",
+  "id",
+  "self_size",
+  "edge_count",
+];
+
+class _EdgeInfo {
+  int type;
+  int nameOrIndex;
+  int nodeOffset;
+  _EdgeInfo(
+    this.type,
+    this.nameOrIndex,
+    this.nodeOffset,
+  );
+}
+
+const List<String> _kRequiredEdgeFields = [
+  "type",
+  "name_or_index",
+  "to_node",
+];
+
+class NodeInfo {
+  String type;
+  String name;
+  int id;
+  int selfSize;
+  NodeInfo(
+    this.type,
+    this.name,
+    this.id,
+    this.selfSize,
+  );
+}
+
+class V8SnapshotProfile extends Graph<int> {
+  // Indexed by node offset.
+  final Map<int, _NodeInfo> _nodes = {};
+
+  // Indexed by start node offset.
+  final Map<int, List<_EdgeInfo>> _toEdges = {};
+  final Map<int, List<_EdgeInfo>> _fromEdges = {};
+
+  List<String> _nodeFields = [];
+  List<String> _edgeFields = [];
+
+  List<String> _nodeTypes = [];
+  List<String> _edgeTypes = [];
+
+  List<String> _strings = [];
+
+  // Only used to ensure IDs are unique.
+  Set<int> _ids = Set<int>();
+
+  V8SnapshotProfile.fromJson(Map top) {
+    final Map snapshot = top["snapshot"];
+    _parseMetadata(snapshot["meta"]);
+
+    _parseStrings(top["strings"]);
+    Expect.equals(snapshot["node_count"], _parseNodes(top["nodes"]));
+    Expect.equals(snapshot["edge_count"], _parseEdges(top["edges"]));
+
+    _calculateFromEdges();
+  }
+
+  void _parseMetadata(Map meta) {
+    final List nodeFields = meta["node_fields"];
+    nodeFields.forEach(_nodeFields.add);
+    Expect.isTrue(_kRequiredNodeFields.every(_nodeFields.contains));
+
+    final List edgeFields = meta["edge_fields"];
+    edgeFields.forEach(_edgeFields.add);
+    Expect.isTrue(_kRequiredEdgeFields.every(_edgeFields.contains));
+
+    // First entry of "node_types" is an array with the actual node types. IDK
+    // what the other entries are for.
+    List nodeTypes = meta["node_types"];
+    nodeTypes = nodeTypes[0];
+    nodeTypes.forEach(_nodeTypes.add);
+
+    // Same for edges.
+    List edgeTypes = meta["edge_types"];
+    edgeTypes = edgeTypes[0];
+    edgeTypes.forEach(_edgeTypes.add);
+  }
+
+  int _parseNodes(List nodes) {
+    final int typeIndex = _nodeFields.indexOf("type");
+    final int nameIndex = _nodeFields.indexOf("name");
+    final int idIndex = _nodeFields.indexOf("id");
+    final int selfSizeIndex = _nodeFields.indexOf("self_size");
+    final int edgeCountIndex = _nodeFields.indexOf("edge_count");
+
+    int offset = 0;
+    for (; offset < nodes.length; offset += _nodeFields.length) {
+      final int type = nodes[offset + typeIndex];
+      Expect.isTrue(0 <= type && type < _nodeTypes.length);
+
+      final int name = nodes[offset + nameIndex];
+      Expect.isTrue(0 <= name && name < _strings.length);
+
+      final int id = nodes[offset + idIndex];
+      Expect.isTrue(id >= 0);
+      Expect.isFalse(_ids.contains(id));
+      _ids.add(id);
+
+      final int selfSize = nodes[offset + selfSizeIndex];
+      Expect.isTrue(selfSize >= 0);
+
+      final int edgeCount = nodes[offset + edgeCountIndex];
+      Expect.isTrue(edgeCount >= 0);
+
+      _nodes[offset] = _NodeInfo(type, name, id, selfSize, edgeCount);
+    }
+
+    Expect.equals(offset, nodes.length);
+    return offset ~/ _nodeFields.length;
+  }
+
+  int _parseEdges(List edges) {
+    final int typeIndex = _edgeFields.indexOf("type");
+    final int nameOrIndexIndex = _edgeFields.indexOf("name_or_index");
+    final int toNodeIndex = _edgeFields.indexOf("to_node");
+
+    int edgeOffset = 0;
+    for (int nodeOffset = 0;
+        nodeOffset < _nodes.length * _nodeFields.length;
+        nodeOffset += _nodeFields.length) {
+      final int edgeCount = _nodes[nodeOffset].edgeCount;
+      final List<_EdgeInfo> nodeEdges = List<_EdgeInfo>(edgeCount);
+      for (int i = 0; i < edgeCount; ++i, edgeOffset += _edgeFields.length) {
+        final int type = edges[edgeOffset + typeIndex];
+        Expect.isTrue(0 <= type && type < _edgeTypes.length);
+
+        final int nameOrIndex = edges[edgeOffset + nameOrIndexIndex];
+        if (_edgeTypes[type] == "property") {
+          Expect.isTrue(0 <= nameOrIndex && nameOrIndex < _strings.length);
+        } else if (_edgeTypes[type] == "element") {
+          Expect.isTrue(nameOrIndex >= 0);
+        }
+
+        final int toNode = edges[edgeOffset + toNodeIndex];
+        checkNode(toNode);
+        nodeEdges[i] = _EdgeInfo(type, nameOrIndex, toNode);
+      }
+      _toEdges[nodeOffset] = nodeEdges;
+    }
+
+    Expect.equals(edgeOffset, edges.length);
+    return edgeOffset ~/ _edgeFields.length;
+  }
+
+  void checkNode(int offset) {
+    Expect.isTrue(offset >= 0 &&
+        offset % _nodeFields.length == 0 &&
+        offset ~/ _nodeFields.length < _nodes.length);
+  }
+
+  void _calculateFromEdges() {
+    for (final MapEntry<int, List<_EdgeInfo>> entry in _toEdges.entries) {
+      final int fromNode = entry.key;
+      for (final _EdgeInfo edge in entry.value) {
+        final List<_EdgeInfo> backEdges =
+            _fromEdges.putIfAbsent(edge.nodeOffset, () => <_EdgeInfo>[]);
+        backEdges.add(_EdgeInfo(edge.type, edge.nameOrIndex, fromNode));
+      }
+    }
+  }
+
+  void _parseStrings(List strings) => strings.forEach(_strings.add);
+
+  int get accountedBytes {
+    int sum = 0;
+    for (final _NodeInfo info in _nodes.values) {
+      sum += info.selfSize;
+    }
+    return sum;
+  }
+
+  int get unknownCount {
+    final int unknownType = _nodeTypes.indexOf("Unknown");
+    Expect.isTrue(unknownType >= 0);
+
+    int count = 0;
+    for (final MapEntry<int, _NodeInfo> entry in _nodes.entries) {
+      if (entry.value.type == unknownType) {
+        ++count;
+      }
+    }
+    return count;
+  }
+
+  bool get isEmpty => _nodes.isEmpty;
+  int get nodeCount => _nodes.length;
+
+  Iterable<int> get nodes => _nodes.keys;
+
+  Iterable<int> targetsOf(int source) {
+    return _toEdges[source].map((_EdgeInfo i) => i.nodeOffset);
+  }
+
+  Iterable<int> sourcesOf(int source) {
+    return _fromEdges[source].map((_EdgeInfo i) => i.nodeOffset);
+  }
+
+  int get root => 0;
+
+  NodeInfo operator [](int node) {
+    _NodeInfo info = _nodes[node];
+    final type = info.type != null ? _nodeTypes[info.type] : null;
+    final name = info.name != null ? _strings[info.name] : null;
+    return NodeInfo(type, name, info.id, info.selfSize);
+  }
+}
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index 1d49fff..c6f5421 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -13,7 +13,6 @@
 # passed to Fasta.
 
 set -e
-set -x
 
 OPTIONS=()
 GEN_KERNEL_OPTIONS=()
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index a6f8e93..3eb59b3 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -7,7 +7,10 @@
 import("runtime_args.gni")
 
 config("dart_public_config") {
-  include_dirs = [ "include" ]
+  include_dirs = [
+    ".",
+    "include",
+  ]
 }
 
 # Adds PRODUCT define if Flutter has specified "release" for dart_runtime_mode
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index cec8c52..a5c2317 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -157,6 +157,8 @@
       "dfe.cc",
       "dfe.h",
       "gen_snapshot.cc",
+      "kernel_isolate.cc",
+      "kernel_isolate.h",
       "options.cc",
       "options.h",
       "vmservice_impl.cc",
@@ -340,6 +342,7 @@
                  "..:dart_config",
                  "..:dart_os_config",
                ] + extra_configs
+    public_configs = [ "..:dart_public_config" ]
     if (is_fuchsia) {
       configs -= [ "//build/config:symbol_visibility_hidden" ]
     }
@@ -714,6 +717,8 @@
                 "dart_embedder_api_impl.cc",
                 "error_exit.cc",
                 "error_exit.h",
+                "kernel_isolate.cc",
+                "kernel_isolate.h",
                 "main.cc",
                 "main_options.cc",
                 "main_options.h",
@@ -936,6 +941,8 @@
               "dfe.h",
               "error_exit.cc",
               "error_exit.h",
+              "kernel_isolate.cc",
+              "kernel_isolate.h",
               "run_vm_tests.cc",
               "snapshot_utils.cc",
               "snapshot_utils.h",
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index af520658..47d95d2 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -5,6 +5,7 @@
 #ifndef RUNTIME_BIN_DFE_H_
 #define RUNTIME_BIN_DFE_H_
 
+#include "bin/kernel_isolate.h"
 #include "include/dart_api.h"
 #include "include/dart_native_api.h"
 #include "platform/assert.h"
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 0fd8939..40aaf7d 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -76,12 +76,31 @@
 }
 
 MappedMemory* File::Map(MapType type, int64_t position, int64_t length) {
-  UNIMPLEMENTED();
-  return NULL;
+  ASSERT(handle_->fd() >= 0);
+  ASSERT(length > 0);
+  int prot = PROT_NONE;
+  switch (type) {
+    case kReadOnly:
+      prot = PROT_READ;
+      break;
+    case kReadExecute:
+      prot = PROT_READ | PROT_EXEC;
+      break;
+    default:
+      return NULL;
+  }
+  void* addr = mmap(NULL, length, prot, MAP_PRIVATE, handle_->fd(), position);
+  if (addr == MAP_FAILED) {
+    return NULL;
+  }
+  return new MappedMemory(addr, length);
 }
 
 void MappedMemory::Unmap() {
-  UNIMPLEMENTED();
+  int result = munmap(address_, size_);
+  ASSERT(result == 0);
+  address_ = 0;
+  size_ = 0;
 }
 
 int64_t File::Read(void* buffer, int64_t num_bytes) {
diff --git a/runtime/bin/file_system_watcher_fuchsia.cc b/runtime/bin/file_system_watcher_fuchsia.cc
index aa943eb..d898542 100644
--- a/runtime/bin/file_system_watcher_fuchsia.cc
+++ b/runtime/bin/file_system_watcher_fuchsia.cc
@@ -7,16 +7,18 @@
 
 #include "bin/file_system_watcher.h"
 
+#include <errno.h>
+
 namespace dart {
 namespace bin {
 
 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return DartUtils::NewDartOSError();
 }
 
 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return -1;
 }
 
@@ -25,7 +27,6 @@
 }
 
 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
-  UNIMPLEMENTED();
 }
 
 intptr_t FileSystemWatcher::Init() {
@@ -33,7 +34,6 @@
 }
 
 void FileSystemWatcher::Close(intptr_t id) {
-  UNIMPLEMENTED();
 }
 
 intptr_t FileSystemWatcher::WatchPath(intptr_t id,
@@ -41,7 +41,7 @@
                                       const char* path,
                                       int events,
                                       bool recursive) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return -1;
 }
 
diff --git a/runtime/bin/kernel_isolate.cc b/runtime/bin/kernel_isolate.cc
new file mode 100644
index 0000000..c6bc711
--- /dev/null
+++ b/runtime/bin/kernel_isolate.cc
@@ -0,0 +1,110 @@
+// 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.
+
+#include "bin/kernel_isolate.h"
+
+#include "vm/dart_api_impl.h"
+#include "vm/isolate.h"
+#include "vm/kernel_isolate.h"
+
+namespace dart {
+
+DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return false;
+#else
+  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
+  return KernelIsolate::IsKernelIsolate(iso);
+#endif
+}
+
+DART_EXPORT bool Dart_KernelIsolateIsRunning() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return false;
+#else
+  return KernelIsolate::IsRunning();
+#endif
+}
+
+DART_EXPORT Dart_Port Dart_KernelPort() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return false;
+#else
+  return KernelIsolate::KernelPort();
+#endif
+}
+
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileToKernel(const char* script_uri,
+                     const uint8_t* platform_kernel,
+                     intptr_t platform_kernel_size,
+                     bool incremental_compile,
+                     const char* package_config) {
+  API_TIMELINE_DURATION(Thread::Current());
+
+  Dart_KernelCompilationResult result;
+#if defined(DART_PRECOMPILED_RUNTIME)
+  result.status = Dart_KernelCompilationStatus_Unknown;
+  result.error = strdup("Dart_CompileToKernel is unsupported.");
+#else
+  result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
+                                          platform_kernel_size, 0, NULL,
+                                          incremental_compile, package_config);
+  if (result.status == Dart_KernelCompilationStatus_Ok) {
+    Dart_KernelCompilationResult accept_result =
+        KernelIsolate::AcceptCompilation();
+    if (accept_result.status != Dart_KernelCompilationStatus_Ok) {
+      FATAL1(
+          "An error occurred in the CFE while accepting the most recent"
+          " compilation results: %s",
+          accept_result.error);
+    }
+  }
+#endif
+  return result;
+}
+
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileSourcesToKernel(const char* script_uri,
+                            const uint8_t* platform_kernel,
+                            intptr_t platform_kernel_size,
+                            int source_files_count,
+                            Dart_SourceFile sources[],
+                            bool incremental_compile,
+                            const char* package_config,
+                            const char* multiroot_filepaths,
+                            const char* multiroot_scheme) {
+  Dart_KernelCompilationResult result;
+#if defined(DART_PRECOMPILED_RUNTIME)
+  result.status = Dart_KernelCompilationStatus_Unknown;
+  result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
+#else
+  result = KernelIsolate::CompileToKernel(
+      script_uri, platform_kernel, platform_kernel_size, source_files_count,
+      sources, incremental_compile, package_config, multiroot_filepaths,
+      multiroot_scheme);
+  if (result.status == Dart_KernelCompilationStatus_Ok) {
+    if (KernelIsolate::AcceptCompilation().status !=
+        Dart_KernelCompilationStatus_Ok) {
+      FATAL(
+          "An error occurred in the CFE while accepting the most recent"
+          " compilation results.");
+    }
+  }
+#endif
+  return result;
+}
+
+DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
+  Dart_KernelCompilationResult result;
+#if defined(DART_PRECOMPILED_RUNTIME)
+  result.status = Dart_KernelCompilationStatus_Unknown;
+  result.error = strdup("Dart_KernelListDependencies is unsupported.");
+#else
+  result = KernelIsolate::ListDependencies();
+#endif
+  return result;
+}
+
+}  // namespace dart
diff --git a/runtime/bin/kernel_isolate.h b/runtime/bin/kernel_isolate.h
new file mode 100644
index 0000000..4a9e667
--- /dev/null
+++ b/runtime/bin/kernel_isolate.h
@@ -0,0 +1,58 @@
+// 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.
+
+#ifndef RUNTIME_BIN_KERNEL_ISOLATE_H_
+#define RUNTIME_BIN_KERNEL_ISOLATE_H_
+
+#include "include/dart_api.h"
+
+namespace dart {
+
+typedef enum {
+  Dart_KernelCompilationStatus_Unknown = -1,
+  Dart_KernelCompilationStatus_Ok = 0,
+  Dart_KernelCompilationStatus_Error = 1,
+  Dart_KernelCompilationStatus_Crash = 2,
+} Dart_KernelCompilationStatus;
+
+typedef struct {
+  Dart_KernelCompilationStatus status;
+  char* error;
+
+  uint8_t* kernel;
+  intptr_t kernel_size;
+} Dart_KernelCompilationResult;
+
+DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate);
+DART_EXPORT bool Dart_KernelIsolateIsRunning();
+DART_EXPORT Dart_Port Dart_KernelPort();
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileToKernel(const char* script_uri,
+                     const uint8_t* platform_kernel,
+                     const intptr_t platform_kernel_size,
+                     bool incremental_compile,
+                     const char* package_config);
+
+typedef struct {
+  const char* uri;
+  const char* source;
+} Dart_SourceFile;
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileSourcesToKernel(const char* script_uri,
+                            const uint8_t* platform_kernel,
+                            intptr_t platform_kernel_size,
+                            int source_files_count,
+                            Dart_SourceFile source_files[],
+                            bool incremental_compile,
+                            const char* package_config,
+                            const char* multiroot_filepaths,
+                            const char* multiroot_scheme);
+
+DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies();
+
+#define DART_KERNEL_ISOLATE_NAME "kernel-service"
+
+}  // namespace dart
+
+#endif  // RUNTIME_BIN_KERNEL_ISOLATE_H_
diff --git a/runtime/bin/platform_patch.dart b/runtime/bin/platform_patch.dart
index dd7d88a..99b4e7c 100644
--- a/runtime/bin/platform_patch.dart
+++ b/runtime/bin/platform_patch.dart
@@ -5,6 +5,7 @@
 // part of "common_patch.dart";
 
 @patch
+@pragma("vm:entry-point")
 class _Platform {
   @patch
   static int _numberOfProcessors() native "Platform_NumberOfProcessors";
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 08a7dcb..1608bc9 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -176,7 +176,7 @@
 
   static zx_status_t Add(zx_handle_t process) {
     MonitorLocker locker(monitor_);
-    LOG_INFO("ExitCodeHandler Adding Process: %ld\n", process);
+    LOG_INFO("ExitCodeHandler Adding Process: %u\n", process);
     return zx_object_wait_async(process, port_, static_cast<uint64_t>(process),
                                 ZX_TASK_TERMINATED, ZX_WAIT_ASYNC_ONCE);
   }
@@ -230,7 +230,7 @@
       zx_handle_t process = static_cast<zx_handle_t>(pkt.key);
       zx_signals_t observed = pkt.signal.observed;
       if ((observed & ZX_TASK_TERMINATED) == ZX_SIGNAL_NONE) {
-        LOG_ERR("ExitCodeHandler: Unexpected signals, process %ld: %lx\n",
+        LOG_ERR("ExitCodeHandler: Unexpected signals, process %u: %ux\n",
                 process, observed);
       }
       SendProcessStatus(process);
@@ -242,7 +242,7 @@
   }
 
   static void SendProcessStatus(zx_handle_t process) {
-    LOG_INFO("ExitCodeHandler thread getting process status: %ld\n", process);
+    LOG_INFO("ExitCodeHandler thread getting process status: %u\n", process);
     int return_code = -1;
     zx_info_process_t proc_info;
     zx_status_t status = zx_object_get_info(
@@ -254,11 +254,11 @@
       return_code = proc_info.return_code;
     }
     zx_handle_close(process);
-    LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process,
+    LOG_INFO("ExitCodeHandler thread process %u exited with %d\n", process,
              return_code);
 
     const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process);
-    LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process,
+    LOG_INFO("ExitCodeHandler thread sending %u code %d on fd %ld\n", process,
              return_code, exit_code_fd);
     if (exit_code_fd != 0) {
       int exit_message[2];
@@ -274,11 +274,11 @@
       }
       LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result,
                exit_code_fd);
-      LOG_INFO("ExitCodeHandler thread removing process %ld from list\n",
+      LOG_INFO("ExitCodeHandler thread removing process %u from list\n",
                process);
       ProcessInfoList::RemoveProcess(process);
     } else {
-      LOG_ERR("ExitCodeHandler: Process %ld not found\n", process);
+      LOG_ERR("ExitCodeHandler: Process %u not found\n", process);
     }
   }
 
@@ -615,8 +615,9 @@
     char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
     uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC |
         FDIO_SPAWN_CLONE_NAMESPACE;
-    status = fdio_spawn_vmo(ZX_HANDLE_INVALID, flags, vmo, program_arguments_,
-                            program_environment_, 4, actions, &process, err_msg);
+    status =
+        fdio_spawn_vmo(ZX_HANDLE_INVALID, flags, vmo, program_arguments_,
+                       program_environment_, 4, actions, &process, err_msg);
 
     if (status != ZX_OK) {
       LOG_ERR("ProcessStarter: Start() fdio_spawn_vmo failed\n");
@@ -626,7 +627,7 @@
       return status;
     }
 
-    LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n",
+    LOG_INFO("ProcessStarter: Start() adding %u to list with exit_pipe %d\n",
              process, exit_pipe_fds[1]);
     ProcessInfoList::AddProcess(process, exit_pipe_fds[1]);
     ExitCodeHandler::Start();
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 375fb93..373eb7d 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -192,6 +192,7 @@
   static _currentRss() native "ProcessInfo_CurrentRSS";
 }
 
+@pragma("vm:entry-point")
 class _ProcessStartStatus {
   @pragma("vm:entry-point", "set")
   int _errorCode; // Set to OS error code if process start failed.
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 5d61f88..876e789 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -64,6 +64,7 @@
  * are backed by an external C array of bytes, so that both Dart code and
  * native code can access the same data.
  */
+@pragma("vm:entry-point")
 class _SecureFilterImpl extends NativeFieldWrapperClass1
     implements _SecureFilter {
   // Performance is improved if a full buffer of plaintext fits
diff --git a/runtime/bin/socket_base_fuchsia.cc b/runtime/bin/socket_base_fuchsia.cc
index b89abf2..d6c9495a 100644
--- a/runtime/bin/socket_base_fuchsia.cc
+++ b/runtime/bin/socket_base_fuchsia.cc
@@ -118,8 +118,7 @@
                               intptr_t num_bytes,
                               RawAddr* addr,
                               SocketOpKind sync) {
-  LOG_ERR("SocketBase::RecvFrom is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return -1;
 }
 
@@ -152,8 +151,7 @@
                             intptr_t num_bytes,
                             const RawAddr& addr,
                             SocketOpKind sync) {
-  LOG_ERR("SocketBase::SendTo is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return -1;
 }
 
@@ -182,19 +180,16 @@
 }
 
 void SocketBase::GetError(intptr_t fd, OSError* os_error) {
-  LOG_ERR("SocketBase::GetError is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
+  os_error->SetCodeAndMessage(OSError::kSystem, errno);
 }
 
 int SocketBase::GetType(intptr_t fd) {
-  LOG_ERR("SocketBase::GetType is unimplemented\n");
-  UNIMPLEMENTED();
-  return File::kOther;
+  errno = ENOSYS;
+  return -1;
 }
 
 intptr_t SocketBase::GetStdioHandle(intptr_t num) {
-  LOG_ERR("SocketBase::GetStdioHandle is unimplemented\n");
-  UNIMPLEMENTED();
   return num;
 }
 
@@ -246,8 +241,7 @@
                                char* host,
                                intptr_t host_len,
                                OSError** os_error) {
-  LOG_ERR("SocketBase::ReverseLookup is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
@@ -335,8 +329,7 @@
 }
 
 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) {
-  LOG_ERR("SocketBase::GetNoDelay is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
@@ -351,40 +344,34 @@
 bool SocketBase::GetMulticastLoop(intptr_t fd,
                                   intptr_t protocol,
                                   bool* enabled) {
-  LOG_ERR("SocketBase::GetMulticastLoop is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool SocketBase::SetMulticastLoop(intptr_t fd,
                                   intptr_t protocol,
                                   bool enabled) {
-  LOG_ERR("SocketBase::SetMulticastLoop is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
-  LOG_ERR("SocketBase::GetMulticastHops is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
-  LOG_ERR("SocketBase::SetMulticastHops is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) {
-  LOG_ERR("SocketBase::GetBroadcast is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) {
-  LOG_ERR("SocketBase::SetBroadcast is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
@@ -392,8 +379,7 @@
                                const RawAddr& addr,
                                const RawAddr&,
                                int interfaceIndex) {
-  LOG_ERR("SocketBase::JoinMulticast is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
@@ -401,8 +387,7 @@
                                 const RawAddr& addr,
                                 const RawAddr&,
                                 int interfaceIndex) {
-  LOG_ERR("SocketBase::LeaveMulticast is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
diff --git a/runtime/bin/socket_fuchsia.cc b/runtime/bin/socket_fuchsia.cc
index 9655e23..d45119d 100644
--- a/runtime/bin/socket_fuchsia.cc
+++ b/runtime/bin/socket_fuchsia.cc
@@ -104,8 +104,7 @@
 
 intptr_t Socket::CreateBindConnect(const RawAddr& addr,
                                    const RawAddr& source_addr) {
-  LOG_ERR("SocketBase::CreateBindConnect is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return -1;
 }
 
@@ -113,8 +112,7 @@
                                     bool reuseAddress,
                                     bool reusePort,
                                     int ttl) {
-  LOG_ERR("SocketBase::CreateBindDatagram is unimplemented\n");
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return -1;
 }
 
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 9d11929..6b3e495 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -1071,16 +1071,17 @@
   }
 
   getOption(SocketOption option) {
-    if (option is! SocketOption) throw new ArgumentError(option);
+    if (option == null) throw new ArgumentError.notNull("option");
     var result = nativeGetOption(option._value, address.type._value);
     if (result is OSError) throw result;
     return result;
   }
 
   bool setOption(SocketOption option, value) {
-    if (option is! SocketOption) throw new ArgumentError(option);
+    if (option == null) throw new ArgumentError.notNull("option");
     var result = nativeSetOption(option._value, address.type._value, value);
-    if (result is OSError) throw result;
+    if (result != null) throw result;
+    return true;
   }
 
   InternetAddress multicastAddress(
@@ -1145,7 +1146,7 @@
   int nativeGetSocketId() native "Socket_GetSocketId";
   OSError nativeGetError() native "Socket_GetError";
   nativeGetOption(int option, int protocol) native "Socket_GetOption";
-  bool nativeSetOption(int option, int protocol, value)
+  OSError nativeSetOption(int option, int protocol, value)
       native "Socket_SetOption";
   OSError nativeJoinMulticast(List<int> addr, List<int> interfaceAddr,
       int interfaceIndex) native "Socket_JoinMulticast";
diff --git a/runtime/bin/stdio_fuchsia.cc b/runtime/bin/stdio_fuchsia.cc
index 65a2918..a626fee 100644
--- a/runtime/bin/stdio_fuchsia.cc
+++ b/runtime/bin/stdio_fuchsia.cc
@@ -7,47 +7,56 @@
 
 #include "bin/stdio.h"
 
+#include <errno.h>
+
+#include "platform/signal_blocker.h"
+
 namespace dart {
 namespace bin {
 
 bool Stdin::ReadByte(intptr_t fd, int* byte) {
-  UNIMPLEMENTED();
-  return false;
+  unsigned char b;
+  ssize_t s = TEMP_FAILURE_RETRY(read(fd, &b, 1));
+  if (s < 0) {
+    return false;
+  }
+  *byte = (s == 0) ? -1 : b;
+  return true;
 }
 
 bool Stdin::GetEchoMode(intptr_t fd, bool* enabled) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool Stdin::SetEchoMode(intptr_t fd, bool enabled) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool Stdin::GetLineMode(intptr_t fd, bool* enabled) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool Stdin::SetLineMode(intptr_t fd, bool enabled) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool Stdin::AnsiSupported(intptr_t fd, bool* supported) {
-  UNIMPLEMENTED();
-  return false;
+  *supported = false;
+  return true;
 }
 
 bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
 bool Stdout::AnsiSupported(intptr_t fd, bool* supported) {
-  UNIMPLEMENTED();
-  return false;
+  *supported = false;
+  return true;
 }
 
 }  // namespace bin
diff --git a/runtime/docs/compiler/pragmas_recognized_by_compiler.md b/runtime/docs/compiler/pragmas_recognized_by_compiler.md
new file mode 100644
index 0000000..21b2d13
--- /dev/null
+++ b/runtime/docs/compiler/pragmas_recognized_by_compiler.md
@@ -0,0 +1,83 @@
+# @pragma annotations recognized by the compiler.
+
+## Annotations for return types and field types.
+
+The VM is not able to see across method calls (apart from inlining) and
+therefore does not know anything about the return'ed values of calls, except for
+the interface type of the signature.
+
+To improve this we have two types of additional information sources the VM
+utilizes to gain knowledge about return types:
+
+   - inferred types (stored in kernel metadata): these are computed by global
+     transformations (e.g. TFA) and are only available in AOT mode
+
+   - @pragma annotations: these are recognized in JIT and AOT mode
+
+This return type information is mainly used in the VM's type propagator.
+
+Since those annotations side-step the normal type system, they are unsafe and we
+therefore restrict those annotations to only have an affect inside dart:
+libraries.
+
+### @pragma("vm:exact-result-type", <type>) annotation
+
+Tells the VM about the exact result type (i.e. the exact class-id) of a function
+or a field load.
+
+There are two limitations on this pragma:
+
+0. The Dart object returned by the method at runtime must have **exactly** the type specified in the annotation (not a subtype).
+
+1. The exact return type declared in the pragma must be a subtype of the interface type declared in the method signature.
+   Note that this restriction is not enforced automatically by the compiler.
+
+If those limitations are violated, undefined behavior may result.
+Note that since `null` is an instance of the `Null` type, which is a subtype of any other, exactness of the annotated result type implies that the result must be non-null.
+
+#### Syntax
+
+```dart
+class A {}
+class B extends A {}
+
+// Reference to type via type literal
+@pragma("vm:exact-result-type", B)
+A foo() native "foo_impl";
+
+// Reference to type via path
+@pragma("vm:exact-result-type", "dart:core#_Smi");
+int foo() native "foo_impl";
+
+class C {
+  // Reference to type via type literal
+  @pragma('vm:exact-result-type', B)
+  final B bValue;
+
+  // Reference to type via path
+  @pragma('vm:exact-result-type', "dart:core#_Smi")
+  final int intValue;
+}
+```
+
+### @pragma("vm:non-nullable-result-type") annotation
+
+Tells the VM that the method/field cannot return `null`.
+
+There is one limitation on this pragma:
+
+0. The Dart object returned by the method at runtime **must not** return `null`.
+
+If this limitation is violated, undefined behavior may result.
+
+#### Syntax
+
+```dart
+@pragma("vm:non-nullable-result-type")
+A foo() native "foo_impl";
+
+class C {
+  @pragma('vm:non-nullable-result-type");
+  final int value;
+}
+```
diff --git a/runtime/docs/compiler/result_type_pragma.md b/runtime/docs/compiler/result_type_pragma.md
deleted file mode 100644
index 2bc5032..0000000
--- a/runtime/docs/compiler/result_type_pragma.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# `vm:exact-result-type` pragma
-
-To facilitate type-flow analysis and other optimizations, Dart methods may use
-the pragma `vm:exact-result-type` to declare an exact return type different than
-the return type in the signature of the method. There are three limitations on
-this pragma:
-
-0. The Dart object returned by the method at runtime must have exactly the type
-specified in the annotation (not a subtype).
-
-1. The exact return type declared in the pragma must be a subtype of the return
-   type declared in the method signature.
-   Note that this restriction is not enforced automatically by the compiler.
-
-2. `vm:exact-result-type` may only be attached to methods in the `dart:*`
-   libraries.
-   This pragma can introduce unsafe behavior since it allows the compiler to
-   make stronger assumptions during optimization than what the sound strong-mode
-   type system allows, so it is only allowed in the core library where the Dart
-   VM team can ensure that it is not misused.
-
-If limitations 0 or 1 are violated, undefined behavior may result.
-Note that since `null` is an instance of the `Null` type, which is a subtype of any other, exactness of the annotated result type implies that the result must be non-null.
-
-## Syntax
-
-### Reference to type via type literal
-
-```dart
-class A {}
-class B extends A {}
-
-@pragma('vm:exact-result-type', B)
-A foo() native 'foo_impl';
-```
-
-### Reference to type via path
-
-```dart
-@pragma('vm:exact-result-type', 'dart:core#_Smi');
-int foo() native 'foo_impl';
-```
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index b55d192..9bfdefa 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1509,6 +1509,19 @@
                                               bool* is_static);
 
 /**
+ * Is this object a closure resulting from a tear-off (closurized method)?
+ *
+ * Returns true for closures produced when an ordinary method is accessed
+ * through a getter call. Returns false otherwise, in particular for closures
+ * produced from local function declarations.
+ *
+ * \param object Some Object.
+ *
+ * \return true if Object is a tear-off.
+ */
+DART_EXPORT bool Dart_IsTearOff(Dart_Handle object);
+
+/**
  * Retrieves the function of a closure.
  *
  * \return A handle to the function of the closure, or an error handle if the
@@ -3070,65 +3083,6 @@
 DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer);
 
 /*
- * ======
- * Kernel
- * ======
- */
-
-/**
- * Experimental support for Dart to Kernel parser isolate.
- *
- * TODO(hausner): Document finalized interface.
- *
- */
-
-// TODO(33433): Remove kernel service from the embedding API.
-
-typedef enum {
-  Dart_KernelCompilationStatus_Unknown = -1,
-  Dart_KernelCompilationStatus_Ok = 0,
-  Dart_KernelCompilationStatus_Error = 1,
-  Dart_KernelCompilationStatus_Crash = 2,
-} Dart_KernelCompilationStatus;
-
-typedef struct {
-  Dart_KernelCompilationStatus status;
-  char* error;
-
-  uint8_t* kernel;
-  intptr_t kernel_size;
-} Dart_KernelCompilationResult;
-
-DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate);
-DART_EXPORT bool Dart_KernelIsolateIsRunning();
-DART_EXPORT Dart_Port Dart_KernelPort();
-DART_EXPORT Dart_KernelCompilationResult
-Dart_CompileToKernel(const char* script_uri,
-                     const uint8_t* platform_kernel,
-                     const intptr_t platform_kernel_size,
-                     bool incremental_compile,
-                     const char* package_config);
-
-typedef struct {
-  const char* uri;
-  const char* source;
-} Dart_SourceFile;
-DART_EXPORT Dart_KernelCompilationResult
-Dart_CompileSourcesToKernel(const char* script_uri,
-                            const uint8_t* platform_kernel,
-                            intptr_t platform_kernel_size,
-                            int source_files_count,
-                            Dart_SourceFile source_files[],
-                            bool incremental_compile,
-                            const char* package_config,
-                            const char* multiroot_filepaths,
-                            const char* multiroot_scheme);
-
-DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies();
-
-#define DART_KERNEL_ISOLATE_NAME "kernel-service"
-
-/*
  * =======
  * Service
  * =======
diff --git a/runtime/lib/class_id.dart b/runtime/lib/class_id.dart
index 2260a75..ff9d0b6 100644
--- a/runtime/lib/class_id.dart
+++ b/runtime/lib/class_id.dart
@@ -4,7 +4,9 @@
 
 // part of "internal_patch.dart";
 
+@pragma("vm:entry-point")
 class ClassID {
+  @pragma("vm:entry-point")
   @pragma("vm:exact-result-type", "dart:core#_Smi")
   static int getID(Object value) native "ClassID_getID";
 
diff --git a/runtime/lib/class_id_fasta.dart b/runtime/lib/class_id_fasta.dart
index 0a89db4..f8579c0 100644
--- a/runtime/lib/class_id_fasta.dart
+++ b/runtime/lib/class_id_fasta.dart
@@ -4,14 +4,24 @@
 
 // part of "internal_patch.dart";
 
+@pragma("vm:entry-point")
 class ClassID {
+  @pragma("vm:entry-point")
   @pragma("vm:exact-result-type", "dart:core#_Smi")
   static int getID(Object value) native "ClassID_getID";
 
+  @pragma("vm:entry-point")
   static final int cidArray = 0;
+  @pragma("vm:entry-point")
   static final int cidExternalOneByteString = 0;
+  @pragma("vm:entry-point")
   static final int cidGrowableObjectArray = 0;
+  @pragma("vm:entry-point")
   static final int cidImmutableArray = 0;
+  @pragma("vm:entry-point")
   static final int cidOneByteString = 0;
+  @pragma("vm:entry-point")
   static final int cidTwoByteString = 0;
+  @pragma("vm:entry-point")
+  static final int cidUint8ArrayView = 0;
 }
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index 0802cbb..3d99c0d 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -7,7 +7,7 @@
 /// used by patches of that library. We plan to change this when we have a
 /// shared front end and simply use parts.
 
-import "dart:_internal" show POWERS_OF_TEN, patch;
+import "dart:_internal" show POWERS_OF_TEN, patch, ClassID;
 
 import "dart:typed_data" show Uint8List, Uint16List;
 
@@ -1816,3 +1816,27 @@
     _sink.close();
   }
 }
+
+@patch
+int _scanOneByteCharacters(List<int> units, int from, int endIndex) {
+  final to = endIndex;
+
+  // Special case for _Uint8ArrayView.
+  final cid = ClassID.getID(units);
+  if (identical(cid, ClassID.cidUint8ArrayView)) {
+    if (from >= 0 && to >= 0 && to <= units.length) {
+      for (int i = from; i < to; i++) {
+        final unit = units[i];
+        if ((unit & _ONE_BYTE_LIMIT) != unit) return i - from;
+      }
+      return to - from;
+    }
+  }
+
+  // Fall through to normal case.
+  for (var i = from; i < to; i++) {
+    final unit = units[i];
+    if ((unit & _ONE_BYTE_LIMIT) != unit) return i - from;
+  }
+  return to - from;
+}
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index f2de9c0..266d433 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -40,6 +40,7 @@
     return _trunc_div(other.toDouble());
   }
 
+  @pragma("vm:non-nullable-result-type")
   int _trunc_div(double other) native "Double_trunc_div";
 
   @pragma("vm:exact-result-type", _Double)
@@ -71,7 +72,9 @@
     return (other is num) && _equal(other.toDouble());
   }
 
+  @pragma("vm:exact-result-type", bool)
   bool _equal(double other) native "Double_equal";
+  @pragma("vm:exact-result-type", bool)
   bool _equalToInteger(int other) native "Double_equalToInteger";
 
   @pragma("vm:exact-result-type", bool)
@@ -84,6 +87,7 @@
     return _greaterThan(other.toDouble());
   }
 
+  @pragma("vm:exact-result-type", bool)
   bool _greaterThan(double other) native "Double_greaterThan";
 
   @pragma("vm:exact-result-type", bool)
@@ -175,6 +179,7 @@
     return this;
   }
 
+  @pragma("vm:non-nullable-result-type")
   int toInt() native "Double_toInt";
 
   double toDouble() {
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index b39ae32..2289012 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -5,10 +5,14 @@
 // part of "core_patch.dart";
 
 abstract class _IntegerImplementation implements int {
+  @pragma("vm:non-nullable-result-type")
   num operator +(num other) => other._addFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
   num operator -(num other) => other._subFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
   num operator *(num other) => other._mulFromInteger(this);
 
+  @pragma("vm:non-nullable-result-type")
   int operator ~/(num other) {
     if ((other is int) && (other == 0)) {
       throw const IntegerDivisionByZeroException();
@@ -20,6 +24,7 @@
     return this.toDouble() / other.toDouble();
   }
 
+  @pragma("vm:non-nullable-result-type")
   num operator %(num other) {
     if ((other is int) && (other == 0)) {
       throw const IntegerDivisionByZeroException();
@@ -27,34 +32,51 @@
     return other._moduloFromInteger(this);
   }
 
+  @pragma("vm:non-nullable-result-type")
   int operator -() {
     return 0 - this;
   }
 
+  @pragma("vm:non-nullable-result-type")
   int operator &(int other) => other._bitAndFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
   int operator |(int other) => other._bitOrFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
   int operator ^(int other) => other._bitXorFromInteger(this);
 
   num remainder(num other) {
     return other._remainderFromInteger(this);
   }
 
+  @pragma("vm:non-nullable-result-type")
   int _bitAndFromSmi(_Smi other) native "Integer_bitAndFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _bitAndFromInteger(int other) native "Integer_bitAndFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _bitOrFromInteger(int other) native "Integer_bitOrFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _bitXorFromInteger(int other) native "Integer_bitXorFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _shrFromInteger(int other) native "Integer_shrFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _shlFromInteger(int other) native "Integer_shlFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _addFromInteger(int other) native "Integer_addFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _subFromInteger(int other) native "Integer_subFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _mulFromInteger(int other) native "Integer_mulFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _truncDivFromInteger(int other) native "Integer_truncDivFromInteger";
+  @pragma("vm:non-nullable-result-type")
   int _moduloFromInteger(int other) native "Integer_moduloFromInteger";
   int _remainderFromInteger(int other) {
     return other - (other ~/ this) * this;
   }
 
+  @pragma("vm:non-nullable-result-type")
   int operator >>(int other) => other._shrFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
   int operator <<(int other) => other._shlFromInteger(this);
 
   @pragma("vm:exact-result-type", bool)
@@ -664,7 +686,9 @@
   }
   int get hashCode => this;
   int get _identityHashCode => this;
+  @pragma("vm:non-nullable-result-type")
   int operator ~() native "Mint_bitNegate";
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
   int get bitLength native "Mint_bitLength";
 
   int _bitAndFromSmi(_Smi other) => _bitAndFromInteger(other);
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
index 2575da5..c84b78b 100644
--- a/runtime/lib/stacktrace.cc
+++ b/runtime/lib/stacktrace.cc
@@ -77,7 +77,7 @@
   intptr_t write_cursor = 0;
   if (for_async_function) {
     // Place the asynchronous gap marker at the top of the stack trace.
-    code = StubCode::AsynchronousGapMarker_entry()->code();
+    code = StubCode::AsynchronousGapMarker().raw();
     ASSERT(!code.IsNull());
     offset = Smi::New(0);
     code_array.SetAt(write_cursor, code);
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 103959b..e90667a 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -222,6 +222,19 @@
   static String _createOneByteString(List<int> charCodes, int start, int len) {
     // It's always faster to do this in Dart than to call into the runtime.
     var s = _OneByteString._allocate(len);
+
+    // Special case for _Uint8ArrayView.
+    final cid = ClassID.getID(charCodes);
+    if (identical(cid, ClassID.cidUint8ArrayView)) {
+      if (start >= 0 && len >= 0) {
+        for (int i = 0; i < len; i++) {
+          s._setAt(i, charCodes[start + i]);
+        }
+        return s;
+      }
+    }
+
+    // Fall through to normal case.
     for (int i = 0; i < len; i++) {
       s._setAt(i, charCodes[start + i]);
     }
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index 0a81886..36e480a 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -147,9 +147,15 @@
 }
 
 // We check the length parameter against a possible maximum length for the
-// array based on available physical addressable memory on the system. The
-// maximum possible length is a scaled value of kSmiMax which is set up based
-// on whether the underlying architecture is 32-bit or 64-bit.
+// array based on available physical addressable memory on the system.
+//
+// More specifically
+//
+//   TypedData::MaxElements(cid) is equal to (kSmiMax / ElementSizeInBytes(cid))
+//
+// which ensures that the number of bytes the array holds is guaranteed to fit
+// into a _Smi.
+//
 // Argument 0 is type arguments and is ignored.
 #define TYPED_DATA_NEW(name)                                                   \
   DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 2) {                             \
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 9c5f7d6..91d7efd 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -39,12 +39,14 @@
   @pragma("vm:entry-point")
   factory ByteData(int length) {
     final list = new Uint8List(length) as _TypedList;
+    _rangeCheck(list.lengthInBytes, 0, length);
     return new _ByteDataView(list, 0, length);
   }
 
   // Called directly from C code.
   @pragma("vm:entry-point")
   factory ByteData._view(_TypedList typedData, int offsetInBytes, int length) {
+    _rangeCheck(typedData.lengthInBytes, offsetInBytes, length);
     return new _ByteDataView(typedData, offsetInBytes, length);
   }
 }
@@ -1904,87 +1906,118 @@
 
   ByteData asByteData([int offsetInBytes = 0, int length]) {
     length ??= this.lengthInBytes - offsetInBytes;
+    _rangeCheck(this._data.lengthInBytes, offsetInBytes, length);
     return new _ByteDataView(this._data, offsetInBytes, length);
   }
 
   Int8List asInt8List([int offsetInBytes = 0, int length]) {
-    length ??= this.lengthInBytes - offsetInBytes;
+    length ??= (this.lengthInBytes - offsetInBytes) ~/ Int8List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int8List.bytesPerElement);
     return new _Int8ArrayView(this, offsetInBytes, length);
   }
 
   Uint8List asUint8List([int offsetInBytes = 0, int length]) {
-    length ??= this.lengthInBytes - offsetInBytes;
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint8List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint8List.bytesPerElement);
     return new _Uint8ArrayView(this, offsetInBytes, length);
   }
 
   Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
-    length ??= this.lengthInBytes - offsetInBytes;
+    length ??= (this.lengthInBytes - offsetInBytes) ~/
+        Uint8ClampedList.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Uint8ClampedList.bytesPerElement);
     return new _Uint8ClampedArrayView(this, offsetInBytes, length);
   }
 
   Int16List asInt16List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int16List.bytesPerElement);
     return new _Int16ArrayView(this, offsetInBytes, length);
   }
 
   Uint16List asUint16List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint16List.bytesPerElement);
     return new _Uint16ArrayView(this, offsetInBytes, length);
   }
 
   Int32List asInt32List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int32List.bytesPerElement);
     return new _Int32ArrayView(this, offsetInBytes, length);
   }
 
   Uint32List asUint32List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint32List.bytesPerElement);
     return new _Uint32ArrayView(this, offsetInBytes, length);
   }
 
   Int64List asInt64List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int64List.bytesPerElement);
     return new _Int64ArrayView(this, offsetInBytes, length);
   }
 
   Uint64List asUint64List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint64List.bytesPerElement);
     return new _Uint64ArrayView(this, offsetInBytes, length);
   }
 
   Float32List asFloat32List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float32List.bytesPerElement);
     return new _Float32ArrayView(this, offsetInBytes, length);
   }
 
   Float64List asFloat64List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float64List.bytesPerElement);
     return new _Float64ArrayView(this, offsetInBytes, length);
   }
 
   Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float32x4List.bytesPerElement);
     return new _Float32x4ArrayView(this, offsetInBytes, length);
   }
 
   Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Int32x4List.bytesPerElement);
     return new _Int32x4ArrayView(this, offsetInBytes, length);
   }
 
   Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float64x2List.bytesPerElement);
     return new _Float64x2ArrayView(this, offsetInBytes, length);
   }
 }
@@ -3544,8 +3577,13 @@
     return _typedData.buffer;
   }
 
+  @pragma("vm:non-nullable-result-type")
   final _TypedList _typedData;
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
   final int offsetInBytes;
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
   final int length;
 }
 
@@ -3554,17 +3592,8 @@
     with _IntListMixin
     implements Int8List {
   // Constructor.
-  _Int8ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Int8List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, _offsetInBytes,
-        length * Int8List.bytesPerElement);
-  }
+  _Int8ArrayView(_ByteBuffer buffer, int offsetInBytes, int length)
+      : super(buffer, offsetInBytes, length);
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3599,17 +3628,8 @@
     with _IntListMixin
     implements Uint8List {
   // Constructor.
-  _Uint8ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Uint8List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, _offsetInBytes,
-        length * Uint8List.bytesPerElement);
-  }
+  _Uint8ArrayView(_ByteBuffer buffer, int offsetInBytes, int length)
+      : super(buffer, offsetInBytes, length);
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3644,18 +3664,8 @@
     with _IntListMixin
     implements Uint8ClampedList {
   // Constructor.
-  _Uint8ClampedArrayView(_ByteBuffer buffer,
-      [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Uint8List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Uint8List.bytesPerElement);
-  }
+  _Uint8ClampedArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length);
 
   // Method(s) implementing List interface.
   int operator [](int index) {
@@ -3690,16 +3700,8 @@
     with _IntListMixin
     implements Int16List {
   // Constructor.
-  _Int16ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Int16List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Int16List.bytesPerElement);
+  _Int16ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Int16List.bytesPerElement);
   }
 
@@ -3748,16 +3750,8 @@
     with _IntListMixin
     implements Uint16List {
   // Constructor.
-  _Uint16ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Uint16List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Uint16List.bytesPerElement);
+  _Uint16ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Uint16List.bytesPerElement);
   }
 
@@ -3807,16 +3801,8 @@
     with _IntListMixin
     implements Int32List {
   // Constructor.
-  _Int32ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Int32List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Int32List.bytesPerElement);
+  _Int32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Int32List.bytesPerElement);
   }
 
@@ -3853,16 +3839,8 @@
     with _IntListMixin
     implements Uint32List {
   // Constructor.
-  _Uint32ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Uint32List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Uint32List.bytesPerElement);
+  _Uint32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Uint32List.bytesPerElement);
   }
 
@@ -3899,16 +3877,8 @@
     with _IntListMixin
     implements Int64List {
   // Constructor.
-  _Int64ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Int64List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Int64List.bytesPerElement);
+  _Int64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Int64List.bytesPerElement);
   }
 
@@ -3945,16 +3915,8 @@
     with _IntListMixin
     implements Uint64List {
   // Constructor.
-  _Uint64ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Uint64List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Uint64List.bytesPerElement);
+  _Uint64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Uint64List.bytesPerElement);
   }
 
@@ -3991,16 +3953,8 @@
     with _DoubleListMixin
     implements Float32List {
   // Constructor.
-  _Float32ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Float32List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Float32List.bytesPerElement);
+  _Float32ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Float32List.bytesPerElement);
   }
 
@@ -4037,16 +3991,8 @@
     with _DoubleListMixin
     implements Float64List {
   // Constructor.
-  _Float64ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Float64List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Float64List.bytesPerElement);
+  _Float64ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Float64List.bytesPerElement);
   }
 
@@ -4083,16 +4029,8 @@
     with _Float32x4ListMixin
     implements Float32x4List {
   // Constructor.
-  _Float32x4ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Float32x4List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Float32x4List.bytesPerElement);
+  _Float32x4ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Float32x4List.bytesPerElement);
   }
 
@@ -4129,16 +4067,8 @@
     with _Int32x4ListMixin
     implements Int32x4List {
   // Constructor.
-  _Int32x4ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Int32x4List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Int32x4List.bytesPerElement);
+  _Int32x4ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Int32x4List.bytesPerElement);
   }
 
@@ -4175,16 +4105,8 @@
     with _Float64x2ListMixin
     implements Float64x2List {
   // Constructor.
-  _Float64x2ArrayView(_ByteBuffer buffer, [int _offsetInBytes = 0, int _length])
-      : super(
-            buffer,
-            _offsetInBytes,
-            _defaultIfNull(
-                _length,
-                ((buffer.lengthInBytes - _offsetInBytes) ~/
-                    Float64x2List.bytesPerElement))) {
-    _rangeCheck(buffer.lengthInBytes, offsetInBytes,
-        length * Float64x2List.bytesPerElement);
+  _Float64x2ArrayView(_ByteBuffer buffer, int _offsetInBytes, int _length)
+      : super(buffer, _offsetInBytes, _length) {
     _offsetAlignmentCheck(_offsetInBytes, Float64x2List.bytesPerElement);
   }
 
@@ -4218,12 +4140,7 @@
 
 @pragma("vm:entry-point")
 class _ByteDataView implements ByteData {
-  _ByteDataView(_TypedList typedData, int _offsetInBytes, int _lengthInBytes)
-      : _typedData = typedData,
-        _offset = _offsetInBytes,
-        length = _lengthInBytes {
-    _rangeCheck(_typedData.lengthInBytes, _offset, length);
-  }
+  _ByteDataView(this._typedData, this._offset, this.length);
 
   // Method(s) implementing TypedData interface.
   _ByteBuffer get buffer {
@@ -4511,6 +4428,9 @@
   return value & 0xFFFFFFFF;
 }
 
+// In addition to explicitly checking the range, this method implicitly ensures
+// that all arguments are non-null (a no such method error gets thrown
+// otherwise).
 void _rangeCheck(int listLength, int start, int length) {
   if (length < 0) {
     throw new RangeError.value(length);
@@ -4529,10 +4449,3 @@
         'BYTES_PER_ELEMENT ($alignment)');
   }
 }
-
-int _defaultIfNull(object, value) {
-  if (object == null) {
-    return value;
-  }
-  return object;
-}
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index c288d6a..aa87514 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -79,6 +79,7 @@
 #endif  // !PRODUCT
 
 DEFINE_NATIVE_ENTRY(VMService_SendIsolateServiceMessage, 2) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return Bool::Get(false).raw();
   }
@@ -95,25 +96,33 @@
   bool result = PortMap::PostMessage(
       writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
   return Bool::Get(result).raw();
+#else
+  return Object::null();
+#endif
 }
 
 DEFINE_NATIVE_ENTRY(VMService_SendRootServiceMessage, 1) {
+#ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0));
   if (FLAG_support_service) {
     return Service::HandleRootMessage(message);
   }
+#endif
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(VMService_SendObjectRootServiceMessage, 1) {
+#ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0));
   if (FLAG_support_service) {
     return Service::HandleObjectRootMessage(message);
   }
+#endif
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(VMService_OnStart, 0) {
+#ifndef PRODUCT
   if (FLAG_trace_service) {
     OS::PrintErr("vm-service: Booting dart:vmservice library.\n");
   }
@@ -122,7 +131,6 @@
   if (!FLAG_support_service) {
     return Object::null();
   }
-#ifndef PRODUCT
   // Register running isolates with service.
   RegisterRunningIsolatesVisitor register_isolates(thread);
   if (FLAG_trace_service) {
@@ -134,16 +142,19 @@
 }
 
 DEFINE_NATIVE_ENTRY(VMService_OnExit, 0) {
+#ifndef PRODUCT
   if (FLAG_trace_service) {
     OS::PrintErr("vm-service: processed exit message.\n");
     MessageHandler* message_handler = isolate->message_handler();
     OS::PrintErr("vm-service: live ports = %" Pd "\n",
                  message_handler->live_ports());
   }
+#endif
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(VMService_OnServerAddressChange, 1) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return Object::null();
   }
@@ -153,31 +164,42 @@
   } else {
     ServiceIsolate::SetServerAddress(address.ToCString());
   }
+#endif
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(VMService_ListenStream, 1) {
+#ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
   bool result = false;
   if (FLAG_support_service) {
     result = Service::ListenStream(stream_id.ToCString());
   }
   return Bool::Get(result).raw();
+#else
+  return Object::null();
+#endif
 }
 
 DEFINE_NATIVE_ENTRY(VMService_CancelStream, 1) {
+#ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
   if (FLAG_support_service) {
     Service::CancelStream(stream_id.ToCString());
   }
+#endif
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(VMService_RequestAssets, 0) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return Object::null();
   }
   return Service::RequestAssets();
+#else
+  return Object::null();
+#endif
 }
 
 #ifndef PRODUCT
diff --git a/runtime/observatory/tests/service/dominator_tree_user_test.dart b/runtime/observatory/tests/service/dominator_tree_user_test.dart
index a0e9fd4..d2053d2 100644
--- a/runtime/observatory/tests/service/dominator_tree_user_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_user_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=
 // VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
 
 import 'package:observatory/heap_snapshot.dart';
 import 'package:observatory/models.dart' as M;
diff --git a/runtime/observatory/tests/service/dominator_tree_vm_test.dart b/runtime/observatory/tests/service/dominator_tree_vm_test.dart
index 7fa6e9b..6199bf5 100644
--- a/runtime/observatory/tests/service/dominator_tree_vm_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_vm_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=
 // VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
 
 import 'package:observatory/heap_snapshot.dart';
 import 'package:observatory/models.dart' as M;
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 57670e29..c6010cb 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -43,7 +43,6 @@
 set_name_rpc_test: RuntimeError
 set_vm_name_rpc_test: RuntimeError
 simple_reload_test: RuntimeError
-step_through_arithmetic_test: RuntimeError
 unused_changes_in_last_reload_test: RuntimeError
 valid_source_locations_test: RuntimeError
 
@@ -61,7 +60,6 @@
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
 pause_on_unhandled_async_exceptions2_test: Pass, Slow
 positive_token_pos_test: RuntimeError # Issue 34746
-step_through_arithmetic_test: RuntimeError # probably constant evaluator pre-evaluating e.g. 1+2
 unused_changes_in_last_reload_test: RuntimeError
 
 [ $compiler == dartkp ]
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 11c9d32..0dfd620 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -238,6 +238,23 @@
 #error Automatic compiler detection failed.
 #endif
 
+#ifdef _MSC_VER
+#elif __GNUC__
+#define DART_HAS_COMPUTED_GOTO 1
+#else
+#error Automatic compiler detection failed.
+#endif
+
+// LIKELY/UNLIKELY give the compiler branch preditions that may affect block
+// scheduling.
+#ifdef __GNUC__
+#define LIKELY(cond) __builtin_expect((cond), 1)
+#define UNLIKELY(cond) __builtin_expect((cond), 0)
+#else
+#define LIKELY(cond) cond
+#define UNLIKELY(cond) cond
+#endif
+
 // DART_UNUSED indicates to the compiler that a variable or typedef is expected
 // to be unused and disables the related warning.
 #ifdef __GNUC__
diff --git a/runtime/tests/vm/dart/entrypoints/static_this_test.dart b/runtime/tests/vm/dart/entrypoints/static_this_test.dart
index fc9253e..8b962ed 100644
--- a/runtime/tests/vm/dart/entrypoints/static_this_test.dart
+++ b/runtime/tests/vm/dart/entrypoints/static_this_test.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=5
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=5 -Denable_inlining=true
 
 // Test that 'StaticCall's against "this" go through the unchecked entry-point.
 
diff --git a/runtime/tests/vm/dart/entrypoints/super_test.dart b/runtime/tests/vm/dart/entrypoints/super_test.dart
index 2a17e61..e923180 100644
--- a/runtime/tests/vm/dart/entrypoints/super_test.dart
+++ b/runtime/tests/vm/dart/entrypoints/super_test.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=5 -Denable_inlining=true
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=5
 
 // Test that 'StaticCall's against "super" go through the unchecked entrypoint.
 
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 9b4394a..5c27ced 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -83,7 +83,10 @@
 
     final generate1Result = await runDartBinary('GENERATE SNAPSHOT 1', [
       '--deterministic',
-      '--dump_tables',
+      '--trace_class_finalization',
+      '--trace_type_finalization',
+      '--trace_compiler',
+      '--verbose_gc',
       '--snapshot=$snapshot1Path',
       '--snapshot-kind=$snapshotKind',
       Platform.script.toFilePath(),
@@ -93,7 +96,10 @@
 
     final generate2Result = await runDartBinary('GENERATE SNAPSHOT 2', [
       '--deterministic',
-      '--dump_tables',
+      '--trace_class_finalization',
+      '--trace_type_finalization',
+      '--trace_compiler',
+      '--verbose_gc',
       '--snapshot=$snapshot2Path',
       '--snapshot-kind=$snapshotKind',
       Platform.script.toFilePath(),
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
new file mode 100644
index 0000000..ede572c
--- /dev/null
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -0,0 +1,105 @@
+// 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:convert";
+import "dart:io";
+
+import "package:expect/expect.dart";
+import "package:vm/v8_snapshot_profile.dart";
+
+String path(List<String> segments) {
+  return "/" + segments.join("/");
+}
+
+test(bool use_elf) async {
+  if (Platform.isWindows) return;
+  if (Platform.isMacOS && use_elf) return;
+
+  final String outputDir = Platform.isMacOS ? "xcodebuild" : "out";
+
+  final List<String> sdkBaseSegments =
+      Uri.file(Platform.resolvedExecutable).pathSegments.toList();
+  sdkBaseSegments.replaceRange(
+      sdkBaseSegments.indexOf(outputDir), sdkBaseSegments.length, []);
+
+  // Generate the snapshot profile.
+  final String thisTestPath = path(sdkBaseSegments) +
+      "/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart";
+
+  final Directory temp = await Directory.systemTemp.createTemp();
+  final String snapshotPath = temp.path + "/test.snap";
+
+  final List<String> precompiler2Args = [
+    "--write-v8-snapshot-profile-to=${temp.path}/profile.heapsnapshot",
+    thisTestPath,
+    snapshotPath,
+  ];
+
+  if (use_elf) {
+    precompiler2Args.insert(0, "--build-elf");
+  }
+
+  final ProcessResult result = await Process.run(
+    "pkg/vm/tool/precompiler2",
+    precompiler2Args,
+    workingDirectory: path(sdkBaseSegments),
+    runInShell: true,
+  );
+
+  // The precompiler2 script tried using GCC for the wrong architecture. We
+  // don't have a workaround for this now.
+  if (use_elf &&
+      result.exitCode != 0 &&
+      result.stderr.contains("Assembler messages")) {
+    return;
+  }
+
+  print(precompiler2Args);
+  print(result.stderr);
+  print(result.stdout);
+
+  Expect.equals(result.exitCode, 0);
+  Expect.equals(result.stderr, "");
+  Expect.equals(result.stdout, "");
+
+  final V8SnapshotProfile profile = V8SnapshotProfile.fromJson(JsonDecoder()
+      .convert(File("${temp.path}/profile.heapsnapshot").readAsStringSync()));
+
+  // Verify that there are no "unknown" nodes. These are emitted when we see a
+  // reference to an some object but no other metadata about the object was
+  // recorded. We should at least record the type for every object in the graph
+  // (in some cases the shallow size can legitimately be 0, e.g. for "base
+  // objects").
+  for (final int node in profile.nodes) {
+    if (profile[node].type == "Unknown") {
+      print(profile[node].id);
+    }
+    Expect.notEquals(profile[node].type, "Unknown");
+  }
+
+  // Verify that all nodes are reachable from the declared roots.
+  int unreachableNodes = 0;
+  Set<int> nodesReachableFromRoots = profile.preOrder(profile.root).toSet();
+  for (final int node in profile.nodes) {
+    if (!nodesReachableFromRoots.contains(node)) {
+      ++unreachableNodes;
+    }
+  }
+  Expect.equals(unreachableNodes, 0);
+
+  // Verify that the actual size of the snapshot is close to the sum of the
+  // shallow sizes of all objects in the profile. They will not be exactly equal
+  // because of global headers and padding.
+  if (use_elf) {
+    await Process.run("strip", [snapshotPath]);
+  }
+  final int actual = await File(snapshotPath).length();
+  final int expected = profile.accountedBytes;
+  Expect.isTrue((actual - expected).abs() / actual < 0.01);
+}
+
+main() async {
+  test(false);
+  test(true);
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c955046..804a35a 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -10,8 +10,8 @@
 cc/Fail0: Fail # These tests are expected to crash on all platforms.
 cc/Fail1: Fail # These tests are expected to crash on all platforms.
 cc/Fail2: Fail # These tests are expected to crash on all platforms.
-cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: Fail, Crash # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
-cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: Fail, Crash # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
+cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: Fail, Crash # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline).
+cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: Fail, Crash # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline).
 cc/IsolateReload_PendingStaticCall_DefinedToNSM: Fail # Issue 32981
 cc/IsolateReload_PendingStaticCall_NSMToDefined: Fail, Crash # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
 cc/IsolateReload_PendingUnqualifiedCall_InstanceToStatic: Fail # Issue 32981
@@ -23,6 +23,18 @@
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 
+[ $system == macos ]
+# Tests failing or crashing are sometimes reported as timeout on MacOS. See issues 35268 and 35275.
+cc/ArrayNew_Overflow_Crash: Crash, Fail, Timeout # These tests are expected to crash on all platforms
+cc/CodeImmutability: Crash, Fail, Timeout # These tests are expected to crash on all platforms
+cc/IsolateReload_PendingStaticCall_NSMToDefined: Fail, Crash, Timeout # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
+cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: Fail, Crash, Timeout # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
+cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: Fail, Crash, Timeout # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
+cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: Fail, Crash, Timeout # Issue 32981. Fails on non-Windows, crashes on Windows (because of test.py special handline)
+
+[ $system == macos && ($compiler == dartk || $compiler == dartkb) && $runtime == vm ]
+cc/Class_ComputeEndTokenPos: Crash, Timeout # May also time out on MacOS (issues 35268 and 35275).
+
 [ $mode == debug ]
 dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 
@@ -314,3 +326,9 @@
 [ $builder_tag == obfuscated && $compiler == dartkp ]
 dart/optimized_stacktrace_line_and_column_test: SkipByDesign # Looks for filenames in stacktrace output
 dart/optimized_stacktrace_line_test: SkipByDesign # Looks for filenames in stacktrace output
+
+[ $compiler != dartkp || $arch == arm || $arch == arm64 ]
+dart/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host).
+
+[ $compiler == dartkp ]
+dart/v8_snapshot_profile_writer_test: Pass, Slow # Can be slow due to re-invoking the precompiler.
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index daa7248..acbd08a 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -105,11 +105,7 @@
       objects_.Add(cls);
     }
 
-    RawObject** from = cls->from();
-    RawObject** to = cls->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(cls);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -118,9 +114,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClass* cls = predefined_[i];
+      s->AssignRef(cls);
+      AutoTraceObject(cls);
       intptr_t class_id = cls->ptr()->id_;
       s->WriteCid(class_id);
-      s->AssignRef(cls);
     }
     count = objects_.length();
     s->WriteUnsigned(count);
@@ -142,18 +139,14 @@
   }
 
   void WriteClass(Serializer* s, RawClass* cls) {
-    Snapshot::Kind kind = s->kind();
-    RawObject** from = cls->from();
-    RawObject** to = cls->to_snapshot(kind);
-    for (RawObject** p = from; p <= to; p++) {
-      s->WriteRef(*p);
-    }
+    AutoTraceObjectName(cls, cls->ptr()->name_);
+    WriteFromTo(cls);
     intptr_t class_id = cls->ptr()->id_;
     if (class_id == kIllegalCid) {
       s->UnexpectedObject(cls, "Class with illegal cid");
     }
     s->WriteCid(class_id);
-    if (kind != Snapshot::kFullAOT) {
+    if (s->kind() != Snapshot::kFullAOT) {
       s->Write<int32_t>(cls->ptr()->kernel_offset_);
     }
     s->Write<int32_t>(cls->ptr()->instance_size_in_words_);
@@ -200,22 +193,17 @@
   }
 
   void ReadFill(Deserializer* d) {
-    Snapshot::Kind kind = d->kind();
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
     ClassTable* table = d->isolate()->class_table();
 
     for (intptr_t id = predefined_start_index_; id < predefined_stop_index_;
          id++) {
       RawClass* cls = reinterpret_cast<RawClass*>(d->Ref(id));
-      RawObject** from = cls->from();
-      RawObject** to_snapshot = cls->to_snapshot(kind);
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(cls);
       intptr_t class_id = d->ReadCid();
       cls->ptr()->id_ = class_id;
 #if !defined(DART_PRECOMPILED_RUNTIME)
-      if (kind != Snapshot::kFullAOT) {
+      if (d->kind() != Snapshot::kFullAOT) {
         cls->ptr()->kernel_offset_ = d->Read<int32_t>();
       }
 #endif
@@ -238,15 +226,7 @@
       RawClass* cls = reinterpret_cast<RawClass*>(d->Ref(id));
       Deserializer::InitializeHeader(cls, kClassCid, Class::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = cls->from();
-      RawObject** to_snapshot = cls->to_snapshot(kind);
-      RawObject** to = cls->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
+      ReadFromTo(cls);
 
       intptr_t class_id = d->ReadCid();
 
@@ -256,7 +236,7 @@
 
       cls->ptr()->id_ = class_id;
 #if !defined(DART_PRECOMPILED_RUNTIME)
-      if (kind != Snapshot::kFullAOT) {
+      if (d->kind() != Snapshot::kFullAOT) {
         cls->ptr()->kernel_offset_ = d->Read<int32_t>();
       }
 #endif
@@ -302,9 +282,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeArguments* type_args = objects_[i];
+      s->AssignRef(type_args);
+      AutoTraceObject(type_args);
       intptr_t length = Smi::Value(type_args->ptr()->length_);
       s->WriteUnsigned(length);
-      s->AssignRef(type_args);
     }
   }
 
@@ -312,6 +293,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeArguments* type_args = objects_[i];
+      AutoTraceObject(type_args);
       intptr_t length = Smi::Value(type_args->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(type_args->IsCanonical());
@@ -378,12 +360,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawPatchClass* cls = PatchClass::RawCast(object);
     objects_.Add(cls);
-
-    RawObject** from = cls->from();
-    RawObject** to = cls->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(cls);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -400,12 +377,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawPatchClass* cls = objects_[i];
-      RawObject** from = cls->from();
-      RawObject** to = cls->to_snapshot(s->kind());
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
-
+      AutoTraceObject(cls);
+      WriteFromTo(cls);
       if (s->kind() != Snapshot::kFullAOT) {
         s->Write<int32_t>(cls->ptr()->library_kernel_offset_);
       }
@@ -440,15 +413,7 @@
       RawPatchClass* cls = reinterpret_cast<RawPatchClass*>(d->Ref(id));
       Deserializer::InitializeHeader(cls, kPatchClassCid,
                                      PatchClass::InstanceSize(), is_vm_object);
-      RawObject** from = cls->from();
-      RawObject** to_snapshot = cls->to_snapshot(d->kind());
-      RawObject** to = cls->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
+      ReadFromTo(cls);
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (d->kind() != Snapshot::kFullAOT) {
         cls->ptr()->library_kernel_offset_ = d->Read<int32_t>();
@@ -469,11 +434,7 @@
     RawFunction* func = Function::RawCast(object);
     objects_.Add(func);
 
-    RawObject** from = func->from();
-    RawObject** to = func->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(func);
     if (kind == Snapshot::kFull) {
       NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_));
     } else if (kind == Snapshot::kFullAOT) {
@@ -501,20 +462,17 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawFunction* func = objects_[i];
-      RawObject** from = func->from();
-      RawObject** to = func->to_snapshot(s->kind());
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObjectName(func, func->ptr()->name_);
+      WriteFromTo(func);
       if (kind == Snapshot::kFull) {
-        NOT_IN_PRECOMPILED(s->WriteRef(func->ptr()->bytecode_));
+        NOT_IN_PRECOMPILED(WriteField(func, bytecode_));
       } else if (kind == Snapshot::kFullAOT) {
-        s->WriteRef(func->ptr()->code_);
+        WriteField(func, code_);
       } else if (s->kind() == Snapshot::kFullJIT) {
-        NOT_IN_PRECOMPILED(s->WriteRef(func->ptr()->unoptimized_code_));
-        NOT_IN_PRECOMPILED(s->WriteRef(func->ptr()->bytecode_));
-        s->WriteRef(func->ptr()->code_);
-        s->WriteRef(func->ptr()->ic_data_array_);
+        NOT_IN_PRECOMPILED(WriteField(func, unoptimized_code_));
+        NOT_IN_PRECOMPILED(WriteField(func, bytecode_));
+        WriteField(func, code_);
+        WriteField(func, ic_data_array_);
       }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -557,15 +515,7 @@
       RawFunction* func = reinterpret_cast<RawFunction*>(d->Ref(id));
       Deserializer::InitializeHeader(func, kFunctionCid,
                                      Function::InstanceSize(), is_vm_object);
-      RawObject** from = func->from();
-      RawObject** to_snapshot = func->to_snapshot(d->kind());
-      RawObject** to = func->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
+      ReadFromTo(func);
 
       if (kind == Snapshot::kFull) {
         NOT_IN_PRECOMPILED(func->ptr()->bytecode_ =
@@ -639,11 +589,9 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
         } else if (FLAG_enable_interpreter && func.HasBytecode()) {
           // Set the code entry_point to InterpretCall stub.
-          func.SetInstructions(
-              Code::Handle(StubCode::InterpretCall_entry()->code()));
+          func.SetInstructions(StubCode::InterpretCall());
         } else if (FLAG_use_bytecode_compiler && func.HasBytecode()) {
-          func.SetInstructions(
-              Code::Handle(StubCode::LazyCompile_entry()->code()));
+          func.SetInstructions(StubCode::LazyCompile());
 #endif                                 // !defined(DART_PRECOMPILED_RUNTIME)
         } else {
           func.ClearCode();  // Set code and entrypoint to lazy compile stub.
@@ -691,6 +639,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawClosureData* data = objects_[i];
+      AutoTraceObject(data);
       if (s->kind() != Snapshot::kFullAOT) {
         s->WriteRef(data->ptr()->context_scope_);
       }
@@ -750,12 +699,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawSignatureData* data = SignatureData::RawCast(object);
     objects_.Add(data);
-
-    RawObject** from = data->from();
-    RawObject** to = data->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(data);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -772,11 +716,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawSignatureData* data = objects_[i];
-      RawObject** from = data->from();
-      RawObject** to = data->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(data);
+      WriteFromTo(data);
     }
   }
 
@@ -808,11 +749,7 @@
       RawSignatureData* data = reinterpret_cast<RawSignatureData*>(d->Ref(id));
       Deserializer::InitializeHeader(
           data, kSignatureDataCid, SignatureData::InstanceSize(), is_vm_object);
-      RawObject** from = data->from();
-      RawObject** to = data->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(data);
     }
   }
 };
@@ -827,12 +764,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawRedirectionData* data = RedirectionData::RawCast(object);
     objects_.Add(data);
-
-    RawObject** from = data->from();
-    RawObject** to = data->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(data);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -849,11 +781,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawRedirectionData* data = objects_[i];
-      RawObject** from = data->from();
-      RawObject** to = data->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(data);
+      WriteFromTo(data);
     }
   }
 
@@ -887,11 +816,7 @@
       Deserializer::InitializeHeader(data, kRedirectionDataCid,
                                      RedirectionData::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = data->from();
-      RawObject** to = data->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(data);
     }
   }
 };
@@ -957,6 +882,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawField* field = objects_[i];
+      AutoTraceObject(field);
 
       s->WriteRef(field->ptr()->name_);
       s->WriteRef(field->ptr()->owner_);
@@ -1033,16 +959,7 @@
       RawField* field = reinterpret_cast<RawField*>(d->Ref(id));
       Deserializer::InitializeHeader(field, kFieldCid, Field::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = field->from();
-      RawObject** to_snapshot = field->to_snapshot(kind);
-      RawObject** to = field->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
-
+      ReadFromTo(field);
       if (kind != Snapshot::kFullAOT) {
         field->ptr()->token_pos_ = d->ReadTokenPosition();
         field->ptr()->end_token_pos_ = d->ReadTokenPosition();
@@ -1091,12 +1008,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawScript* script = Script::RawCast(object);
     objects_.Add(script);
-
-    RawObject** from = script->from();
-    RawObject** to = script->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(script);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1110,16 +1022,11 @@
   }
 
   void WriteFill(Serializer* s) {
-    Snapshot::Kind kind = s->kind();
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawScript* script = objects_[i];
-      RawObject** from = script->from();
-      RawObject** to = script->to_snapshot(kind);
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
-
+      AutoTraceObject(script);
+      WriteFromTo(script);
       s->Write<int32_t>(script->ptr()->line_offset_);
       s->Write<int32_t>(script->ptr()->col_offset_);
       s->Write<int8_t>(script->ptr()->kind_);
@@ -1148,23 +1055,13 @@
   }
 
   void ReadFill(Deserializer* d) {
-    Snapshot::Kind kind = d->kind();
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawScript* script = reinterpret_cast<RawScript*>(d->Ref(id));
       Deserializer::InitializeHeader(script, kScriptCid, Script::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = script->from();
-      RawObject** to_snapshot = script->to_snapshot(kind);
-      RawObject** to = script->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
-
+      ReadFromTo(script);
       script->ptr()->line_offset_ = d->Read<int32_t>();
       script->ptr()->col_offset_ = d->Read<int32_t>();
       script->ptr()->kind_ = d->Read<int8_t>();
@@ -1183,12 +1080,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawLibrary* lib = Library::RawCast(object);
     objects_.Add(lib);
-
-    RawObject** from = lib->from();
-    RawObject** to = lib->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(lib);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1205,12 +1097,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLibrary* lib = objects_[i];
-      RawObject** from = lib->from();
-      RawObject** to = lib->to_snapshot(s->kind());
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
-
+      AutoTraceObjectName(lib, lib->ptr()->url_);
+      WriteFromTo(lib);
       s->Write<int32_t>(lib->ptr()->index_);
       s->Write<uint16_t>(lib->ptr()->num_imports_);
       s->Write<int8_t>(lib->ptr()->load_state_);
@@ -1250,16 +1138,7 @@
       RawLibrary* lib = reinterpret_cast<RawLibrary*>(d->Ref(id));
       Deserializer::InitializeHeader(lib, kLibraryCid, Library::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = lib->from();
-      RawObject** to_snapshot = lib->to_snapshot(d->kind());
-      RawObject** to = lib->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
-
+      ReadFromTo(lib);
       lib->ptr()->native_entry_resolver_ = NULL;
       lib->ptr()->native_entry_symbol_resolver_ = NULL;
       lib->ptr()->index_ = d->Read<int32_t>();
@@ -1287,12 +1166,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawNamespace* ns = Namespace::RawCast(object);
     objects_.Add(ns);
-
-    RawObject** from = ns->from();
-    RawObject** to = ns->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(ns);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1309,11 +1183,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawNamespace* ns = objects_[i];
-      RawObject** from = ns->from();
-      RawObject** to = ns->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(ns);
+      WriteFromTo(ns);
     }
   }
 
@@ -1344,11 +1215,7 @@
       RawNamespace* ns = reinterpret_cast<RawNamespace*>(d->Ref(id));
       Deserializer::InitializeHeader(ns, kNamespaceCid,
                                      Namespace::InstanceSize(), is_vm_object);
-      RawObject** from = ns->from();
-      RawObject** to = ns->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(ns);
     }
   }
 };
@@ -1364,12 +1231,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawKernelProgramInfo* info = KernelProgramInfo::RawCast(object);
     objects_.Add(info);
-
-    RawObject** from = info->from();
-    RawObject** to = info->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(info);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1386,11 +1248,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawKernelProgramInfo* info = objects_[i];
-      RawObject** from = info->from();
-      RawObject** to = info->to_snapshot(s->kind());
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(info);
+      WriteFromTo(info);
     }
   }
 
@@ -1425,15 +1284,7 @@
       Deserializer::InitializeHeader(info, kKernelProgramInfoCid,
                                      KernelProgramInfo::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = info->from();
-      RawObject** to = info->to_snapshot(d->kind());
-      RawObject** end = info->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to + 1; p <= end; p++) {
-        *p = Object::null();
-      }
+      ReadFromTo(info);
     }
   }
 
@@ -1496,6 +1347,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawCode* code = objects_[i];
+      AutoTraceObject(code);
 
       intptr_t pointer_offsets_length =
           Code::PtrOffBits::decode(code->ptr()->state_bits_);
@@ -1647,12 +1499,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawBytecode* bytecode = Bytecode::RawCast(object);
     objects_.Add(bytecode);
-
-    RawObject** from = bytecode->from();
-    RawObject** to = bytecode->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(bytecode);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1670,11 +1517,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawBytecode* bytecode = objects_[i];
-      RawObject** from = bytecode->from();
-      RawObject** to = bytecode->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      WriteFromTo(bytecode);
       s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
     }
   }
@@ -1706,11 +1549,7 @@
       RawBytecode* bytecode = reinterpret_cast<RawBytecode*>(d->Ref(id));
       Deserializer::InitializeHeader(bytecode, kBytecodeCid,
                                      Bytecode::InstanceSize(), is_vm_object);
-      RawObject** from = bytecode->from();
-      RawObject** to = bytecode->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(bytecode);
       bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
     }
   }
@@ -1742,9 +1581,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawObjectPool* pool = objects_[i];
+      s->AssignRef(pool);
+      AutoTraceObject(pool);
       intptr_t length = pool->ptr()->length_;
       s->WriteUnsigned(length);
-      s->AssignRef(pool);
     }
   }
 
@@ -1752,6 +1592,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawObjectPool* pool = objects_[i];
+      AutoTraceObject(pool);
       intptr_t length = pool->ptr()->length_;
       s->WriteUnsigned(length);
       uint8_t* entry_bits = pool->ptr()->entry_bits();
@@ -1761,14 +1602,12 @@
         switch (ObjectPool::TypeBits::decode(entry_bits[j])) {
           case ObjectPool::kTaggedObject: {
 #if !defined(TARGET_ARCH_DBC)
-            if ((entry.raw_obj_ ==
-                 StubCode::CallNoScopeNative_entry()->code()) ||
-                (entry.raw_obj_ ==
-                 StubCode::CallAutoScopeNative_entry()->code())) {
+            if ((entry.raw_obj_ == StubCode::CallNoScopeNative().raw()) ||
+                (entry.raw_obj_ == StubCode::CallAutoScopeNative().raw())) {
               // Natives can run while precompiling, becoming linked and
               // switching their stub. Reset to the initial stub used for
               // lazy-linking.
-              s->WriteRef(StubCode::CallBootstrapNative_entry()->code());
+              s->WriteRef(StubCode::CallBootstrapNative().raw());
               break;
             }
 #endif
@@ -1904,12 +1743,13 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawObject* object = shared_objects_[i];
+      s->AssignRef(object);
+      AutoTraceObject(object);
       uint32_t offset;
       if (!s->GetSharedDataOffset(object, &offset)) {
         UNREACHABLE();
       }
       s->WriteUnsigned(offset);
-      s->AssignRef(object);
     }
 
     count = objects_.length();
@@ -1917,12 +1757,14 @@
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
       RawObject* object = objects_[i];
+      s->AssignRef(object);
+      AutoTraceObject(object);
       uint32_t offset = s->GetDataOffset(object);
+      s->TraceDataOffset(offset);
       ASSERT(Utils::IsAligned(offset, kObjectAlignment));
       ASSERT(offset > running_offset);
       s->WriteUnsigned((offset - running_offset) >> kObjectAlignmentLog2);
       running_offset = offset;
-      s->AssignRef(object);
     }
   }
 
@@ -1982,9 +1824,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawExceptionHandlers* handlers = objects_[i];
+      s->AssignRef(handlers);
+      AutoTraceObject(handlers);
       intptr_t length = handlers->ptr()->num_entries_;
       s->WriteUnsigned(length);
-      s->AssignRef(handlers);
     }
   }
 
@@ -1992,6 +1835,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawExceptionHandlers* handlers = objects_[i];
+      AutoTraceObject(handlers);
       intptr_t length = handlers->ptr()->num_entries_;
       s->WriteUnsigned(length);
       s->WriteRef(handlers->ptr()->handled_types_data_);
@@ -2076,9 +1920,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawContext* context = objects_[i];
+      s->AssignRef(context);
+      AutoTraceObject(context);
       intptr_t length = context->ptr()->num_variables_;
       s->WriteUnsigned(length);
-      s->AssignRef(context);
     }
   }
 
@@ -2086,6 +1931,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawContext* context = objects_[i];
+      AutoTraceObject(context);
       intptr_t length = context->ptr()->num_variables_;
       s->WriteUnsigned(length);
       s->WriteRef(context->ptr()->parent_);
@@ -2145,11 +1991,7 @@
     objects_.Add(scope);
 
     intptr_t length = scope->ptr()->num_variables_;
-    RawObject** from = scope->from();
-    RawObject** to = scope->to(length);
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(scope, length);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2158,9 +2000,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawContextScope* scope = objects_[i];
+      s->AssignRef(scope);
+      AutoTraceObject(scope);
       intptr_t length = scope->ptr()->num_variables_;
       s->WriteUnsigned(length);
-      s->AssignRef(scope);
     }
   }
 
@@ -2168,14 +2011,11 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawContextScope* scope = objects_[i];
+      AutoTraceObject(scope);
       intptr_t length = scope->ptr()->num_variables_;
       s->WriteUnsigned(length);
       s->Write<bool>(scope->ptr()->is_implicit_);
-      RawObject** from = scope->from();
-      RawObject** to = scope->to(length);
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      WriteFromTo(scope, length);
     }
   }
 
@@ -2212,11 +2052,7 @@
                                      is_vm_object);
       scope->ptr()->num_variables_ = length;
       scope->ptr()->is_implicit_ = d->Read<bool>();
-      RawObject** from = scope->from();
-      RawObject** to = scope->to(length);
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(scope, length);
     }
   }
 };
@@ -2230,12 +2066,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawUnlinkedCall* unlinked = UnlinkedCall::RawCast(object);
     objects_.Add(unlinked);
-
-    RawObject** from = unlinked->from();
-    RawObject** to = unlinked->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(unlinked);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2252,11 +2083,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawUnlinkedCall* unlinked = objects_[i];
-      RawObject** from = unlinked->from();
-      RawObject** to = unlinked->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(unlinked);
+      WriteFromTo(unlinked);
     }
   }
 
@@ -2290,11 +2118,7 @@
       Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid,
                                      UnlinkedCall::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = unlinked->from();
-      RawObject** to = unlinked->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(unlinked);
     }
   }
 };
@@ -2308,12 +2132,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawICData* ic = ICData::RawCast(object);
     objects_.Add(ic);
-
-    RawObject** from = ic->from();
-    RawObject** to = ic->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(ic);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2331,11 +2150,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawICData* ic = objects_[i];
-      RawObject** from = ic->from();
-      RawObject** to = ic->to_snapshot(kind);
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(ic);
+      WriteFromTo(ic);
       if (kind != Snapshot::kFullAOT) {
         NOT_IN_PRECOMPILED(s->Write<int32_t>(ic->ptr()->deopt_id_));
       }
@@ -2367,22 +2183,13 @@
   }
 
   void ReadFill(Deserializer* d) {
-    Snapshot::Kind kind = d->kind();
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawICData* ic = reinterpret_cast<RawICData*>(d->Ref(id));
       Deserializer::InitializeHeader(ic, kICDataCid, ICData::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = ic->from();
-      RawObject** to_snapshot = ic->to_snapshot(kind);
-      RawObject** to = ic->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
+      ReadFromTo(ic);
       NOT_IN_PRECOMPILED(ic->ptr()->deopt_id_ = d->Read<int32_t>());
       ic->ptr()->state_bits_ = d->Read<int32_t>();
 #if defined(TAG_IC_DATA)
@@ -2402,12 +2209,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawMegamorphicCache* cache = MegamorphicCache::RawCast(object);
     objects_.Add(cache);
-
-    RawObject** from = cache->from();
-    RawObject** to = cache->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(cache);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2424,11 +2226,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawMegamorphicCache* cache = objects_[i];
-      RawObject** from = cache->from();
-      RawObject** to = cache->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(cache);
+      WriteFromTo(cache);
       s->Write<int32_t>(cache->ptr()->filled_entry_count_);
     }
   }
@@ -2463,11 +2262,7 @@
       Deserializer::InitializeHeader(cache, kMegamorphicCacheCid,
                                      MegamorphicCache::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = cache->from();
-      RawObject** to = cache->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(cache);
       cache->ptr()->filled_entry_count_ = d->Read<int32_t>();
     }
   }
@@ -2500,6 +2295,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawSubtypeTestCache* cache = objects_[i];
+      AutoTraceObject(cache);
       s->WriteRef(cache->ptr()->cache_);
     }
   }
@@ -2548,12 +2344,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawLanguageError* error = LanguageError::RawCast(object);
     objects_.Add(error);
-
-    RawObject** from = error->from();
-    RawObject** to = error->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(error);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2570,11 +2361,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLanguageError* error = objects_[i];
-      RawObject** from = error->from();
-      RawObject** to = error->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(error);
+      WriteFromTo(error);
       s->WriteTokenPosition(error->ptr()->token_pos_);
       s->Write<bool>(error->ptr()->report_after_token_);
       s->Write<int8_t>(error->ptr()->kind_);
@@ -2610,11 +2398,7 @@
       Deserializer::InitializeHeader(error, kLanguageErrorCid,
                                      LanguageError::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = error->from();
-      RawObject** to = error->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(error);
       error->ptr()->token_pos_ = d->ReadTokenPosition();
       error->ptr()->report_after_token_ = d->Read<bool>();
       error->ptr()->kind_ = d->Read<int8_t>();
@@ -2632,12 +2416,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawUnhandledException* exception = UnhandledException::RawCast(object);
     objects_.Add(exception);
-
-    RawObject** from = exception->from();
-    RawObject** to = exception->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(exception);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2654,11 +2433,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawUnhandledException* exception = objects_[i];
-      RawObject** from = exception->from();
-      RawObject** to = exception->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(exception);
+      WriteFromTo(exception);
     }
   }
 
@@ -2692,11 +2468,7 @@
       Deserializer::InitializeHeader(exception, kUnhandledExceptionCid,
                                      UnhandledException::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = exception->from();
-      RawObject** to = exception->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(exception);
     }
   }
 };
@@ -2747,6 +2519,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawInstance* instance = objects_[i];
+      AutoTraceObject(instance);
       s->Write<bool>(instance->IsCanonical());
       intptr_t offset = Instance::NextFieldOffset();
       while (offset < next_field_offset) {
@@ -2828,12 +2601,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawLibraryPrefix* prefix = LibraryPrefix::RawCast(object);
     objects_.Add(prefix);
-
-    RawObject** from = prefix->from();
-    RawObject** to = prefix->to_snapshot(s->kind());
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(prefix);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2847,15 +2615,11 @@
   }
 
   void WriteFill(Serializer* s) {
-    Snapshot::Kind kind = s->kind();
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLibraryPrefix* prefix = objects_[i];
-      RawObject** from = prefix->from();
-      RawObject** to = prefix->to_snapshot(kind);
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(prefix);
+      WriteFromTo(prefix);
       s->Write<uint16_t>(prefix->ptr()->num_imports_);
       s->Write<bool>(prefix->ptr()->is_deferred_load_);
     }
@@ -2883,7 +2647,6 @@
   }
 
   void ReadFill(Deserializer* d) {
-    Snapshot::Kind kind = d->kind();
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -2892,16 +2655,7 @@
       Deserializer::InitializeHeader(prefix, kLibraryPrefixCid,
                                      LibraryPrefix::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = prefix->from();
-      RawObject** to_snapshot = prefix->to_snapshot(kind);
-      RawObject** to = prefix->to();
-      for (RawObject** p = from; p <= to_snapshot; p++) {
-        *p = d->ReadRef();
-      }
-      for (RawObject** p = to_snapshot + 1; p <= to; p++) {
-        *p = Object::null();
-      }
-
+      ReadFromTo(prefix);
       prefix->ptr()->num_imports_ = d->Read<uint16_t>();
       prefix->ptr()->is_deferred_load_ = d->Read<bool>();
       prefix->ptr()->is_loaded_ = !prefix->ptr()->is_deferred_load_;
@@ -2924,11 +2678,7 @@
       objects_.Add(type);
     }
 
-    RawObject** from = type->from();
-    RawObject** to = type->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(type);
 
     if (type->ptr()->type_class_id_->IsHeapObject()) {
       // Type class is still an unresolved class.
@@ -2965,11 +2715,8 @@
     intptr_t count = canonical_objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawType* type = canonical_objects_[i];
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(type);
+      WriteFromTo(type);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int8_t>(type->ptr()->type_state_);
       if (should_write_type_testing_stub) {
@@ -2981,11 +2728,8 @@
     count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawType* type = objects_[i];
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(type);
+      WriteFromTo(type);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int8_t>(type->ptr()->type_state_);
       if (should_write_type_testing_stub) {
@@ -3048,11 +2792,7 @@
       RawType* type = reinterpret_cast<RawType*>(d->Ref(id));
       Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
                                      is_vm_isolate, true);
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(type);
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
       if (should_read_type_testing_stub) {
@@ -3066,11 +2806,7 @@
       RawType* type = reinterpret_cast<RawType*>(d->Ref(id));
       Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
                                      is_vm_isolate);
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(type);
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
       if (should_read_type_testing_stub) {
@@ -3123,12 +2859,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawTypeRef* type = TypeRef::RawCast(object);
     objects_.Add(type);
-
-    RawObject** from = type->from();
-    RawObject** to = type->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(type);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3148,11 +2879,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeRef* type = objects_[i];
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(type);
+      WriteFromTo(type);
       if (should_write_type_testing_stub) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
@@ -3192,11 +2920,7 @@
       RawTypeRef* type = reinterpret_cast<RawTypeRef*>(d->Ref(id));
       Deserializer::InitializeHeader(type, kTypeRefCid, TypeRef::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(type);
       if (should_read_type_testing_stub) {
         instr_ = d->ReadInstructions();
         type_ = type;
@@ -3232,12 +2956,7 @@
     RawTypeParameter* type = TypeParameter::RawCast(object);
     objects_.Add(type);
     ASSERT(!type->IsCanonical());
-
-    RawObject** from = type->from();
-    RawObject** to = type->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(type);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3257,11 +2976,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeParameter* type = objects_[i];
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(type);
+      WriteFromTo(type);
       s->Write<int32_t>(type->ptr()->parameterized_class_id_);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int16_t>(type->ptr()->index_);
@@ -3306,11 +3022,7 @@
       RawTypeParameter* type = reinterpret_cast<RawTypeParameter*>(d->Ref(id));
       Deserializer::InitializeHeader(
           type, kTypeParameterCid, TypeParameter::InstanceSize(), is_vm_object);
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(type);
       type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->index_ = d->Read<int16_t>();
@@ -3347,12 +3059,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawBoundedType* type = BoundedType::RawCast(object);
     objects_.Add(type);
-
-    RawObject** from = type->from();
-    RawObject** to = type->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(type);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3369,11 +3076,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawBoundedType* type = objects_[i];
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(type);
+      WriteFromTo(type);
     }
   }
 
@@ -3405,11 +3109,7 @@
       RawBoundedType* type = reinterpret_cast<RawBoundedType*>(d->Ref(id));
       Deserializer::InitializeHeader(type, kBoundedTypeCid,
                                      BoundedType::InstanceSize(), is_vm_object);
-      RawObject** from = type->from();
-      RawObject** to = type->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(type);
     }
   }
 };
@@ -3423,12 +3123,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawClosure* closure = Closure::RawCast(object);
     objects_.Add(closure);
-
-    RawObject** from = closure->from();
-    RawObject** to = closure->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(closure);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3445,12 +3140,9 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawClosure* closure = objects_[i];
+      AutoTraceObject(closure);
       s->Write<bool>(closure->IsCanonical());
-      RawObject** from = closure->from();
-      RawObject** to = closure->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      WriteFromTo(closure);
     }
   }
 
@@ -3483,11 +3175,7 @@
       Deserializer::InitializeHeader(closure, kClosureCid,
                                      Closure::InstanceSize(), is_vm_object,
                                      is_canonical);
-      RawObject** from = closure->from();
-      RawObject** to = closure->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(closure);
     }
   }
 };
@@ -3514,15 +3202,17 @@
     s->WriteUnsigned(smis_.length() + mints_.length());
     for (intptr_t i = 0; i < smis_.length(); i++) {
       RawSmi* smi = smis_[i];
+      s->AssignRef(smi);
+      AutoTraceObject(smi);
       s->Write<bool>(true);
       s->Write<int64_t>(Smi::Value(smi));
-      s->AssignRef(smi);
     }
     for (intptr_t i = 0; i < mints_.length(); i++) {
       RawMint* mint = mints_[i];
+      s->AssignRef(mint);
+      AutoTraceObject(mint);
       s->Write<bool>(mint->IsCanonical());
       s->Write<int64_t>(mint->ptr()->value_);
-      s->AssignRef(mint);
     }
   }
 
@@ -3606,6 +3296,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawDouble* dbl = objects_[i];
+      AutoTraceObject(dbl);
       s->Write<bool>(dbl->IsCanonical());
       s->Write<double>(dbl->ptr()->value_);
     }
@@ -3654,12 +3345,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawGrowableObjectArray* array = GrowableObjectArray::RawCast(object);
     objects_.Add(array);
-
-    RawObject** from = array->from();
-    RawObject** to = array->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(array);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3676,12 +3362,9 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawGrowableObjectArray* array = objects_[i];
+      AutoTraceObject(array);
       s->Write<bool>(array->IsCanonical());
-      RawObject** from = array->from();
-      RawObject** to = array->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      WriteFromTo(array);
     }
   }
 
@@ -3717,11 +3400,7 @@
       Deserializer::InitializeHeader(list, kGrowableObjectArrayCid,
                                      GrowableObjectArray::InstanceSize(),
                                      is_vm_object, is_canonical);
-      RawObject** from = list->from();
-      RawObject** to = list->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(list);
     }
   }
 };
@@ -3744,9 +3423,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypedData* data = objects_[i];
+      s->AssignRef(data);
+      AutoTraceObject(data);
       intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
-      s->AssignRef(data);
     }
   }
 
@@ -3755,6 +3435,7 @@
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
       RawTypedData* data = objects_[i];
+      AutoTraceObject(data);
       intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(data->IsCanonical());
@@ -3837,6 +3518,7 @@
     intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
       RawExternalTypedData* data = objects_[i];
+      AutoTraceObject(data);
       intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data_);
@@ -3898,12 +3580,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawStackTrace* trace = StackTrace::RawCast(object);
     objects_.Add(trace);
-
-    RawObject** from = trace->from();
-    RawObject** to = trace->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(trace);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3920,11 +3597,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawStackTrace* trace = objects_[i];
-      RawObject** from = trace->from();
-      RawObject** to = trace->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(trace);
+      WriteFromTo(trace);
     }
   }
 
@@ -3956,11 +3630,7 @@
       RawStackTrace* trace = reinterpret_cast<RawStackTrace*>(d->Ref(id));
       Deserializer::InitializeHeader(trace, kStackTraceCid,
                                      StackTrace::InstanceSize(), is_vm_object);
-      RawObject** from = trace->from();
-      RawObject** to = trace->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(trace);
     }
   }
 };
@@ -3974,12 +3644,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawRegExp* regexp = RegExp::RawCast(object);
     objects_.Add(regexp);
-
-    RawObject** from = regexp->from();
-    RawObject** to = regexp->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(regexp);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -3996,12 +3661,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawRegExp* regexp = objects_[i];
-      RawObject** from = regexp->from();
-      RawObject** to = regexp->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
-
+      AutoTraceObject(regexp);
+      WriteFromTo(regexp);
       s->Write<int32_t>(regexp->ptr()->num_registers_);
       s->Write<int8_t>(regexp->ptr()->type_flags_);
     }
@@ -4034,12 +3695,7 @@
       RawRegExp* regexp = reinterpret_cast<RawRegExp*>(d->Ref(id));
       Deserializer::InitializeHeader(regexp, kRegExpCid, RegExp::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = regexp->from();
-      RawObject** to = regexp->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
-
+      ReadFromTo(regexp);
       regexp->ptr()->num_registers_ = d->Read<int32_t>();
       regexp->ptr()->type_flags_ = d->Read<int8_t>();
     }
@@ -4055,12 +3711,7 @@
   void Trace(Serializer* s, RawObject* object) {
     RawWeakProperty* property = WeakProperty::RawCast(object);
     objects_.Add(property);
-
-    RawObject** from = property->from();
-    RawObject** to = property->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
+    PushFromTo(property);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -4077,11 +3728,8 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawWeakProperty* property = objects_[i];
-      RawObject** from = property->from();
-      RawObject** to = property->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
+      AutoTraceObject(property);
+      WriteFromTo(property);
     }
   }
 
@@ -4115,11 +3763,7 @@
       Deserializer::InitializeHeader(property, kWeakPropertyCid,
                                      WeakProperty::InstanceSize(),
                                      is_vm_object);
-      RawObject** from = property->from();
-      RawObject** to = property->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
+      ReadFromTo(property);
     }
   }
 };
@@ -4163,6 +3807,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLinkedHashMap* map = objects_[i];
+      AutoTraceObject(map);
       s->Write<bool>(map->IsCanonical());
 
       s->WriteRef(map->ptr()->type_arguments_);
@@ -4274,9 +3919,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawArray* array = objects_[i];
+      s->AssignRef(array);
+      AutoTraceObject(array);
       intptr_t length = Smi::Value(array->ptr()->length_);
       s->WriteUnsigned(length);
-      s->AssignRef(array);
     }
   }
 
@@ -4284,6 +3930,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawArray* array = objects_[i];
+      AutoTraceObject(array);
       intptr_t length = Smi::Value(array->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(array->IsCanonical());
@@ -4356,9 +4003,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawOneByteString* str = objects_[i];
+      s->AssignRef(str);
+      AutoTraceObject(str);
       intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
-      s->AssignRef(str);
     }
   }
 
@@ -4366,6 +4014,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawOneByteString* str = objects_[i];
+      AutoTraceObject(str);
       intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(str->IsCanonical());
@@ -4433,9 +4082,10 @@
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTwoByteString* str = objects_[i];
+      s->AssignRef(str);
+      AutoTraceObject(str);
       intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
-      s->AssignRef(str);
     }
   }
 
@@ -4443,6 +4093,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTwoByteString* str = objects_[i];
+      AutoTraceObject(str);
       intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(str->IsCanonical());
@@ -4512,7 +4163,9 @@
                        uint8_t** buffer,
                        ReAlloc alloc,
                        intptr_t initial_size,
-                       ImageWriter* image_writer)
+                       ImageWriter* image_writer,
+                       bool vm,
+                       V8SnapshotProfileWriter* profile_writer)
     : StackResource(thread),
       heap_(thread->isolate()->heap()),
       zone_(thread->zone()),
@@ -4524,7 +4177,9 @@
       num_cids_(0),
       num_base_objects_(0),
       num_written_objects_(0),
-      next_ref_index_(1)
+      next_ref_index_(1),
+      vm_(vm),
+      profile_writer_(profile_writer)
 #if defined(SNAPSHOT_BACKTRACE)
       ,
       current_parent_(Object::null()),
@@ -4542,6 +4197,43 @@
   delete[] clusters_by_cid_;
 }
 
+void Serializer::TraceStartWritingObject(const char* type,
+                                         RawObject* obj,
+                                         RawString* name) {
+  if (profile_writer_ == nullptr) return;
+
+  intptr_t id = 0;
+  if (obj->IsHeapObject()) {
+    id = heap_->GetObjectId(obj);
+  } else {
+    id = smi_ids_.Lookup(Smi::RawCast(obj))->id_;
+  }
+  ASSERT(id != 0);
+
+  const char* name_str = nullptr;
+  if (name != nullptr) {
+    String& str = thread()->StringHandle();
+    str = name;
+    name_str = str.ToCString();
+  }
+
+  object_currently_writing_id_ = id;
+  profile_writer_->SetObjectTypeAndName(
+      {V8SnapshotProfileWriter::kSnapshot, id}, type, name_str);
+  object_currently_writing_start_ = stream_.Position();
+}
+
+void Serializer::TraceEndWritingObject() {
+  if (profile_writer_ != nullptr) {
+    ASSERT(object_currently_writing_id_ != 0);
+    profile_writer_->AttributeBytesTo(
+        {V8SnapshotProfileWriter::kSnapshot, object_currently_writing_id_},
+        stream_.Position() - object_currently_writing_start_);
+    object_currently_writing_id_ = 0;
+    object_currently_writing_start_ = 0;
+  }
+}
+
 SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
@@ -4679,6 +4371,31 @@
   const intptr_t offset = image_writer_->GetTextOffsetFor(instr, code);
   ASSERT(offset != 0);
   Write<int32_t>(offset);
+
+  // If offset < 0, it's pointing to a shared instruction. We don't profile
+  // references to shared text/data (since they don't consume any space). Of
+  // course, the space taken for the reference is profiled.
+  if (profile_writer_ != nullptr && offset >= 0) {
+    // Instructions cannot be roots.
+    ASSERT(object_currently_writing_id_ != 0);
+    auto offset_space = vm_ ? V8SnapshotProfileWriter::kVmText
+                            : V8SnapshotProfileWriter::kIsolateText;
+    profile_writer_->AttributeReferenceTo(
+        {V8SnapshotProfileWriter::kSnapshot, object_currently_writing_id_},
+        {offset_space, offset < 0 ? -offset : offset});
+  }
+}
+
+void Serializer::TraceDataOffset(uint32_t offset) {
+  if (profile_writer_ != nullptr) {
+    // ROData cannot be roots.
+    ASSERT(object_currently_writing_id_ != 0);
+    auto offset_space = vm_ ? V8SnapshotProfileWriter::kVmData
+                            : V8SnapshotProfileWriter::kIsolateData;
+    profile_writer_->AttributeReferenceTo(
+        {V8SnapshotProfileWriter::kSnapshot, object_currently_writing_id_},
+        {offset_space, offset});
+  }
 }
 
 bool Serializer::GetSharedDataOffset(RawObject* object,
@@ -4923,30 +4640,36 @@
   // These objects are always allocated by Object::InitOnce, so they are not
   // written into the snapshot.
 
-  AddBaseObject(Object::null());
-  AddBaseObject(Object::sentinel().raw());
-  AddBaseObject(Object::transition_sentinel().raw());
-  AddBaseObject(Object::empty_array().raw());
-  AddBaseObject(Object::zero_array().raw());
-  AddBaseObject(Object::dynamic_type().raw());
-  AddBaseObject(Object::void_type().raw());
-  AddBaseObject(Object::empty_type_arguments().raw());
-  AddBaseObject(Bool::True().raw());
-  AddBaseObject(Bool::False().raw());
+  AddBaseObject(Object::null(), "Null", "<null>");
+  AddBaseObject(Object::sentinel().raw(), "Sentinel");
+  AddBaseObject(Object::transition_sentinel().raw(), "Sentinel");
+  AddBaseObject(Object::empty_array().raw(), "Array", "<empty_array>");
+  AddBaseObject(Object::zero_array().raw(), "Array", "<zero_array>");
+  AddBaseObject(Object::dynamic_type().raw(), "Type", "<dynamic type>");
+  AddBaseObject(Object::void_type().raw(), "Type", "<void type>");
+  AddBaseObject(Object::empty_type_arguments().raw(), "TypeArguments", "[]");
+  AddBaseObject(Bool::True().raw(), "bool", "true");
+  AddBaseObject(Bool::False().raw(), "bool", "false");
   ASSERT(Object::extractor_parameter_types().raw() != Object::null());
-  AddBaseObject(Object::extractor_parameter_types().raw());
+  AddBaseObject(Object::extractor_parameter_types().raw(), "Array",
+                "<extractor parameter types>");
   ASSERT(Object::extractor_parameter_names().raw() != Object::null());
-  AddBaseObject(Object::extractor_parameter_names().raw());
-  AddBaseObject(Object::empty_context_scope().raw());
-  AddBaseObject(Object::empty_descriptors().raw());
-  AddBaseObject(Object::empty_var_descriptors().raw());
-  AddBaseObject(Object::empty_exception_handlers().raw());
+  AddBaseObject(Object::extractor_parameter_names().raw(), "Array",
+                "<extractor parameter names>");
+  AddBaseObject(Object::empty_context_scope().raw(), "ContextScope", "<empty>");
+  AddBaseObject(Object::empty_descriptors().raw(), "PcDescriptors", "<empty>");
+  AddBaseObject(Object::empty_var_descriptors().raw(), "LocalVarDescriptors",
+                "<empty>");
+  AddBaseObject(Object::empty_exception_handlers().raw(), "ExceptionHandlers",
+                "<empty>");
 
   for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
-    AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
+    AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i],
+                  "ArgumentsDescriptor", "<cached arguments descriptor>");
   }
   for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
-    AddBaseObject(ICData::cached_icdata_arrays_[i]);
+    AddBaseObject(ICData::cached_icdata_arrays_[i], "ICData",
+                  "<cached icdata>");
   }
 
   ClassTable* table = isolate()->class_table();
@@ -4954,15 +4677,15 @@
     // Error has no class object.
     if (cid != kErrorCid) {
       ASSERT(table->HasValidClassAt(cid));
-      AddBaseObject(table->At(cid));
+      AddBaseObject(table->At(cid), "Class");
     }
   }
-  AddBaseObject(table->At(kDynamicCid));
-  AddBaseObject(table->At(kVoidCid));
+  AddBaseObject(table->At(kDynamicCid), "Class");
+  AddBaseObject(table->At(kVoidCid), "Class");
 
   if (!Snapshot::IncludesCode(kind_)) {
     for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-      AddBaseObject(StubCode::EntryAt(i)->code());
+      AddBaseObject(StubCode::EntryAt(i).raw(), "Code", "<stub code>");
     }
   }
 }
@@ -4977,7 +4700,7 @@
   Push(symbols.raw());
   if (Snapshot::IncludesCode(kind_)) {
     for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-      Push(StubCode::EntryAt(i)->code());
+      Push(StubCode::EntryAt(i).raw());
     }
   }
   if (seeds != NULL) {
@@ -4989,10 +4712,10 @@
   Serialize();
 
   // Write roots.
-  WriteRef(symbols.raw());
+  WriteRootRef(symbols.raw());
   if (Snapshot::IncludesCode(kind_)) {
     for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-      WriteRef(StubCode::EntryAt(i)->code());
+      WriteRootRef(StubCode::EntryAt(i).raw());
     }
   }
 
@@ -5035,7 +4758,7 @@
 
   // Write roots.
   for (RawObject** p = from; p <= to; p++) {
-    WriteRef(*p);
+    WriteRootRef(*p);
   }
 
 #if defined(DEBUG)
@@ -5385,7 +5108,7 @@
 
   if (!Snapshot::IncludesCode(kind_)) {
     for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-      AddBaseObject(StubCode::EntryAt(i)->code());
+      AddBaseObject(StubCode::EntryAt(i).raw());
     }
   }
 }
@@ -5407,10 +5130,10 @@
     symbol_table ^= ReadRef();
     isolate()->object_store()->set_symbol_table(symbol_table);
     if (Snapshot::IncludesCode(kind_)) {
-      Code& code = Code::Handle(zone_);
       for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-        code ^= ReadRef();
-        StubCode::EntryAtPut(i, new StubEntry(code));
+        Code* code = Code::ReadOnlyHandle();
+        *code ^= ReadRef();
+        StubCode::EntryAtPut(i, code);
       }
     }
 
@@ -5571,6 +5294,13 @@
   KernelProgramInfo& kernel_program_info_;
 };
 
+#if defined(DART_PRECOMPILER)
+DEFINE_FLAG(charp,
+            write_v8_snapshot_profile_to,
+            NULL,
+            "Write a snapshot profile in V8 format to a file.");
+#endif
+
 FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
                                        uint8_t** vm_snapshot_data_buffer,
                                        uint8_t** isolate_snapshot_data_buffer,
@@ -5634,6 +5364,12 @@
     saved_symbol_table_ = object_store->symbol_table();
     new_vm_symbol_table_ = Dart::vm_isolate()->object_store()->symbol_table();
   }
+
+#if defined(DART_PRECOMPILER)
+  if (FLAG_write_v8_snapshot_profile_to != nullptr) {
+    profile_writer_ = new (zone()) V8SnapshotProfileWriter(zone());
+  }
+#endif
 }
 
 FullSnapshotWriter::~FullSnapshotWriter() {
@@ -5651,7 +5387,8 @@
 
   ASSERT(vm_snapshot_data_buffer_ != NULL);
   Serializer serializer(thread(), kind_, vm_snapshot_data_buffer_, alloc_,
-                        kInitialSize, vm_image_writer_);
+                        kInitialSize, vm_image_writer_, /*vm=*/true,
+                        profile_writer_);
 
   serializer.ReserveHeader();
   serializer.WriteVersionAndFeatures(true);
@@ -5665,10 +5402,12 @@
   clustered_vm_size_ = serializer.bytes_written();
 
   if (Snapshot::IncludesCode(kind_)) {
+    vm_image_writer_->SetProfileWriter(profile_writer_);
     vm_image_writer_->Write(serializer.stream(), true);
     mapped_data_size_ += vm_image_writer_->data_size();
     mapped_text_size_ += vm_image_writer_->text_size();
     vm_image_writer_->ResetOffsets();
+    vm_image_writer_->ClearProfileWriter();
   }
 
   // The clustered part + the direct mapped data part.
@@ -5681,7 +5420,8 @@
       thread(), Timeline::GetIsolateStream(), "WriteIsolateSnapshot"));
 
   Serializer serializer(thread(), kind_, isolate_snapshot_data_buffer_, alloc_,
-                        kInitialSize, isolate_image_writer_);
+                        kInitialSize, isolate_image_writer_, /*vm=*/false,
+                        profile_writer_);
   ObjectStore* object_store = isolate()->object_store();
   ASSERT(object_store != NULL);
 
@@ -5694,6 +5434,7 @@
   clustered_isolate_size_ = serializer.bytes_written();
 
   if (Snapshot::IncludesCode(kind_)) {
+    isolate_image_writer_->SetProfileWriter(profile_writer_);
     isolate_image_writer_->Write(serializer.stream(), false);
 #if defined(DART_PRECOMPILER)
     isolate_image_writer_->DumpStatistics();
@@ -5702,6 +5443,7 @@
     mapped_data_size_ += isolate_image_writer_->data_size();
     mapped_text_size_ += isolate_image_writer_->text_size();
     isolate_image_writer_->ResetOffsets();
+    isolate_image_writer_->ClearProfileWriter();
   }
 
   // The clustered part + the direct mapped data part.
@@ -5730,6 +5472,12 @@
               clustered_vm_size_ + clustered_isolate_size_ + mapped_data_size_ +
                   mapped_text_size_);
   }
+
+#if defined(DART_PRECOMPILER)
+  if (FLAG_write_v8_snapshot_profile_to != nullptr) {
+    profile_writer_->Write(FLAG_write_v8_snapshot_profile_to);
+  }
+#endif
 }
 
 FullSnapshotReader::FullSnapshotReader(const Snapshot* snapshot,
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 1f64d11..79bdd8d 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -16,6 +16,7 @@
 #include "vm/object.h"
 #include "vm/snapshot.h"
 #include "vm/type_testing_stubs.h"
+#include "vm/v8_snapshot_writer.h"
 #include "vm/version.h"
 
 #if defined(DEBUG)
@@ -132,7 +133,9 @@
              uint8_t** buffer,
              ReAlloc alloc,
              intptr_t initial_size,
-             ImageWriter* image_writer_);
+             ImageWriter* image_writer_,
+             bool vm_,
+             V8SnapshotProfileWriter* profile_writer = nullptr);
   ~Serializer();
 
   intptr_t WriteVMSnapshot(const Array& symbols,
@@ -142,12 +145,26 @@
 
   void AddVMIsolateBaseObjects();
 
-  void AddBaseObject(RawObject* base_object) {
-    AssignRef(base_object);
+  void AddBaseObject(RawObject* base_object,
+                     const char* type = nullptr,
+                     const char* name = nullptr) {
+    intptr_t ref = AssignRef(base_object);
     num_base_objects_++;
+
+    if (profile_writer_ != nullptr) {
+      if (type == nullptr) {
+        type = "Unknown";
+      }
+      if (name == nullptr) {
+        name = "<base object>";
+      }
+      profile_writer_->SetObjectTypeAndName(
+          {V8SnapshotProfileWriter::kSnapshot, ref}, type, name);
+      profile_writer_->AddRoot({V8SnapshotProfileWriter::kSnapshot, ref});
+    }
   }
 
-  void AssignRef(RawObject* object) {
+  intptr_t AssignRef(RawObject* object) {
     ASSERT(next_ref_index_ != 0);
     if (object->IsHeapObject()) {
       // The object id weak table holds image offsets for Instructions instead
@@ -168,7 +185,7 @@
         smi_ids_.Insert(new_pair);
       }
     }
-    next_ref_index_++;
+    return next_ref_index_++;
   }
 
   void Push(RawObject* object);
@@ -202,6 +219,11 @@
   WriteStream* stream() { return &stream_; }
   intptr_t bytes_written() { return stream_.bytes_written(); }
 
+  void TraceStartWritingObject(const char* type,
+                               RawObject* obj,
+                               RawString* name);
+  void TraceEndWritingObject();
+
   // Writes raw data to the stream (basic type).
   // sizeof(T) must be in {1,2,4,8}.
   template <typename T>
@@ -214,41 +236,74 @@
   }
   void Align(intptr_t alignment) { stream_.Align(alignment); }
 
-  void WriteRef(RawObject* object) {
+  void WriteRef(RawObject* object, bool is_root = false) {
+    intptr_t id = 0;
     if (!object->IsHeapObject()) {
       RawSmi* smi = Smi::RawCast(object);
-      intptr_t id = smi_ids_.Lookup(smi)->id_;
+      id = smi_ids_.Lookup(smi)->id_;
       if (id == 0) {
         FATAL("Missing ref");
       }
-      WriteUnsigned(id);
-      return;
+    } else {
+      // The object id weak table holds image offsets for Instructions instead
+      // of ref indices.
+      ASSERT(!object->IsInstructions());
+      id = heap_->GetObjectId(object);
+      if (id == 0) {
+        if (object->IsCode() && !Snapshot::IncludesCode(kind_)) {
+          WriteRef(Object::null());
+          return;
+        }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
+          WriteRef(Object::null());
+          return;
+        }
+#endif  // !DART_PRECOMPILED_RUNTIME
+        if (object->IsSendPort()) {
+          // TODO(rmacnak): Do a better job of resetting fields in
+          // precompilation and assert this is unreachable.
+          WriteRef(Object::null());
+          return;
+        }
+        FATAL("Missing ref");
+      }
     }
 
-    // The object id weak table holds image offsets for Instructions instead
-    // of ref indices.
-    ASSERT(!object->IsInstructions());
-    intptr_t id = heap_->GetObjectId(object);
-    if (id == 0) {
-      if (object->IsCode() && !Snapshot::IncludesCode(kind_)) {
-        WriteRef(Object::null());
-        return;
-      }
-#if !defined(DART_PRECOMPILED_RUNTIME)
-      if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
-        WriteRef(Object::null());
-        return;
-      }
-#endif  // !DART_PRECOMPILED_RUNTIME
-      if (object->IsSendPort()) {
-        // TODO(rmacnak): Do a better job of resetting fields in precompilation
-        // and assert this is unreachable.
-        WriteRef(Object::null());
-        return;
-      }
-      FATAL("Missing ref");
-    }
     WriteUnsigned(id);
+
+    if (profile_writer_ != nullptr) {
+      if (object_currently_writing_id_ != 0) {
+        profile_writer_->AttributeReferenceTo(
+            {V8SnapshotProfileWriter::kSnapshot, object_currently_writing_id_},
+            {V8SnapshotProfileWriter::kSnapshot, id});
+      } else {
+        ASSERT(is_root);
+        profile_writer_->AddRoot({V8SnapshotProfileWriter::kSnapshot, id});
+      }
+    }
+  }
+
+  template <typename T, typename... P>
+  void WriteFromTo(T* obj, P&&... args) {
+    RawObject** from = obj->from();
+    RawObject** to = obj->to_snapshot(kind(), args...);
+    for (RawObject** p = from; p <= to; p++) {
+      WriteRef(*p);
+    }
+  }
+
+  template <typename T, typename... P>
+  void PushFromTo(T* obj, P&&... args) {
+    RawObject** from = obj->from();
+    RawObject** to = obj->to_snapshot(kind(), args...);
+    for (RawObject** p = from; p <= to; p++) {
+      Push(*p);
+    }
+  }
+
+  void WriteRootRef(RawObject* object) {
+    WriteRef(object, /* is_root = */ true);
   }
 
   void WriteTokenPosition(TokenPosition pos) {
@@ -263,6 +318,7 @@
   void WriteInstructions(RawInstructions* instr, RawCode* code);
   bool GetSharedDataOffset(RawObject* object, uint32_t* offset) const;
   uint32_t GetDataOffset(RawObject* object) const;
+  void TraceDataOffset(uint32_t offset);
   intptr_t GetDataSize() const;
   intptr_t GetTextSize() const;
 
@@ -286,6 +342,13 @@
   intptr_t next_ref_index_;
   SmiObjectIdMap smi_ids_;
 
+  // True if writing VM snapshot, false for Isolate snapshot.
+  bool vm_;
+
+  V8SnapshotProfileWriter* profile_writer_ = nullptr;
+  intptr_t object_currently_writing_id_ = 0;
+  intptr_t object_currently_writing_start_ = 0;
+
 #if defined(SNAPSHOT_BACKTRACE)
   RawObject* current_parent_;
   GrowableArray<Object*> parent_pairs_;
@@ -294,6 +357,35 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer);
 };
 
+#define AutoTraceObject(obj)                                                   \
+  SerializerWritingObjectScope scope_##__COUNTER__(s, name(), obj, nullptr)
+
+#define AutoTraceObjectName(obj, str)                                          \
+  SerializerWritingObjectScope scope_##__COUNTER__(s, name(), obj, str)
+
+#define WriteField(obj, field) s->WriteRef(obj->ptr()->field);
+
+#define WriteFieldValue(field, value) s->WriteRef(value);
+
+#define WriteFromTo(obj, ...) s->WriteFromTo(obj, ##__VA_ARGS__);
+
+#define PushFromTo(obj, ...) s->PushFromTo(obj, ##__VA_ARGS__);
+
+struct SerializerWritingObjectScope {
+  SerializerWritingObjectScope(Serializer* serializer,
+                               const char* type,
+                               RawObject* object,
+                               RawString* name)
+      : serializer_(serializer) {
+    serializer_->TraceStartWritingObject(type, object, name);
+  }
+
+  ~SerializerWritingObjectScope() { serializer_->TraceEndWritingObject(); }
+
+ private:
+  Serializer* serializer_;
+};
+
 class Deserializer : public StackResource {
  public:
   Deserializer(Thread* thread,
@@ -351,6 +443,20 @@
 
   RawObject* ReadRef() { return Ref(ReadUnsigned()); }
 
+  template <typename T, typename... P>
+  void ReadFromTo(T* obj, P&&... params) {
+    RawObject** from = obj->from();
+    RawObject** to_snapshot = obj->to_snapshot(kind(), params...);
+    RawObject** to = obj->to(params...);
+    for (RawObject** p = from; p <= to_snapshot; p++) {
+      *p = ReadRef();
+    }
+    // TODO(sjindel/rmacnak): Is this really necessary?
+    for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+      *p = Object::null();
+    }
+  }
+
   TokenPosition ReadTokenPosition() {
     return TokenPosition::SnapshotDecode(Read<int32_t>());
   }
@@ -391,6 +497,8 @@
   DeserializationCluster** clusters_;
 };
 
+#define ReadFromTo(obj, ...) d->ReadFromTo(obj, ##__VA_ARGS__);
+
 class FullSnapshotWriter {
  public:
   static const intptr_t kInitialSize = 64 * KB;
@@ -446,6 +554,8 @@
   intptr_t mapped_data_size_;
   intptr_t mapped_text_size_;
 
+  V8SnapshotProfileWriter* profile_writer_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(FullSnapshotWriter);
 };
 
diff --git a/runtime/vm/code_patcher_arm64_test.cc b/runtime/vm/code_patcher_arm64_test.cc
index 113a7b8..c2437cf 100644
--- a/runtime/vm/code_patcher_arm64_test.cc
+++ b/runtime/vm/code_patcher_arm64_test.cc
@@ -44,7 +44,7 @@
   __ set_constant_pool_allowed(true);
 
   __ LoadObject(R5, ic_data);
-  __ BranchLinkPatchable(*StubCode::OneArgCheckInlineCache_entry());
+  __ BranchLinkPatchable(StubCode::OneArgCheckInlineCache());
   __ ret();
 }
 
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index 3e3ca0b..9463dae 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -44,7 +44,7 @@
   __ set_constant_pool_allowed(true);
 
   __ LoadObject(R9, ic_data);
-  __ BranchLinkPatchable(*StubCode::OneArgCheckInlineCache_entry());
+  __ BranchLinkPatchable(StubCode::OneArgCheckInlineCache());
   __ Ret();
 }
 
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index a843893..19e4563 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -41,7 +41,7 @@
       function, target_name, args_descriptor, 15, 1, ICData::kInstance));
 
   __ LoadObject(ECX, ic_data);
-  __ Call(*StubCode::OneArgCheckInlineCache_entry());
+  __ Call(StubCode::OneArgCheckInlineCache());
   __ ret();
 }
 
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index 90bd5f5..d6ac021 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -44,7 +44,7 @@
   __ set_constant_pool_allowed(true);
 
   __ LoadObject(RBX, ic_data);
-  __ CallPatchable(*StubCode::OneArgCheckInlineCache_entry());
+  __ CallPatchable(StubCode::OneArgCheckInlineCache());
   __ ret();
 }
 
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 216bdb5..d355960 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -9,6 +9,7 @@
 #include "vm/compiler/aot/aot_call_specializer.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/backend/block_scheduler.h"
 #include "vm/compiler/backend/branch_optimizer.h"
 #include "vm/compiler/backend/constant_propagator.h"
 #include "vm/compiler/backend/flow_graph.h"
@@ -824,94 +825,6 @@
   return parsed_function->function().raw();
 }
 
-RawObject* Precompiler::EvaluateStaticInitializer(const Field& field) {
-  ASSERT(field.is_static());
-  // The VM sets the field's value to transiton_sentinel prior to
-  // evaluating the initializer value.
-  ASSERT(field.StaticValue() == Object::transition_sentinel().raw());
-  LongJumpScope jump;
-  if (setjmp(*jump.Set()) == 0) {
-    // Under precompilation, the initializer may have already been compiled, in
-    // which case use it. Under lazy compilation or early in precompilation, the
-    // initializer has not yet been created, so create it now, but don't bother
-    // remembering it because it won't be used again.
-    Function& initializer = Function::Handle();
-    if (!field.HasPrecompiledInitializer()) {
-      initializer = CompileStaticInitializer(field);
-    } else {
-      initializer ^= field.PrecompiledInitializer();
-    }
-    // Invoke the function to evaluate the expression.
-    return DartEntry::InvokeFunction(initializer, Object::empty_array());
-  } else {
-    Thread* const thread = Thread::Current();
-    StackZone zone(thread);
-    const Error& error = Error::Handle(thread->zone(), thread->sticky_error());
-    thread->clear_sticky_error();
-    return error.raw();
-  }
-  UNREACHABLE();
-  return Object::null();
-}
-
-RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) {
-  LongJumpScope jump;
-  if (setjmp(*jump.Set()) == 0) {
-    Thread* const thread = Thread::Current();
-
-    // Create a dummy function object for the code generator.
-    // The function needs to be associated with a named Class: the interface
-    // Function fits the bill.
-    const char* kEvalConst = "eval_const";
-    const Function& func = Function::ZoneHandle(Function::New(
-        String::Handle(Symbols::New(thread, kEvalConst)),
-        RawFunction::kRegularFunction,
-        true,   // static function
-        false,  // not const function
-        false,  // not abstract
-        false,  // not external
-        false,  // not native
-        Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()),
-        fragment->token_pos()));
-
-    func.set_result_type(Object::dynamic_type());
-    func.set_num_fixed_parameters(0);
-    func.SetNumOptionalParameters(0, true);
-    // Manually generated AST, do not recompile.
-    func.SetIsOptimizable(false);
-    func.set_is_debuggable(false);
-
-    // We compile the function here, even though InvokeFunction() below
-    // would compile func automatically. We are checking fewer invariants
-    // here.
-    ParsedFunction* parsed_function = new ParsedFunction(thread, func);
-    parsed_function->SetNodeSequence(fragment);
-    fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp());
-    fragment->scope()->AddVariable(parsed_function->current_context_var());
-    parsed_function->AllocateVariables();
-
-    // Non-optimized code generator.
-    DartCompilationPipeline pipeline;
-    PrecompileParsedFunctionHelper helper(/* precompiler = */ NULL,
-                                          parsed_function,
-                                          /* optimized = */ false);
-    helper.Compile(&pipeline);
-    NOT_IN_PRODUCT(Code::Handle(func.unoptimized_code())
-                       .set_var_descriptors(Object::empty_var_descriptors()));
-
-    const Object& result = PassiveObject::Handle(
-        DartEntry::InvokeFunction(func, Object::empty_array()));
-    return result.raw();
-  } else {
-    Thread* const thread = Thread::Current();
-    const Object& result = PassiveObject::Handle(thread->sticky_error());
-    thread->clear_sticky_error();
-    return result.raw();
-  }
-  UNREACHABLE();
-  return Object::null();
-}
-
 void Precompiler::AddFunction(const Function& function) {
   if (enqueued_functions_.HasKey(&function)) return;
 
@@ -1019,20 +932,22 @@
     while (it.HasNext()) {
       cls = it.GetNextClass();
 
+      // Check for @pragma on the class itself.
       if (cls.has_pragma()) {
-        // Check for @pragma on the class itself.
         metadata ^= lib.GetMetadata(cls);
         if (metadata_defines_entrypoint() == EntryPointPragma::kAlways) {
           AddInstantiatedClass(cls);
         }
+      }
 
-        // Check for @pragma on any fields in the class.
-        members = cls.fields();
-        implicit_getters = GrowableObjectArray::New(members.Length());
-        implicit_setters = GrowableObjectArray::New(members.Length());
-        implicit_static_getters = GrowableObjectArray::New(members.Length());
-        for (intptr_t k = 0; k < members.Length(); ++k) {
-          field ^= members.At(k);
+      // Check for @pragma on any fields in the class.
+      members = cls.fields();
+      implicit_getters = GrowableObjectArray::New(members.Length());
+      implicit_setters = GrowableObjectArray::New(members.Length());
+      implicit_static_getters = GrowableObjectArray::New(members.Length());
+      for (intptr_t k = 0; k < members.Length(); ++k) {
+        field ^= members.At(k);
+        if (field.has_pragma()) {
           metadata ^= lib.GetMetadata(field);
           if (metadata.IsNull()) continue;
           EntryPointPragma pragma = metadata_defines_entrypoint();
@@ -1537,7 +1452,7 @@
   }
 
   ASSERT(Object::dynamic_type().type_test_stub_entry_point() !=
-         StubCode::DefaultTypeTest_entry()->EntryPoint());
+         StubCode::DefaultTypeTest().EntryPoint());
 }
 
 void Precompiler::DropTypes() {
@@ -2028,9 +1943,8 @@
           unlinked_.set_args_descriptor(args_descriptor_);
           unlinked_ = DedupUnlinkedCall(unlinked_);
           pool.SetObjectAt(i, unlinked_);
-        } else if (entry_.raw() ==
-                   StubCode::ICCallThroughFunction_entry()->code()) {
-          target_code_ = StubCode::UnlinkedCall_entry()->code();
+        } else if (entry_.raw() == StubCode::ICCallThroughFunction().raw()) {
+          target_code_ = StubCode::UnlinkedCall().raw();
           pool.SetObjectAt(i, target_code_);
         }
       }
@@ -2314,8 +2228,12 @@
         FlowGraphPrinter::PrintGraph("Unoptimized Compilation", flow_graph);
       }
 
+      BlockScheduler block_scheduler(flow_graph);
       CompilerPassState pass_state(thread(), flow_graph, &speculative_policy,
                                    precompiler_);
+      pass_state.block_scheduler = &block_scheduler;
+      pass_state.reorder_blocks =
+          FlowGraph::ShouldReorderBlocks(function, optimized());
       NOT_IN_PRODUCT(pass_state.compiler_timeline = compiler_timeline);
 
       if (optimized()) {
@@ -2604,7 +2522,7 @@
 // TODO(dartbug.com/30524) instead call to Obfuscator::Rename from a place
 // where these are looked up.
 #define PREVENT_RENAMING(class_name, function_name, recognized_enum,           \
-                         result_type, fingerprint)                             \
+                         fingerprint)                                          \
   do {                                                                         \
     PreventRenaming(#class_name);                                              \
     PreventRenaming(#function_name);                                           \
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 47ac594..7c4dacac 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -239,9 +239,6 @@
                                    Zone* zone,
                                    const Function& function);
 
-  static RawObject* EvaluateStaticInitializer(const Field& field);
-  static RawObject* ExecuteOnce(SequenceNode* fragment);
-
   static RawFunction* CompileStaticInitializer(const Field& field);
 
   // Returns true if get:runtimeType is not overloaded by any class.
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 320d6e3..2ca5b32 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -2522,13 +2522,12 @@
   vmulqs(qd, qn, qd);
 }
 
-void Assembler::Branch(const StubEntry& stub_entry,
+void Assembler::Branch(const Code& target,
                        ObjectPool::Patchability patchable,
                        Register pp,
                        Condition cond) {
-  const Code& target_code = Code::ZoneHandle(stub_entry.code());
   const int32_t offset = ObjectPool::element_offset(
-      object_pool_wrapper().FindObject(target_code, patchable));
+      object_pool_wrapper().FindObject(target, patchable));
   LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp, cond);
   Branch(FieldAddress(CODE_REG, Code::entry_point_offset()), cond);
 }
@@ -2551,12 +2550,6 @@
   blx(LR);  // Use blx instruction so that the return branch prediction works.
 }
 
-void Assembler::BranchLink(const StubEntry& stub_entry,
-                           ObjectPool::Patchability patchable) {
-  const Code& code = Code::ZoneHandle(stub_entry.code());
-  BranchLink(code, patchable);
-}
-
 void Assembler::BranchLinkPatchable(const Code& target,
                                     Code::EntryKind entry_kind) {
   BranchLink(target, ObjectPool::kPatchable, entry_kind);
@@ -2576,10 +2569,9 @@
   blx(LR);
 }
 
-void Assembler::BranchLinkWithEquivalence(const StubEntry& stub_entry,
+void Assembler::BranchLinkWithEquivalence(const Code& target,
                                           const Object& equivalence,
                                           Code::EntryKind entry_kind) {
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   // Make sure that class CallPattern is able to patch the label referred
   // to by this code sequence.
   // For added code robustness, use 'blx lr' in a patchable sequence and
@@ -2596,11 +2588,6 @@
   blx(LR);  // Use blx instruction so that the return branch prediction works.
 }
 
-void Assembler::BranchLinkPatchable(const StubEntry& stub_entry,
-                                    Code::EntryKind entry_kind) {
-  BranchLinkPatchable(Code::ZoneHandle(stub_entry.code()), entry_kind);
-}
-
 void Assembler::BranchLinkOffset(Register base, int32_t offset) {
   ASSERT(base != PC);
   ASSERT(base != IP);
@@ -3418,7 +3405,8 @@
     PushList((1 << R0) | (1 << IP) | (1 << LR));  // Preserve R0, IP, LR.
     LoadImmediate(R0, reinterpret_cast<int32_t>(message));
     // PrintStopMessage() preserves all registers.
-    BranchLink(&StubCode::PrintStopMessage_entry()->label());
+    ExternalLabel label(StubCode::PrintStopMessage().EntryPoint());
+    BranchLink(&label);
     PopList((1 << R0) | (1 << IP) | (1 << LR));  // Restore R0, IP, LR.
   }
   bkpt(Instr::kStopMessageCode);
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 801f1c3..b4c35c9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -21,7 +21,6 @@
 
 // Forward declarations.
 class RuntimeEntry;
-class StubEntry;
 class RegisterSet;
 
 // Instruction encoding bits.
@@ -656,7 +655,7 @@
   void bx(Register rm, Condition cond = AL);
   void blx(Register rm, Condition cond = AL);
 
-  void Branch(const StubEntry& stub_entry,
+  void Branch(const Code& code,
               ObjectPool::Patchability patchable = ObjectPool::kNotPatchable,
               Register pp = PP,
               Condition cond = AL);
@@ -664,28 +663,22 @@
   void Branch(const Address& address, Condition cond = AL);
 
   void BranchLink(
-      const StubEntry& stub_entry,
-      ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
-  void BranchLink(const Code& code,
-                  ObjectPool::Patchability patchable,
-                  Code::EntryKind entry_kind = Code::EntryKind::kNormal);
+      const Code& code,
+      ObjectPool::Patchability patchable = ObjectPool::kNotPatchable,
+      Code::EntryKind entry_kind = Code::EntryKind::kNormal);
   void BranchLinkToRuntime();
 
   void CallNullErrorShared(bool save_fpu_registers);
 
   // Branch and link to an entry address. Call sequence can be patched.
   void BranchLinkPatchable(
-      const StubEntry& stub_entry,
-      Code::EntryKind entry_kind = Code::EntryKind::kNormal);
-
-  void BranchLinkPatchable(
       const Code& code,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
   // Emit a call that shares its object pool entries with other calls
   // that have the same equivalence marker.
   void BranchLinkWithEquivalence(
-      const StubEntry& stub_entry,
+      const Code& code,
       const Object& equivalence,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 5780bbd..b76aad5 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -626,10 +626,9 @@
   }
 }
 
-void Assembler::Branch(const StubEntry& stub_entry,
+void Assembler::Branch(const Code& target,
                        Register pp,
                        ObjectPool::Patchability patchable) {
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper().FindObject(target, patchable));
   LoadWordFromPoolOffset(CODE_REG, offset, pp);
@@ -637,13 +636,12 @@
   br(TMP);
 }
 
-void Assembler::BranchPatchable(const StubEntry& stub_entry) {
-  Branch(stub_entry, PP, ObjectPool::kPatchable);
+void Assembler::BranchPatchable(const Code& code) {
+  Branch(code, PP, ObjectPool::kPatchable);
 }
 
-void Assembler::BranchLink(const StubEntry& stub_entry,
+void Assembler::BranchLink(const Code& target,
                            ObjectPool::Patchability patchable) {
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper().FindObject(target, patchable));
   LoadWordFromPoolOffset(CODE_REG, offset);
@@ -651,18 +649,13 @@
   blr(TMP);
 }
 
-void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
-  BranchLink(stub_entry, ObjectPool::kPatchable);
-}
-
 void Assembler::BranchLinkToRuntime() {
   ldr(LR, Address(THR, Thread::call_to_runtime_entry_point_offset()));
   blr(LR);
 }
 
-void Assembler::BranchLinkWithEquivalence(const StubEntry& stub_entry,
+void Assembler::BranchLinkWithEquivalence(const Code& target,
                                           const Object& equivalence) {
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const int32_t offset = ObjectPool::element_offset(
       object_pool_wrapper().FindObject(target, equivalence));
   LoadWordFromPoolOffset(CODE_REG, offset);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 761ec23..4d3d69a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -21,7 +21,6 @@
 
 // Forward declarations.
 class RuntimeEntry;
-class StubEntry;
 class RegisterSet;
 
 class Immediate : public ValueObject {
@@ -1350,24 +1349,25 @@
 
   void BranchIfSmi(Register reg, Label* label) { tbz(label, reg, kSmiTag); }
 
-  void Branch(const StubEntry& stub_entry,
+  void Branch(const Code& code,
               Register pp,
               ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
-  void BranchPatchable(const StubEntry& stub_entry);
+  void BranchPatchable(const Code& code);
 
   void BranchLink(
-      const StubEntry& stub_entry,
+      const Code& code,
       ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
 
-  void BranchLinkPatchable(const StubEntry& stub_entry);
+  void BranchLinkPatchable(const Code& code) {
+    BranchLink(code, ObjectPool::kPatchable);
+  }
   void BranchLinkToRuntime();
 
   void CallNullErrorShared(bool save_fpu_registers);
 
   // Emit a call that shares its object pool entries with other calls
   // that have the same equivalence marker.
-  void BranchLinkWithEquivalence(const StubEntry& stub_entry,
-                                 const Object& equivalence);
+  void BranchLinkWithEquivalence(const Code& code, const Object& equivalence);
 
   void AddImmediate(Register dest, int64_t imm) {
     AddImmediate(dest, dest, imm);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index a936849..97823b4 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2132,8 +2132,7 @@
   entry.Call(this, argument_count);
 }
 
-void Assembler::Call(const StubEntry& stub_entry, bool movable_target) {
-  const Code& target = Code::ZoneHandle(stub_entry.code());
+void Assembler::Call(const Code& target, bool movable_target) {
   LoadObject(CODE_REG, target, movable_target);
   call(FieldAddress(CODE_REG, Code::entry_point_offset()));
 }
@@ -2142,13 +2141,13 @@
   call(Address(THR, Thread::call_to_runtime_entry_point_offset()));
 }
 
-void Assembler::Jmp(const StubEntry& stub_entry) {
-  const ExternalLabel label(stub_entry.EntryPoint());
+void Assembler::Jmp(const Code& target) {
+  const ExternalLabel label(target.EntryPoint());
   jmp(&label);
 }
 
-void Assembler::J(Condition condition, const StubEntry& stub_entry) {
-  const ExternalLabel label(stub_entry.EntryPoint());
+void Assembler::J(Condition condition, const Code& target) {
+  const ExternalLabel label(target.EntryPoint());
   j(condition, &label);
 }
 
@@ -2368,8 +2367,8 @@
   if (FLAG_print_stop_message) {
     pushl(EAX);  // Preserve EAX.
     movl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
-    Call(*StubCode::PrintStopMessage_entry());  // Passing message in EAX.
-    popl(EAX);                                  // Restore EAX.
+    Call(StubCode::PrintStopMessage());  // Passing message in EAX.
+    popl(EAX);                           // Restore EAX.
   }
   // Emit the int3 instruction.
   int3();  // Execution can be resumed with the 'cont' command in gdb.
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 4c4854c..9fcc3eb 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -18,7 +18,6 @@
 
 // Forward declarations.
 class RuntimeEntry;
-class StubEntry;
 
 class Immediate : public ValueObject {
  public:
@@ -650,13 +649,13 @@
 
   void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
 
-  void Call(const StubEntry& stub_entry, bool movable_target = false);
+  void Call(const Code& code, bool movable_target = false);
   void CallToRuntime();
 
   void CallNullErrorShared(bool save_fpu_registers) { UNREACHABLE(); }
 
-  void Jmp(const StubEntry& stub_entry);
-  void J(Condition condition, const StubEntry& stub_entry);
+  void Jmp(const Code& code);
+  void J(Condition condition, const Code& code);
 
   /*
    * Loading and comparing classes of objects.
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 26a220a..cd3206c 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -58,10 +58,8 @@
   call(TMP);
 }
 
-void Assembler::CallPatchable(const StubEntry& stub_entry,
-                              Code::EntryKind entry_kind) {
+void Assembler::CallPatchable(const Code& target, Code::EntryKind entry_kind) {
   ASSERT(constant_pool_allowed());
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const intptr_t idx =
       object_pool_wrapper().AddObject(target, ObjectPool::kPatchable);
   const int32_t offset = ObjectPool::element_offset(idx);
@@ -69,20 +67,18 @@
   call(FieldAddress(CODE_REG, Code::entry_point_offset(entry_kind)));
 }
 
-void Assembler::CallWithEquivalence(const StubEntry& stub_entry,
+void Assembler::CallWithEquivalence(const Code& target,
                                     const Object& equivalence,
                                     Code::EntryKind entry_kind) {
   ASSERT(constant_pool_allowed());
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const intptr_t idx = object_pool_wrapper().FindObject(target, equivalence);
   const int32_t offset = ObjectPool::element_offset(idx);
   LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag);
   call(FieldAddress(CODE_REG, Code::entry_point_offset(entry_kind)));
 }
 
-void Assembler::Call(const StubEntry& stub_entry) {
+void Assembler::Call(const Code& target) {
   ASSERT(constant_pool_allowed());
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const intptr_t idx =
       object_pool_wrapper().FindObject(target, ObjectPool::kNotPatchable);
   const int32_t offset = ObjectPool::element_offset(idx);
@@ -878,13 +874,11 @@
   }
 }
 
-void Assembler::J(Condition condition,
-                  const StubEntry& stub_entry,
-                  Register pp) {
+void Assembler::J(Condition condition, const Code& target, Register pp) {
   Label no_jump;
   // Negate condition.
   j(static_cast<Condition>(condition ^ 1), &no_jump, kNearJump);
-  Jmp(stub_entry, pp);
+  Jmp(target, pp);
   Bind(&no_jump);
 }
 
@@ -921,9 +915,8 @@
   jmp(TMP);
 }
 
-void Assembler::JmpPatchable(const StubEntry& stub_entry, Register pp) {
+void Assembler::JmpPatchable(const Code& target, Register pp) {
   ASSERT((pp != PP) || constant_pool_allowed());
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const intptr_t idx =
       object_pool_wrapper().AddObject(target, ObjectPool::kPatchable);
   const int32_t offset = ObjectPool::element_offset(idx);
@@ -932,9 +925,8 @@
   jmp(TMP);
 }
 
-void Assembler::Jmp(const StubEntry& stub_entry, Register pp) {
+void Assembler::Jmp(const Code& target, Register pp) {
   ASSERT((pp != PP) || constant_pool_allowed());
-  const Code& target = Code::ZoneHandle(stub_entry.code());
   const intptr_t idx =
       object_pool_wrapper().FindObject(target, ObjectPool::kNotPatchable);
   const int32_t offset = ObjectPool::element_offset(idx);
@@ -1401,7 +1393,8 @@
     pushq(TMP);  // Preserve TMP register.
     pushq(RDI);  // Preserve RDI register.
     LoadImmediate(RDI, Immediate(message_address));
-    call(&StubCode::PrintStopMessage_entry()->label());
+    ExternalLabel label(StubCode::PrintStopMessage().EntryPoint());
+    call(&label);
     popq(RDI);  // Restore RDI register.
     popq(TMP);  // Restore TMP register.
   }
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 0d6e3cf..dc61bb9 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -20,7 +20,6 @@
 
 // Forward declarations.
 class RuntimeEntry;
-class StubEntry;
 
 class Immediate : public ValueObject {
  public:
@@ -628,7 +627,7 @@
   void jmp(const Address& address) { EmitUnaryL(address, 0xFF, 4); }
   void jmp(Label* label, bool near = kFarJump);
   void jmp(const ExternalLabel* label);
-  void jmp(const StubEntry& stub_entry);
+  void jmp(const Code& code);
 
   // Issue memory to memory move through a TMP register.
   // TODO(koda): Assert that these are not used for heap objects.
@@ -689,12 +688,12 @@
   void LoadFunctionFromCalleePool(Register dst,
                                   const Function& function,
                                   Register new_pp);
-  void JmpPatchable(const StubEntry& stub_entry, Register pp);
-  void Jmp(const StubEntry& stub_entry, Register pp = PP);
-  void J(Condition condition, const StubEntry& stub_entry, Register pp);
-  void CallPatchable(const StubEntry& stub_entry,
+  void JmpPatchable(const Code& code, Register pp);
+  void Jmp(const Code& code, Register pp = PP);
+  void J(Condition condition, const Code& code, Register pp);
+  void CallPatchable(const Code& code,
                      Code::EntryKind entry_kind = Code::EntryKind::kNormal);
-  void Call(const StubEntry& stub_entry);
+  void Call(const Code& stub_entry);
   void CallToRuntime();
 
   void CallNullErrorShared(bool save_fpu_registers);
@@ -702,7 +701,7 @@
   // Emit a call that shares its object pool entries with other calls
   // that have the same equivalence marker.
   void CallWithEquivalence(
-      const StubEntry& stub_entry,
+      const Code& code,
       const Object& equivalence,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
diff --git a/runtime/vm/compiler/backend/block_scheduler.cc b/runtime/vm/compiler/backend/block_scheduler.cc
index 24dc895..451c824 100644
--- a/runtime/vm/compiler/backend/block_scheduler.cc
+++ b/runtime/vm/compiler/backend/block_scheduler.cc
@@ -55,6 +55,9 @@
   if (!FLAG_reorder_basic_blocks) {
     return;
   }
+  if (FLAG_precompiled_mode) {
+    return;
+  }
 
   const Array& ic_data_array =
       Array::Handle(flow_graph()->zone(),
@@ -155,6 +158,18 @@
 }
 
 void BlockScheduler::ReorderBlocks() const {
+  if (FLAG_precompiled_mode) {
+    ReorderBlocksAOT();
+  } else {
+    ReorderBlocksJIT();
+  }
+}
+
+void BlockScheduler::ReorderBlocksJIT() const {
+  if (!FLAG_reorder_basic_blocks) {
+    return;
+  }
+
   // Add every block to a chain of length 1 and compute a list of edges
   // sorted by weight.
   intptr_t block_count = flow_graph()->preorder().length();
@@ -215,6 +230,68 @@
   }
 }
 
+// Moves blocks ending in a throw/rethrow, as well as any block post-dominated
+// by such a throwing block, to the end.
+void BlockScheduler::ReorderBlocksAOT() const {
+  if (!FLAG_reorder_basic_blocks) {
+    return;
+  }
+
+  auto& reverse_postorder = flow_graph()->reverse_postorder();
+  const intptr_t block_count = reverse_postorder.length();
+  GrowableArray<bool> is_terminating(block_count);
+  is_terminating.FillWith(false, 0, block_count);
+
+  // Any block in the worklist is marked and any of its unconditional
+  // predecessors need to be marked as well.
+  GrowableArray<BlockEntryInstr*> worklist;
+
+  // Add all throwing blocks to the worklist.
+  for (intptr_t i = 0; i < block_count; ++i) {
+    auto block = reverse_postorder[i];
+    auto last = block->last_instruction();
+    if (last->IsThrow() || last->IsReThrow()) {
+      const intptr_t preorder_nr = block->preorder_number();
+      is_terminating[preorder_nr] = true;
+      worklist.Add(block);
+    }
+  }
+
+  // Follow all indirect predecessors which unconditionally will end up in a
+  // throwing block.
+  while (worklist.length() > 0) {
+    auto block = worklist.RemoveLast();
+    for (intptr_t i = 0; i < block->PredecessorCount(); ++i) {
+      auto predecessor = block->PredecessorAt(i);
+      if (predecessor->last_instruction()->IsGoto()) {
+        const intptr_t preorder_nr = predecessor->preorder_number();
+        if (!is_terminating[preorder_nr]) {
+          is_terminating[preorder_nr] = true;
+          worklist.Add(predecessor);
+        }
+      }
+    }
+  }
+
+  // Emit code in reverse postorder but move any throwing blocks to the very
+  // end.
+  auto& codegen_order = *flow_graph()->CodegenBlockOrder(true);
+  for (intptr_t i = 0; i < block_count; ++i) {
+    auto block = reverse_postorder[i];
+    const intptr_t preorder_nr = block->preorder_number();
+    if (!is_terminating[preorder_nr]) {
+      codegen_order.Add(block);
+    }
+  }
+  for (intptr_t i = 0; i < block_count; ++i) {
+    auto block = reverse_postorder[i];
+    const intptr_t preorder_nr = block->preorder_number();
+    if (is_terminating[preorder_nr]) {
+      codegen_order.Add(block);
+    }
+  }
+}
+
 }  // namespace dart
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/block_scheduler.h b/runtime/vm/compiler/backend/block_scheduler.h
index f1f1217..90308bc 100644
--- a/runtime/vm/compiler/backend/block_scheduler.h
+++ b/runtime/vm/compiler/backend/block_scheduler.h
@@ -18,10 +18,12 @@
   FlowGraph* flow_graph() const { return flow_graph_; }
 
   void AssignEdgeWeights() const;
-
   void ReorderBlocks() const;
 
  private:
+  void ReorderBlocksAOT() const;
+  void ReorderBlocksJIT() const;
+
   FlowGraph* const flow_graph_;
 };
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 01b1cc8..a156279 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -270,11 +270,11 @@
 bool FlowGraphCompiler::IsEmptyBlock(BlockEntryInstr* block) const {
   // Entry-points cannot be merged because they must have assembly
   // prologue emitted which should not be included in any block they jump to.
-  return !block->IsCatchBlockEntry() && !block->HasNonRedundantParallelMove() &&
+  return !block->IsGraphEntry() && !block->IsFunctionEntry() &&
+         !block->IsCatchBlockEntry() && !block->IsOsrEntry() &&
+         !block->IsIndirectEntry() && !block->HasNonRedundantParallelMove() &&
          block->next()->IsGoto() &&
-         !block->next()->AsGoto()->HasNonRedundantParallelMove() &&
-         !block->IsIndirectEntry() && !block->IsFunctionEntry() &&
-         !block->IsOsrEntry();
+         !block->next()->AsGoto()->HasNonRedundantParallelMove();
 }
 
 void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) {
@@ -706,7 +706,7 @@
 }
 
 void FlowGraphCompiler::AddPcRelativeCallStubTarget(const Code& stub_code) {
-  ASSERT(stub_code.IsZoneHandle());
+  ASSERT(stub_code.IsZoneHandle() || stub_code.IsReadOnlyHandle());
   ASSERT(!stub_code.IsNull());
   static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
       Code::kPcRelativeCall, assembler()->CodeSize(), NULL, &stub_code));
@@ -719,7 +719,7 @@
 }
 
 void FlowGraphCompiler::AddStubCallTarget(const Code& code) {
-  ASSERT(code.IsZoneHandle());
+  ASSERT(code.IsZoneHandle() || code.IsReadOnlyHandle());
   static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
       Code::kCallViaCode, assembler()->CodeSize(), NULL, &code));
 }
@@ -1208,10 +1208,10 @@
 #if !defined(TARGET_ARCH_DBC)
 void FlowGraphCompiler::GenerateCallWithDeopt(TokenPosition token_pos,
                                               intptr_t deopt_id,
-                                              const StubEntry& stub_entry,
+                                              const Code& stub,
                                               RawPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
-  GenerateCall(token_pos, stub_entry, kind, locs);
+  GenerateCall(token_pos, stub, kind, locs);
   const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
   if (is_optimizing()) {
     AddDeoptIndexAtCall(deopt_id_after);
@@ -1222,31 +1222,31 @@
   }
 }
 
-static const StubEntry* StubEntryFor(const ICData& ic_data, bool optimized) {
+static const Code& StubEntryFor(const ICData& ic_data, bool optimized) {
   switch (ic_data.NumArgsTested()) {
     case 1:
 #if defined(TARGET_ARCH_X64)
       if (ic_data.IsTrackingExactness()) {
         if (optimized) {
-          return StubCode::
-              OneArgOptimizedCheckInlineCacheWithExactnessCheck_entry();
+          return StubCode::OneArgOptimizedCheckInlineCacheWithExactnessCheck();
         } else {
-          return StubCode::OneArgCheckInlineCacheWithExactnessCheck_entry();
+          return StubCode::OneArgCheckInlineCacheWithExactnessCheck();
         }
       }
 #else
       // TODO(dartbug.com/34170) Port exactness tracking to other platforms.
       ASSERT(!ic_data.IsTrackingExactness());
 #endif
-      return optimized ? StubCode::OneArgOptimizedCheckInlineCache_entry()
-                       : StubCode::OneArgCheckInlineCache_entry();
+      return optimized ? StubCode::OneArgOptimizedCheckInlineCache()
+                       : StubCode::OneArgCheckInlineCache();
     case 2:
       ASSERT(!ic_data.IsTrackingExactness());
-      return optimized ? StubCode::TwoArgsOptimizedCheckInlineCache_entry()
-                       : StubCode::TwoArgsCheckInlineCache_entry();
+      return optimized ? StubCode::TwoArgsOptimizedCheckInlineCache()
+                       : StubCode::TwoArgsCheckInlineCache();
     default:
+      ic_data.Print();
       UNIMPLEMENTED();
-      return nullptr;
+      return Code::Handle();
   }
 }
 
@@ -1267,7 +1267,7 @@
     // Emit IC call that will count and thus may need reoptimization at
     // function entry.
     ASSERT(may_reoptimize() || flow_graph().IsCompiledForOsr());
-    EmitOptimizedInstanceCall(*StubEntryFor(ic_data, /*optimized=*/true),
+    EmitOptimizedInstanceCall(StubEntryFor(ic_data, /*optimized=*/true),
                               ic_data, deopt_id, token_pos, locs, entry_kind);
     return;
   }
@@ -1281,7 +1281,7 @@
     return;
   }
 
-  EmitInstanceCall(*StubEntryFor(ic_data, /*optimized=*/false), ic_data,
+  EmitInstanceCall(StubEntryFor(ic_data, /*optimized=*/false), ic_data,
                    deopt_id, token_pos, locs);
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index e7deb03..dd1cf66 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -444,24 +444,24 @@
                            LocationSummary* locs);
 
   void GenerateCall(TokenPosition token_pos,
-                    const StubEntry& stub_entry,
+                    const Code& stub,
                     RawPcDescriptors::Kind kind,
                     LocationSummary* locs);
 
   void GenerateCallWithDeopt(TokenPosition token_pos,
                              intptr_t deopt_id,
-                             const StubEntry& stub_entry,
+                             const Code& stub,
                              RawPcDescriptors::Kind kind,
                              LocationSummary* locs);
 
   void GeneratePatchableCall(TokenPosition token_pos,
-                             const StubEntry& stub_entry,
+                             const Code& stub,
                              RawPcDescriptors::Kind kind,
                              LocationSummary* locs);
 
   void GenerateDartCall(intptr_t deopt_id,
                         TokenPosition token_pos,
-                        const StubEntry& stub_entry,
+                        const Code& stub,
                         RawPcDescriptors::Kind kind,
                         LocationSummary* locs,
                         Code::EntryKind entry_kind = Code::EntryKind::kNormal);
@@ -528,14 +528,14 @@
                                      bool fall_through_if_inside = false);
 
   void EmitOptimizedInstanceCall(
-      const StubEntry& stub_entry,
+      const Code& stub,
       const ICData& ic_data,
       intptr_t deopt_id,
       TokenPosition token_pos,
       LocationSummary* locs,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
-  void EmitInstanceCall(const StubEntry& stub_entry,
+  void EmitInstanceCall(const Code& stub,
                         const ICData& ic_data,
                         intptr_t deopt_id,
                         TokenPosition token_pos,
@@ -937,7 +937,8 @@
           function(function_arg),
           code(code_arg) {
       ASSERT((function == NULL) || function->IsZoneHandle());
-      ASSERT((code == NULL) || code->IsZoneHandle());
+      ASSERT((code == NULL) || code->IsZoneHandle() ||
+             code->IsReadOnlyHandle());
     }
 
    private:
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 3e786a8..00c9618 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -209,19 +209,19 @@
   if (test_kind == kTestTypeOneArg) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
-    __ BranchLink(*StubCode::Subtype1TestCache_entry());
+    __ BranchLink(StubCode::Subtype1TestCache());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
-    __ BranchLink(*StubCode::Subtype2TestCache_entry());
+    __ BranchLink(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
     ASSERT(instantiator_type_arguments_reg == R2);
     ASSERT(function_type_arguments_reg == R1);
-    __ BranchLink(*StubCode::Subtype4TestCache_entry());
+    __ BranchLink(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
     ASSERT(instantiator_type_arguments_reg == R2);
     ASSERT(function_type_arguments_reg == R1);
-    __ BranchLink(*StubCode::Subtype6TestCache_entry());
+    __ BranchLink(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
   }
@@ -875,8 +875,8 @@
     }
     __ CompareImmediate(R3, GetOptimizationThreshold());
     ASSERT(function_reg == R8);
-    __ Branch(*StubCode::OptimizeFunction_entry(), ObjectPool::kNotPatchable,
-              new_pp, GE);
+    __ Branch(StubCode::OptimizeFunction(), ObjectPool::kNotPatchable, new_pp,
+              GE);
   }
   __ Comment("Enter frame");
   if (flow_graph().IsCompiledForOsr()) {
@@ -960,29 +960,29 @@
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const StubEntry& stub_entry,
+                                     const Code& stub,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ BranchLink(stub_entry);
+  __ BranchLink(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
-  AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
+  AddStubCallTarget(stub);
 }
 
 void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
-                                              const StubEntry& stub_entry,
+                                              const Code& stub,
                                               RawPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
-  __ BranchLinkPatchable(stub_entry);
+  __ BranchLinkPatchable(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
-                                         const StubEntry& stub_entry,
+                                         const Code& stub,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
-  __ BranchLinkPatchable(stub_entry, entry_kind);
+  __ BranchLinkPatchable(stub, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
 
@@ -996,8 +996,8 @@
   // call sites are never patched for breakpoints: the function is deoptimized
   // and the unoptimized code with IC calls for static calls is patched instead.
   ASSERT(is_optimizing());
-  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
-  __ BranchLinkWithEquivalence(stub_entry, target, entry_kind);
+  const auto& stub = StubCode::CallStaticFunction();
+  __ BranchLinkWithEquivalence(stub, target, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
 }
@@ -1033,7 +1033,7 @@
 #endif  // DEBUG
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
                                                   const ICData& ic_data,
                                                   intptr_t deopt_id,
                                                   TokenPosition token_pos,
@@ -1049,20 +1049,19 @@
 
   __ LoadObject(R8, parsed_function().function());
   __ LoadUniqueObject(R9, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs, entry_kind);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
+                   entry_kind);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
-void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitInstanceCall(const Code& stub,
                                          const ICData& ic_data,
                                          intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   __ LoadUniqueObject(R9, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
@@ -1115,8 +1114,7 @@
                                                    TokenPosition token_pos,
                                                    LocationSummary* locs) {
   ASSERT(ic_data.NumArgsTested() == 1);
-  const Code& initial_stub =
-      Code::ZoneHandle(StubCode::ICCallThroughFunction_entry()->code());
+  const Code& initial_stub = StubCode::ICCallThroughFunction();
 
   __ Comment("SwitchableCall");
   __ LoadFromOffset(kWord, R0, SP,
@@ -1137,10 +1135,10 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   const ICData& ic_data) {
-  const StubEntry* stub_entry =
+  const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R9, ic_data);
-  GenerateDartCall(deopt_id, token_pos, *stub_entry,
+  GenerateDartCall(deopt_id, token_pos, stub,
                    RawPcDescriptors::kUnoptStaticCall, locs);
   __ Drop(count_with_type_args);
 }
@@ -1177,11 +1175,9 @@
     __ Push(reg);
     __ PushObject(obj);
     if (is_optimizing()) {
-      __ BranchLinkPatchable(
-          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ BranchLinkPatchable(
-          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmp, we need Z computed).
@@ -1202,11 +1198,9 @@
     __ Push(left);
     __ Push(right);
     if (is_optimizing()) {
-      __ BranchLinkPatchable(
-          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ BranchLinkPatchable(
-          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmp, we need Z computed).
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 50ca711..82e5a82 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -204,19 +204,19 @@
   if (test_kind == kTestTypeOneArg) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
-    __ BranchLink(*StubCode::Subtype1TestCache_entry());
+    __ BranchLink(StubCode::Subtype1TestCache());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
-    __ BranchLink(*StubCode::Subtype2TestCache_entry());
+    __ BranchLink(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
     ASSERT(instantiator_type_arguments_reg == R1);
     ASSERT(function_type_arguments_reg == R2);
-    __ BranchLink(*StubCode::Subtype4TestCache_entry());
+    __ BranchLink(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
     ASSERT(instantiator_type_arguments_reg == R1);
     ASSERT(function_type_arguments_reg == R2);
-    __ BranchLink(*StubCode::Subtype6TestCache_entry());
+    __ BranchLink(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
   }
@@ -860,7 +860,7 @@
     ASSERT(function_reg == R6);
     Label dont_optimize;
     __ b(&dont_optimize, LT);
-    __ Branch(*StubCode::OptimizeFunction_entry(), new_pp);
+    __ Branch(StubCode::OptimizeFunction(), new_pp);
     __ Bind(&dont_optimize);
   }
   __ Comment("Enter frame");
@@ -936,30 +936,30 @@
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const StubEntry& stub_entry,
+                                     const Code& stub,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ BranchLink(stub_entry);
+  __ BranchLink(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
-  AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
+  AddStubCallTarget(stub);
 }
 
 void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
-                                              const StubEntry& stub_entry,
+                                              const Code& stub,
                                               RawPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
-  __ BranchLinkPatchable(stub_entry);
+  __ BranchLinkPatchable(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
-                                         const StubEntry& stub_entry,
+                                         const Code& stub,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
   // TODO(sjindel/entrypoints): Support multiple entrypoints on ARM64.
-  __ BranchLinkPatchable(stub_entry);
+  __ BranchLinkPatchable(stub);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
 
@@ -974,8 +974,8 @@
   // call sites are never patched for breakpoints: the function is deoptimized
   // and the unoptimized code with IC calls for static calls is patched instead.
   ASSERT(is_optimizing());
-  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
-  __ BranchLinkWithEquivalence(stub_entry, target);
+  const Code& stub = StubCode::CallStaticFunction();
+  __ BranchLinkWithEquivalence(stub, target);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
 }
@@ -1004,7 +1004,7 @@
   __ StoreFieldToOffset(TMP, R0, Array::element_offset(edge_id));
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
                                                   const ICData& ic_data,
                                                   intptr_t deopt_id,
                                                   TokenPosition token_pos,
@@ -1021,20 +1021,18 @@
 
   __ LoadObject(R6, parsed_function().function());
   __ LoadUniqueObject(R5, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
-void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitInstanceCall(const Code& stub,
                                          const ICData& ic_data,
                                          intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   __ LoadUniqueObject(R5, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
@@ -1088,8 +1086,7 @@
                                                    TokenPosition token_pos,
                                                    LocationSummary* locs) {
   ASSERT(ic_data.NumArgsTested() == 1);
-  const Code& initial_stub =
-      Code::ZoneHandle(StubCode::ICCallThroughFunction_entry()->code());
+  const Code& initial_stub = StubCode::ICCallThroughFunction();
 
   auto& op = __ object_pool_wrapper();
 
@@ -1118,10 +1115,10 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   const ICData& ic_data) {
-  const StubEntry* stub_entry =
+  const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R5, ic_data);
-  GenerateDartCall(deopt_id, token_pos, *stub_entry,
+  GenerateDartCall(deopt_id, token_pos, stub,
                    RawPcDescriptors::kUnoptStaticCall, locs);
   __ Drop(count_with_type_args);
 }
@@ -1159,11 +1156,9 @@
     __ Push(reg);
     __ PushObject(obj);
     if (is_optimizing()) {
-      __ BranchLinkPatchable(
-          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ BranchLinkPatchable(
-          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmp, we need Z computed).
@@ -1184,11 +1179,9 @@
     __ Push(left);
     __ Push(right);
     if (is_optimizing()) {
-      __ BranchLinkPatchable(
-          *StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ BranchLinkPatchable(
-          *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmp, we need Z computed).
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 2b1f13a..c60cdb3 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -166,7 +166,7 @@
 
   ASSERT(deopt_env() != NULL);
   __ pushl(CODE_REG);
-  __ Call(*StubCode::Deoptimize_entry());
+  __ Call(StubCode::Deoptimize());
   set_pc_offset(assembler->CodeSize());
   __ int3();
 #undef __
@@ -210,21 +210,21 @@
     ASSERT(function_type_arguments_reg == kNoRegister);
     __ pushl(raw_null);
     __ pushl(raw_null);
-    __ Call(*StubCode::Subtype1TestCache_entry());
+    __ Call(StubCode::Subtype1TestCache());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
     __ pushl(raw_null);
     __ pushl(raw_null);
-    __ Call(*StubCode::Subtype2TestCache_entry());
+    __ Call(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
     __ pushl(instantiator_type_arguments_reg);
     __ pushl(function_type_arguments_reg);
-    __ Call(*StubCode::Subtype4TestCache_entry());
+    __ Call(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
     __ pushl(instantiator_type_arguments_reg);
     __ pushl(function_type_arguments_reg);
-    __ Call(*StubCode::Subtype6TestCache_entry());
+    __ Call(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
   }
@@ -799,7 +799,7 @@
     __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()),
             Immediate(GetOptimizationThreshold()));
     ASSERT(function_reg == EBX);
-    __ J(GREATER_EQUAL, *StubCode::OptimizeFunction_entry());
+    __ J(GREATER_EQUAL, StubCode::OptimizeFunction());
   }
   __ Comment("Enter frame");
   if (flow_graph().IsCompiledForOsr()) {
@@ -855,22 +855,22 @@
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const StubEntry& stub_entry,
+                                     const Code& stub,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ Call(stub_entry);
+  __ Call(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
-  AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
+  AddStubCallTarget(stub);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
-                                         const StubEntry& stub_entry,
+                                         const Code& stub,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
   // TODO(sjindel/entrypoints): Support multiple entrypoints on IA32.
-  __ Call(stub_entry);
+  __ Call(stub);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
 
@@ -881,8 +881,8 @@
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
   // TODO(sjindel/entrypoints): Support multiple entrypoints on IA32.
-  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
-  __ Call(stub_entry, true /* movable_target */);
+  const auto& stub = StubCode::CallStaticFunction();
+  __ Call(stub, true /* movable_target */);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
 }
@@ -901,10 +901,10 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   const ICData& ic_data) {
-  const StubEntry& stub_entry =
-      *StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
+  const Code& stub =
+      StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(ECX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry,
+  GenerateDartCall(deopt_id, token_pos, stub,
                    RawPcDescriptors::kUnoptStaticCall, locs);
   __ Drop(count_with_type_args);
 }
@@ -921,7 +921,7 @@
   __ IncrementSmiField(FieldAddress(EAX, Array::element_offset(edge_id)), 1);
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
                                                   const ICData& ic_data,
                                                   intptr_t deopt_id,
                                                   TokenPosition token_pos,
@@ -937,20 +937,18 @@
   // Pass the function explicitly, it is used in IC stub.
   __ LoadObject(EBX, parsed_function().function());
   __ LoadObject(ECX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
-void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitInstanceCall(const Code& stub,
                                          const ICData& ic_data,
                                          intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
   __ LoadObject(ECX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs());
 }
 
@@ -1038,9 +1036,9 @@
     __ pushl(reg);
     __ PushObject(obj);
     if (is_optimizing()) {
-      __ Call(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ Call(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ Call(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ Call(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmpl, we need ZF computed).
@@ -1061,9 +1059,9 @@
     __ pushl(left);
     __ pushl(right);
     if (is_optimizing()) {
-      __ Call(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ Call(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ Call(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ Call(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmpl, we need ZF computed).
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 45a5f13..579e9f1 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -209,19 +209,19 @@
   if (test_kind == kTestTypeOneArg) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
-    __ Call(*StubCode::Subtype1TestCache_entry());
+    __ Call(StubCode::Subtype1TestCache());
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(instantiator_type_arguments_reg == kNoRegister);
     ASSERT(function_type_arguments_reg == kNoRegister);
-    __ Call(*StubCode::Subtype2TestCache_entry());
+    __ Call(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
     ASSERT(RDX == instantiator_type_arguments_reg);
     ASSERT(RCX == function_type_arguments_reg);
-    __ Call(*StubCode::Subtype4TestCache_entry());
+    __ Call(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
     ASSERT(RDX == instantiator_type_arguments_reg);
     ASSERT(RCX == function_type_arguments_reg);
-    __ Call(*StubCode::Subtype6TestCache_entry());
+    __ Call(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
   }
@@ -875,7 +875,7 @@
       __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()),
               Immediate(GetOptimizationThreshold()));
       ASSERT(function_reg == RDI);
-      __ J(GREATER_EQUAL, *StubCode::OptimizeFunction_entry(), new_pp);
+      __ J(GREATER_EQUAL, StubCode::OptimizeFunction(), new_pp);
     }
     ASSERT(StackSize() >= 0);
     __ Comment("Enter frame");
@@ -951,29 +951,29 @@
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const StubEntry& stub_entry,
+                                     const Code& stub,
                                      RawPcDescriptors::Kind kind,
                                      LocationSummary* locs) {
-  __ Call(stub_entry);
+  __ Call(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
-  AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
+  AddStubCallTarget(stub);
 }
 
 void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
-                                              const StubEntry& stub_entry,
+                                              const Code& stub,
                                               RawPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
-  __ CallPatchable(stub_entry);
+  __ CallPatchable(stub);
   EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
                                          TokenPosition token_pos,
-                                         const StubEntry& stub_entry,
+                                         const Code& stub,
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
-  __ CallPatchable(stub_entry, entry_kind);
+  __ CallPatchable(stub, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
 
@@ -987,7 +987,7 @@
   // call sites are never patched for breakpoints: the function is deoptimized
   // and the unoptimized code with IC calls for static calls is patched instead.
   ASSERT(is_optimizing());
-  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
+  const auto& stub_entry = StubCode::CallStaticFunction();
   __ CallWithEquivalence(stub_entry, target, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
@@ -1007,10 +1007,10 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   const ICData& ic_data) {
-  const StubEntry* stub_entry =
+  const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(RBX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, *stub_entry,
+  GenerateDartCall(deopt_id, token_pos, stub,
                    RawPcDescriptors::kUnoptStaticCall, locs);
   __ Drop(count_with_type_args, RCX);
 }
@@ -1028,7 +1028,7 @@
   __ IncrementSmiField(FieldAddress(RAX, Array::element_offset(edge_id)), 1);
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
                                                   const ICData& ic_data,
                                                   intptr_t deopt_id,
                                                   TokenPosition token_pos,
@@ -1043,20 +1043,19 @@
   // Pass the function explicitly, it is used in IC stub.
   __ LoadObject(RDI, parsed_function().function());
   __ LoadUniqueObject(RBX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs, entry_kind);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs,
+                   entry_kind);
   __ Drop(ic_data.CountWithTypeArgs(), RCX);
 }
 
-void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
+void FlowGraphCompiler::EmitInstanceCall(const Code& stub,
                                          const ICData& ic_data,
                                          intptr_t deopt_id,
                                          TokenPosition token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   __ LoadUniqueObject(RBX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
-                   locs);
+  GenerateDartCall(deopt_id, token_pos, stub, RawPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.CountWithTypeArgs(), RCX);
 }
 
@@ -1107,8 +1106,7 @@
                                                    TokenPosition token_pos,
                                                    LocationSummary* locs) {
   ASSERT(ic_data.NumArgsTested() == 1);
-  const Code& initial_stub =
-      Code::ZoneHandle(StubCode::ICCallThroughFunction_entry()->code());
+  const Code& initial_stub = StubCode::ICCallThroughFunction();
 
   __ Comment("SwitchableCall");
   __ movq(RDI, Address(RSP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
@@ -1161,9 +1159,9 @@
     __ pushq(reg);
     __ PushObject(obj);
     if (is_optimizing()) {
-      __ CallPatchable(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ CallPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ CallPatchable(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ CallPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmpq, we need ZF computed).
@@ -1184,9 +1182,9 @@
     __ pushq(left);
     __ pushq(right);
     if (is_optimizing()) {
-      __ CallPatchable(*StubCode::OptimizedIdenticalWithNumberCheck_entry());
+      __ CallPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
     } else {
-      __ CallPatchable(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
+      __ CallPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
     AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
     // Stub returns result in flags (result of a cmpq, we need ZF computed).
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index ad4cd91..b8a44ec 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -3917,19 +3917,19 @@
 
 // DBC does not use specialized inline cache stubs for smi operations.
 #if !defined(TARGET_ARCH_DBC)
-static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
+static RawCode* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
   if (!FLAG_two_args_smi_icd) {
-    return 0;
+    return Code::null();
   }
   switch (kind) {
     case Token::kADD:
-      return StubCode::SmiAddInlineCache_entry();
+      return StubCode::SmiAddInlineCache().raw();
     case Token::kSUB:
-      return StubCode::SmiSubInlineCache_entry();
+      return StubCode::SmiSubInlineCache().raw();
     case Token::kEQ:
-      return StubCode::SmiEqualInlineCache_entry();
+      return StubCode::SmiEqualInlineCache().raw();
     default:
-      return NULL;
+      return Code::null();
   }
 }
 #else
@@ -4037,16 +4037,17 @@
     compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(),
                                    token_pos());
     bool is_smi_two_args_op = false;
-    const StubEntry* stub_entry = TwoArgsSmiOpInlineCacheEntry(token_kind());
-    if (stub_entry != nullptr) {
+    const Code& stub =
+        Code::ZoneHandle(TwoArgsSmiOpInlineCacheEntry(token_kind()));
+    if (!stub.IsNull()) {
       // We have a dedicated inline cache stub for this operation, add an
       // an initial Smi/Smi check with count 0.
       is_smi_two_args_op = call_ic_data->AddSmiSmiCheckForFastSmiStubs();
     }
     if (is_smi_two_args_op) {
       ASSERT(ArgumentCount() == 2);
-      compiler->EmitInstanceCall(*stub_entry, *call_ic_data, deopt_id(),
-                                 token_pos(), locs());
+      compiler->EmitInstanceCall(stub, *call_ic_data, deopt_id(), token_pos(),
+                                 locs());
     } else {
       compiler->GenerateInstanceCall(deopt_id(), token_pos(), locs(),
                                      *call_ic_data);
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 4051382..cc806de 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -1977,8 +1977,6 @@
   virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
 };
 
-class InductionVariableInfo;
-
 class PhiInstr : public Definition {
  public:
   PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
@@ -1986,7 +1984,6 @@
         inputs_(num_inputs),
         representation_(kTagged),
         reaching_defs_(NULL),
-        loop_variable_info_(NULL),
         is_alive_(false),
         is_receiver_(kUnknownReceiver) {
     for (intptr_t i = 0; i < num_inputs; ++i) {
@@ -2042,14 +2039,6 @@
   // A phi is redundant if all input operands are the same.
   bool IsRedundant() const;
 
-  void set_induction_variable_info(InductionVariableInfo* info) {
-    loop_variable_info_ = info;
-  }
-
-  InductionVariableInfo* induction_variable_info() {
-    return loop_variable_info_;
-  }
-
   PRINT_TO_SUPPORT
 
   enum ReceiverType { kUnknownReceiver = -1, kNotReceiver = 0, kReceiver = 1 };
@@ -2071,7 +2060,6 @@
   GrowableArray<Value*> inputs_;
   Representation representation_;
   BitVector* reaching_defs_;
-  InductionVariableInfo* loop_variable_info_;
   bool is_alive_;
   int8_t is_receiver_;
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 0026a95..3bc424f 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -941,14 +941,14 @@
   // into the runtime system.
   uword entry;
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
-  const StubEntry* stub_entry;
+  const Code* stub;
   if (link_lazily()) {
-    stub_entry = StubCode::CallBootstrapNative_entry();
+    stub = &StubCode::CallBootstrapNative();
     entry = NativeEntry::LinkNativeCallEntry();
   } else {
     entry = reinterpret_cast<uword>(native_c_function());
     if (is_bootstrap_native()) {
-      stub_entry = StubCode::CallBootstrapNative_entry();
+      stub = &StubCode::CallBootstrapNative();
 #if defined(USING_SIMULATOR)
       entry = Simulator::RedirectExternalReference(
           entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
@@ -957,12 +957,12 @@
       // In the case of non bootstrap native methods the CallNativeCFunction
       // stub generates the redirection address when running under the simulator
       // and hence we do not change 'entry' here.
-      stub_entry = StubCode::CallAutoScopeNative_entry();
+      stub = &StubCode::CallAutoScopeNative();
     } else {
       // In the case of non bootstrap native methods the CallNativeCFunction
       // stub generates the redirection address when running under the simulator
       // and hence we do not change 'entry' here.
-      stub_entry = StubCode::CallNoScopeNative_entry();
+      stub = &StubCode::CallNoScopeNative();
     }
   }
   __ LoadImmediate(R1, argc_tag);
@@ -971,10 +971,10 @@
       R9, &label,
       link_lazily() ? ObjectPool::kPatchable : ObjectPool::kNotPatchable);
   if (link_lazily()) {
-    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+    compiler->GeneratePatchableCall(token_pos(), *stub,
                                     RawPcDescriptors::kOther, locs());
   } else {
-    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+    compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther,
                            locs());
   }
   __ Pop(result);
@@ -2019,7 +2019,6 @@
     __ Bind(entry_label());
     const Code& stub = Code::ZoneHandle(
         compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
-    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction()->locs();
 
@@ -2027,7 +2026,7 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(TokenPosition::kNoSource,  // No token position.
-                           stub_entry, RawPcDescriptors::kOther, locs);
+                           stub, RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -2555,7 +2554,7 @@
     }
   }
   compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  *StubCode::AllocateArray_entry(),
+                                  StubCode::AllocateArray(),
                                   RawPcDescriptors::kOther, locs());
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2833,7 +2832,7 @@
 
     __ LoadImmediate(R1, instruction()->num_context_variables());
     compiler->GenerateCall(instruction()->token_pos(),
-                           *StubCode::AllocateContext_entry(),
+                           StubCode::AllocateContext(),
                            RawPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == R0);
     compiler->RestoreLiveRegisters(instruction()->locs());
@@ -2879,7 +2878,7 @@
   ASSERT(locs()->out(0).reg() == R0);
 
   __ LoadImmediate(R1, num_context_variables());
-  compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(),
+  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
                          RawPcDescriptors::kOther, locs());
 }
 
@@ -6727,15 +6726,13 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  const StubEntry stub_entry(stub);
-  compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
   __ Drop(ArgumentCount());  // Discard arguments.
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry());
+  __ BranchLinkPatchable(StubCode::DebugStepCheck());
   compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
   compiler->RecordSafepoint(locs());
 }
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index bd7fe21..a3a7868 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -831,14 +831,14 @@
   // into the runtime system.
   uword entry;
   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
-  const StubEntry* stub_entry;
+  const Code* stub;
   if (link_lazily()) {
-    stub_entry = StubCode::CallBootstrapNative_entry();
+    stub = &StubCode::CallBootstrapNative();
     entry = NativeEntry::LinkNativeCallEntry();
   } else {
     entry = reinterpret_cast<uword>(native_c_function());
     if (is_bootstrap_native()) {
-      stub_entry = StubCode::CallBootstrapNative_entry();
+      stub = &StubCode::CallBootstrapNative();
 #if defined(USING_SIMULATOR)
       entry = Simulator::RedirectExternalReference(
           entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
@@ -847,12 +847,12 @@
       // In the case of non bootstrap native methods the CallNativeCFunction
       // stub generates the redirection address when running under the simulator
       // and hence we do not change 'entry' here.
-      stub_entry = StubCode::CallAutoScopeNative_entry();
+      stub = &StubCode::CallAutoScopeNative();
     } else {
       // In the case of non bootstrap native methods the CallNativeCFunction
       // stub generates the redirection address when running under the simulator
       // and hence we do not change 'entry' here.
-      stub_entry = StubCode::CallNoScopeNative_entry();
+      stub = &StubCode::CallNoScopeNative();
     }
   }
   __ LoadImmediate(R1, argc_tag);
@@ -861,10 +861,10 @@
       R5, &label,
       link_lazily() ? ObjectPool::kPatchable : ObjectPool::kNotPatchable);
   if (link_lazily()) {
-    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+    compiler->GeneratePatchableCall(token_pos(), *stub,
                                     RawPcDescriptors::kOther, locs());
   } else {
-    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+    compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther,
                            locs());
   }
   __ Pop(result);
@@ -1834,7 +1834,6 @@
     __ Bind(entry_label());
     const Code& stub = Code::ZoneHandle(
         compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
-    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction()->locs();
 
@@ -1842,7 +1841,7 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(TokenPosition::kNoSource,  // No token position.
-                           stub_entry, RawPcDescriptors::kOther, locs);
+                           stub, RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -2251,7 +2250,7 @@
     }
   }
   compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  *StubCode::AllocateArray_entry(),
+                                  StubCode::AllocateArray(),
                                   RawPcDescriptors::kOther, locs());
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2521,7 +2520,7 @@
 
     __ LoadImmediate(R1, instruction()->num_context_variables());
     compiler->GenerateCall(instruction()->token_pos(),
-                           *StubCode::AllocateContext_entry(),
+                           StubCode::AllocateContext(),
                            RawPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == R0);
     compiler->RestoreLiveRegisters(instruction()->locs());
@@ -2567,7 +2566,7 @@
   ASSERT(locs()->out(0).reg() == R0);
 
   __ LoadImmediate(R1, num_context_variables());
-  compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(),
+  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
                          RawPcDescriptors::kOther, locs());
 }
 
@@ -5965,15 +5964,13 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  const StubEntry stub_entry(stub);
-  compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
   __ Drop(ArgumentCount());  // Discard arguments.
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry());
+  __ BranchLinkPatchable(StubCode::DebugStepCheck());
   compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
   compiler->RecordSafepoint(locs());
 }
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index b4c0e35..ce677dc 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -823,21 +823,20 @@
 
   __ movl(EDX, Immediate(argc_tag));
 
-  const StubEntry* stub_entry;
+  const Code* stub;
 
   // There is no lazy-linking support on ia32.
   ASSERT(!link_lazily());
   if (is_bootstrap_native()) {
-    stub_entry = StubCode::CallBootstrapNative_entry();
+    stub = &StubCode::CallBootstrapNative();
   } else if (is_auto_scope()) {
-    stub_entry = StubCode::CallAutoScopeNative_entry();
+    stub = &StubCode::CallAutoScopeNative();
   } else {
-    stub_entry = StubCode::CallNoScopeNative_entry();
+    stub = &StubCode::CallNoScopeNative();
   }
   const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
   __ movl(ECX, Immediate(label.address()));
-  compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther, locs());
 
   __ popl(result);
 
@@ -1723,14 +1722,13 @@
     __ Bind(entry_label());
     const Code& stub = Code::ZoneHandle(
         compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
-    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction()->locs();
 
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(TokenPosition::kNoSource, stub_entry,
+    compiler->GenerateCall(TokenPosition::kNoSource, stub,
                            RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, EAX);
     compiler->RestoreLiveRegisters(locs);
@@ -2136,7 +2134,7 @@
 
   __ Bind(&slow_path);
   compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  *StubCode::AllocateArray_entry(),
+                                  StubCode::AllocateArray(),
                                   RawPcDescriptors::kOther, locs());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
@@ -2410,7 +2408,7 @@
 
     __ movl(EDX, Immediate(instruction()->num_context_variables()));
     compiler->GenerateCall(instruction()->token_pos(),
-                           *StubCode::AllocateContext_entry(),
+                           StubCode::AllocateContext(),
                            RawPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == EAX);
     compiler->RestoreLiveRegisters(instruction()->locs());
@@ -2458,7 +2456,7 @@
   ASSERT(locs()->out(0).reg() == EAX);
 
   __ movl(EDX, Immediate(num_context_variables()));
-  compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(),
+  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
                          RawPcDescriptors::kOther, locs());
 }
 
@@ -6165,15 +6163,13 @@
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  const StubEntry stub_entry(stub);
-  compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
   __ Drop(ArgumentCount());  // Discard arguments.
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  __ Call(*StubCode::DebugStepCheck_entry());
+  __ Call(StubCode::DebugStepCheck());
   compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
   compiler->RecordSafepoint(locs());
 }
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 9553b94..4ae5a22 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -849,24 +849,24 @@
   __ leaq(RAX, Address(RSP, ArgumentCount() * kWordSize));
 
   __ LoadImmediate(R10, Immediate(argc_tag));
-  const StubEntry* stub_entry;
+  const Code* stub;
   if (link_lazily()) {
-    stub_entry = StubCode::CallBootstrapNative_entry();
+    stub = &StubCode::CallBootstrapNative();
     ExternalLabel label(NativeEntry::LinkNativeCallEntry());
     __ LoadNativeEntry(RBX, &label, ObjectPool::kPatchable);
-    compiler->GeneratePatchableCall(token_pos(), *stub_entry,
+    compiler->GeneratePatchableCall(token_pos(), *stub,
                                     RawPcDescriptors::kOther, locs());
   } else {
     if (is_bootstrap_native()) {
-      stub_entry = StubCode::CallBootstrapNative_entry();
+      stub = &StubCode::CallBootstrapNative();
     } else if (is_auto_scope()) {
-      stub_entry = StubCode::CallAutoScopeNative_entry();
+      stub = &StubCode::CallAutoScopeNative();
     } else {
-      stub_entry = StubCode::CallNoScopeNative_entry();
+      stub = &StubCode::CallNoScopeNative();
     }
     const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
     __ LoadNativeEntry(RBX, &label, ObjectPool::kNotPatchable);
-    compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+    compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther,
                            locs());
   }
   __ popq(result);
@@ -1017,7 +1017,6 @@
     __ Bind(entry_label());
     const Code& stub = Code::ZoneHandle(
         compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
-    const StubEntry stub_entry(stub);
 
     LocationSummary* locs = instruction()->locs();
 
@@ -1025,7 +1024,7 @@
 
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(TokenPosition::kNoSource,  // No token position.
-                           stub_entry, RawPcDescriptors::kOther, locs);
+                           stub, RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, RAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -2264,7 +2263,7 @@
 
   __ Bind(&slow_path);
   compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  *StubCode::AllocateArray_entry(),
+                                  StubCode::AllocateArray(),
                                   RawPcDescriptors::kOther, locs());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
@@ -2534,7 +2533,7 @@
 
     __ LoadImmediate(R10, Immediate(instruction()->num_context_variables()));
     compiler->GenerateCall(instruction()->token_pos(),
-                           *StubCode::AllocateContext_entry(),
+                           StubCode::AllocateContext(),
                            RawPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == RAX);
     compiler->RestoreLiveRegisters(instruction()->locs());
@@ -2581,7 +2580,7 @@
   ASSERT(locs()->out(0).reg() == RAX);
 
   __ LoadImmediate(R10, Immediate(num_context_variables()));
-  compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(),
+  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
                          RawPcDescriptors::kOther, locs());
 }
 
@@ -6297,15 +6296,13 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  const StubEntry stub_entry(stub);
-  compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
   __ Drop(ArgumentCount());  // Discard arguments.
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(!compiler->is_optimizing());
-  __ CallPatchable(*StubCode::DebugStepCheck_entry());
+  __ CallPatchable(StubCode::DebugStepCheck());
   compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
   compiler->RecordSafepoint(locs());
 }
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index bb5778a..61a6a51 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2692,6 +2692,22 @@
   return true;
 }
 
+static bool InlineLoadClassId(FlowGraph* flow_graph,
+                              Instruction* call,
+                              GraphEntryInstr* graph_entry,
+                              FunctionEntryInstr** entry,
+                              Instruction** last) {
+  *entry =
+      new (Z) FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
+                                 call->GetBlock()->try_index(), DeoptId::kNone);
+  (*entry)->InheritDeoptTarget(Z, call);
+  auto load_cid = new (Z)
+      LoadClassIdInstr(call->PushArgumentAt(0)->value()->CopyWithType(Z));
+  flow_graph->InsertBefore(call, load_cid, nullptr, FlowGraph::kValue);
+  *last = load_cid;
+  return true;
+}
+
 // Adds an explicit bounds check for a typed getter/setter.
 static void PrepareInlineTypedArrayBoundsCheck(FlowGraph* flow_graph,
                                                Instruction* call,
@@ -3605,6 +3621,8 @@
       }
       return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
                               entry, last, can_speculate);
+    case MethodRecognizer::kClassIDgetID:
+      return InlineLoadClassId(flow_graph, call, graph_entry, entry, last);
     default:
       break;
   }
diff --git a/runtime/vm/compiler/backend/loops.cc b/runtime/vm/compiler/backend/loops.cc
index 394da9e..707864e 100644
--- a/runtime/vm/compiler/backend/loops.cc
+++ b/runtime/vm/compiler/backend/loops.cc
@@ -65,16 +65,19 @@
   void Classify(LoopInfo* loop, Definition* def);
   void ClassifySCC(LoopInfo* loop);
 
-  // Transfer methods. Computes how induction of the operands, if any,
+  // Transfer methods. Compute how induction of the operands, if any,
   // tranfers over the operation performed by the given definition.
   InductionVar* TransferPhi(LoopInfo* loop, Definition* def, intptr_t idx = -1);
   InductionVar* TransferBinary(LoopInfo* loop, Definition* def);
   InductionVar* TransferUnary(LoopInfo* loop, Definition* def);
 
-  // Solver methods. Computes how temporary meaning given to the
+  // Solver methods. Compute how temporary meaning given to the
   // definitions in a cycle transfer over the operation performed
   // by the given definition.
   InductionVar* SolvePhi(LoopInfo* loop, Definition* def, intptr_t idx = -1);
+  InductionVar* SolveConstraint(LoopInfo* loop,
+                                Definition* def,
+                                InductionVar* init);
   InductionVar* SolveBinary(LoopInfo* loop,
                             Definition* def,
                             InductionVar* init);
@@ -239,8 +242,8 @@
     }
   } else if (def->IsPhi()) {
     induc = TransferPhi(loop, def);
-  } else if (def->IsRedefinition() || def->IsConstraint() || def->IsBox() ||
-             def->IsUnbox()) {
+  } else if (def->IsRedefinition() || def->IsBox() || def->IsUnbox() ||
+             def->IsConstraint()) {
     induc = Lookup(loop, def->InputAt(0)->definition());  // pass-through
   } else if (def->IsBinaryIntegerOp()) {
     induc = TransferBinary(loop, def);
@@ -278,9 +281,10 @@
       InductionVar* update = nullptr;
       if (def->IsPhi()) {
         update = SolvePhi(loop, def);
-      } else if (def->IsRedefinition() || def->IsConstraint() || def->IsBox() ||
-                 def->IsUnbox()) {
+      } else if (def->IsRedefinition() || def->IsBox() || def->IsUnbox()) {
         update = LookupCycle(def->InputAt(0)->definition());  // pass-through
+      } else if (def->IsConstraint()) {
+        update = SolveConstraint(loop, def, init);
       } else if (def->IsBinaryIntegerOp()) {
         update = SolveBinary(loop, def, init);
       } else if (def->IsUnaryIntegerOp()) {
@@ -381,6 +385,21 @@
   return induc;
 }
 
+InductionVar* InductionVarAnalysis::SolveConstraint(LoopInfo* loop,
+                                                    Definition* def,
+                                                    InductionVar* init) {
+  InductionVar* c = LookupCycle(def->InputAt(0)->definition());
+  if (c == init) {
+    // Record a non-artifical bound constraint on a phi.
+    // TODO(ajcbik): detect full loop logic, trip counts, etc.
+    ConstraintInstr* constraint = def->AsConstraint();
+    if (constraint->target() != nullptr) {
+      loop->limit_ = constraint;
+    }
+  }
+  return c;
+}
+
 InductionVar* InductionVarAnalysis::SolveBinary(LoopInfo* loop,
                                                 Definition* def,
                                                 InductionVar* init) {
@@ -629,6 +648,7 @@
       blocks_(blocks),
       back_edges_(),
       induction_(),
+      limit_(nullptr),
       outer_(nullptr),
       inner_(nullptr),
       next_(nullptr) {}
@@ -650,9 +670,9 @@
   return false;
 }
 
-bool LoopInfo::IsHeaderPhi(Instruction* instr) const {
-  return instr->IsPhi() && instr->GetBlock() == header_ &&
-         !instr->AsPhi()->IsRedundant();  // phi(x,..,x) = x
+bool LoopInfo::IsHeaderPhi(Definition* def) const {
+  return def != nullptr && def->IsPhi() && def->GetBlock() == header_ &&
+         !def->AsPhi()->IsRedundant();  // phi(x,..,x) = x
 }
 
 bool LoopInfo::IsIn(LoopInfo* loop) const {
@@ -679,6 +699,8 @@
 }
 
 void LoopInfo::AddInduction(Definition* def, InductionVar* induc) {
+  ASSERT(def != nullptr);
+  ASSERT(induc != nullptr);
   induction_.Insert(InductionKV::Pair(def, induc));
 }
 
diff --git a/runtime/vm/compiler/backend/loops.h b/runtime/vm/compiler/backend/loops.h
index 1d5b45a..30fdf59 100644
--- a/runtime/vm/compiler/backend/loops.h
+++ b/runtime/vm/compiler/backend/loops.h
@@ -38,7 +38,7 @@
   // Constructor for a constant.
   explicit InductionVar(int64_t offset) : InductionVar(offset, 0, nullptr) {}
 
-  // Constructor for induction.
+  // Constructor for an induction.
   InductionVar(Kind kind, InductionVar* initial, InductionVar* next)
       : kind_(kind), initial_(initial), next_(next) {
     ASSERT(IsInvariant(initial));
@@ -73,6 +73,29 @@
     return false;
   }
 
+  // Getters.
+  Kind kind() const { return kind_; }
+  int64_t offset() const {
+    ASSERT(kind_ == kInvariant);
+    return offset_;
+  }
+  int64_t mult() const {
+    ASSERT(kind_ == kInvariant);
+    return mult_;
+  }
+  Definition* def() const {
+    ASSERT(kind_ == kInvariant);
+    return def_;
+  }
+  InductionVar* initial() const {
+    ASSERT(kind_ != kInvariant);
+    return initial_;
+  }
+  InductionVar* next() const {
+    ASSERT(kind_ != kInvariant);
+    return next_;
+  }
+
   // For debugging.
   const char* ToCString() const;
 
@@ -134,8 +157,8 @@
   // Returns true if given block is backedge of this loop.
   bool IsBackEdge(BlockEntryInstr* block) const;
 
-  // Returns true if given instruction is a header phi for this loop.
-  bool IsHeaderPhi(Instruction* instr) const;
+  // Returns true if given definition is a header phi for this loop.
+  bool IsHeaderPhi(Definition* def) const;
 
   // Returns true if this loop is nested inside given loop.
   bool IsIn(LoopInfo* loop) const;
@@ -158,8 +181,9 @@
   // Getters.
   intptr_t id() const { return id_; }
   BlockEntryInstr* header() const { return header_; }
-  const GrowableArray<BlockEntryInstr*>& back_edges() { return back_edges_; }
   BitVector* blocks() const { return blocks_; }
+  const GrowableArray<BlockEntryInstr*>& back_edges() { return back_edges_; }
+  ConstraintInstr* limit() const { return limit_; }
   LoopInfo* outer() const { return outer_; }
   LoopInfo* inner() const { return inner_; }
   LoopInfo* next() const { return next_; }
@@ -187,9 +211,12 @@
   // Back edges of loop (usually one).
   GrowableArray<BlockEntryInstr*> back_edges_;
 
-  // Map instruction -> induction for this loop.
+  // Map definition -> induction for this loop.
   DirectChainedHashMap<InductionKV> induction_;
 
+  // Constraint on a header phi.
+  ConstraintInstr* limit_;
+
   // Loop hierarchy.
   LoopInfo* outer_;
   LoopInfo* inner_;
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 5b50229..d94536a 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -30,7 +30,7 @@
 void RangeAnalysis::Analyze() {
   CollectValues();
   InsertConstraints();
-  DiscoverSimpleInductionVariables();
+  flow_graph_->GetLoopHierarchy().ComputeInduction();
   InferRanges();
   EliminateRedundantBoundsChecks();
   MarkUnreachableBlocks();
@@ -43,6 +43,7 @@
   RemoveConstraints();
 }
 
+// Helper method to chase to a constrained definition.
 static Definition* UnwrapConstraint(Definition* defn) {
   while (defn->IsConstraint()) {
     defn = defn->AsConstraint()->value()->definition();
@@ -50,167 +51,6 @@
   return defn;
 }
 
-// Simple induction variable is a variable that satisfies the following pattern:
-//
-//                         v1 <- phi(v0, v1 + 1)
-//
-// If there are two simple induction variables in the same block and one of
-// them is constrained - then another one is constrained as well, e.g.
-// from
-//
-//                        B1:
-//                         v3 <- phi(v0, v3 + 1)
-//                         v4 <- phi(v2, v4 + 1)
-//                        Bx:
-//                         v3 is constrained to [v0, v1]
-//
-// it follows that
-//
-//                        Bx:
-//                         v4 is constrained to [v2, v2 + (v0 - v1)]
-//
-// This pass essentially pattern matches induction variables introduced
-// like this:
-//
-//                  for (var i = i0, j = j0; i < L; i++, j++) {
-//                      j is known to be within [j0, j0 + (L - i0 - 1)]
-//                  }
-//
-class InductionVariableInfo : public ZoneAllocated {
- public:
-  InductionVariableInfo(PhiInstr* phi,
-                        Definition* initial_value,
-                        BinarySmiOpInstr* increment,
-                        ConstraintInstr* limit)
-      : phi_(phi),
-        initial_value_(initial_value),
-        increment_(increment),
-        limit_(limit),
-        bound_(NULL) {}
-
-  PhiInstr* phi() const { return phi_; }
-  Definition* initial_value() const { return initial_value_; }
-  BinarySmiOpInstr* increment() const { return increment_; }
-
-  // Outermost constraint that constrains this induction variable into
-  // [-inf, X] range.
-  ConstraintInstr* limit() const { return limit_; }
-
-  // Induction variable from the same join block that has limiting constraint.
-  PhiInstr* bound() const { return bound_; }
-  void set_bound(PhiInstr* bound) { bound_ = bound; }
-
- private:
-  PhiInstr* phi_;
-  Definition* initial_value_;
-  BinarySmiOpInstr* increment_;
-  ConstraintInstr* limit_;
-
-  PhiInstr* bound_;
-};
-
-static ConstraintInstr* FindBoundingConstraint(PhiInstr* phi,
-                                               Definition* defn) {
-  ConstraintInstr* limit = NULL;
-  for (ConstraintInstr* constraint = defn->AsConstraint(); constraint != NULL;
-       constraint = constraint->value()->definition()->AsConstraint()) {
-    if (constraint->target() == NULL) {
-      continue;  // Only interested in non-artifical constraints.
-    }
-
-    Range* constraining_range = constraint->constraint();
-    if (constraining_range->min().Equals(RangeBoundary::MinSmi()) &&
-        (constraining_range->max().IsSymbol() &&
-         phi->IsDominatedBy(constraining_range->max().symbol()))) {
-      limit = constraint;
-    }
-  }
-
-  return limit;
-}
-
-static InductionVariableInfo* DetectSimpleInductionVariable(PhiInstr* phi) {
-  if (phi->Type()->ToCid() != kSmiCid) {
-    return NULL;
-  }
-
-  if (phi->InputCount() != 2) {
-    return NULL;
-  }
-
-  BitVector* loop_blocks = phi->block()->loop_info()->blocks();
-
-  const intptr_t backedge_idx =
-      loop_blocks->Contains(phi->block()->PredecessorAt(0)->preorder_number())
-          ? 0
-          : 1;
-
-  Definition* initial_value = phi->InputAt(1 - backedge_idx)->definition();
-
-  BinarySmiOpInstr* increment =
-      UnwrapConstraint(phi->InputAt(backedge_idx)->definition())
-          ->AsBinarySmiOp();
-
-  if ((increment != NULL) && (increment->op_kind() == Token::kADD) &&
-      (UnwrapConstraint(increment->left()->definition()) == phi) &&
-      increment->right()->BindsToConstant() &&
-      increment->right()->BoundConstant().IsSmi() &&
-      (Smi::Cast(increment->right()->BoundConstant()).Value() == 1)) {
-    return new InductionVariableInfo(
-        phi, initial_value, increment,
-        FindBoundingConstraint(phi, increment->left()->definition()));
-  }
-
-  return NULL;
-}
-
-// TODO(ajcbik): move induction variable recognition in loop framework
-void RangeAnalysis::DiscoverSimpleInductionVariables() {
-  GrowableArray<InductionVariableInfo*> loop_variables;
-
-  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
-       !block_it.Done(); block_it.Advance()) {
-    BlockEntryInstr* block = block_it.Current();
-
-    JoinEntryInstr* join = block->AsJoinEntry();
-    if (join != NULL && join->loop_info() != NULL &&
-        join->loop_info()->header() == join) {
-      loop_variables.Clear();
-
-      for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
-        PhiInstr* current = phi_it.Current();
-
-        InductionVariableInfo* info = DetectSimpleInductionVariable(current);
-        if (info != NULL) {
-          if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
-            THR_Print("Simple loop variable: %s bound <%s>\n",
-                      current->ToCString(),
-                      info->limit() != NULL ? info->limit()->ToCString() : "?");
-          }
-
-          loop_variables.Add(info);
-        }
-      }
-    }
-
-    InductionVariableInfo* bound = NULL;
-    for (intptr_t i = 0; i < loop_variables.length(); i++) {
-      if (loop_variables[i]->limit() != NULL) {
-        bound = loop_variables[i];
-        break;
-      }
-    }
-
-    if (bound != NULL) {
-      for (intptr_t i = 0; i < loop_variables.length(); i++) {
-        InductionVariableInfo* info = loop_variables[i];
-        info->set_bound(bound->phi());
-        info->phi()->set_induction_variable_info(info);
-      }
-    }
-  }
-}
-
 void RangeAnalysis::CollectValues() {
   auto graph_entry = flow_graph_->graph_entry();
 
@@ -1077,6 +917,8 @@
   }
 
   typedef Definition* (BoundsCheckGeneralizer::*PhiBoundFunc)(PhiInstr*,
+                                                              LoopInfo*,
+                                                              InductionVar*,
                                                               Instruction*);
 
   // Construct symbolic lower bound for a value at the given point.
@@ -1091,6 +933,52 @@
                           value, point);
   }
 
+  // Helper methods to implement "older" business logic.
+  // TODO(ajcbik): generalize with new induction variable information
+
+  // Only accept loops with a smi constraint on smi induction.
+  LoopInfo* GetSmiBoundedLoop(PhiInstr* phi) {
+    LoopInfo* loop = phi->GetBlock()->loop_info();
+    if (loop == nullptr) {
+      return nullptr;
+    }
+    ConstraintInstr* limit = loop->limit();
+    if (limit == nullptr) {
+      return nullptr;
+    }
+    Definition* def = UnwrapConstraint(limit->value()->definition());
+    Range* constraining_range = limit->constraint();
+    if (GetSmiInduction(loop, def) != nullptr &&
+        constraining_range->min().Equals(RangeBoundary::MinSmi()) &&
+        constraining_range->max().IsSymbol() &&
+        def->IsDominatedBy(constraining_range->max().symbol())) {
+      return loop;
+    }
+    return nullptr;
+  }
+
+  // Only accept smi linear induction with unit stride.
+  InductionVar* GetSmiInduction(LoopInfo* loop, Definition* def) {
+    if (loop != nullptr && def->Type()->ToCid() == kSmiCid) {
+      InductionVar* induc = loop->LookupInduction(def);
+      if (induc != nullptr && induc->kind() == InductionVar::kLinear &&
+          induc->next()->offset() == 1 && induc->next()->mult() == 0) {
+        return induc;
+      }
+    }
+    return nullptr;
+  }
+
+  // Reconstruct invariant (phi-init is always already in the graph).
+  Definition* GenerateInvariant(InductionVar* induc) {
+    if (induc->mult() == 0) {
+      return flow_graph_->GetConstant(
+          Smi::ZoneHandle(Smi::New(induc->offset())));
+    }
+    ASSERT(induc->offset() == 0 && induc->mult() == 1);
+    return induc->def();
+  }
+
   // Construct symbolic bound for a value at the given point:
   //
   //   1. if value is an induction variable use its bounds;
@@ -1109,8 +997,10 @@
     value = UnwrapConstraint(value);
     if (value->IsPhi()) {
       PhiInstr* phi = value->AsPhi();
-      if (phi->induction_variable_info() != NULL) {
-        return (this->*phi_bound_func)(phi, point);
+      LoopInfo* loop = GetSmiBoundedLoop(phi);
+      InductionVar* induc = GetSmiInduction(loop, phi);
+      if (induc != nullptr) {
+        return (this->*phi_bound_func)(phi, loop, induc, point);
       }
     } else if (value->IsBinarySmiOp()) {
       BinarySmiOpInstr* bin_op = value->AsBinarySmiOp();
@@ -1131,58 +1021,61 @@
         }
       }
     }
-
     return value;
   }
 
-  Definition* InductionVariableUpperBound(PhiInstr* phi, Instruction* point) {
-    const InductionVariableInfo& info = *phi->induction_variable_info();
-    if (info.bound() == phi) {
-      if (point->IsDominatedBy(info.limit())) {
-        // Given induction variable
-        //
-        //          x <- phi(x0, x + 1)
-        //
-        // and a constraint x <= M that dominates the given
-        // point we conclude that M is an upper bound for x.
-        return RangeBoundaryToDefinition(info.limit()->constraint()->max());
-      }
-    } else {
-      const InductionVariableInfo& bound_info =
-          *info.bound()->induction_variable_info();
-      if (point->IsDominatedBy(bound_info.limit())) {
-        // Given two induction variables
-        //
-        //          x <- phi(x0, x + 1)
-        //          y <- phi(y0, y + 1)
-        //
-        // and a constraint x <= M that dominates the given
-        // point we can conclude that
-        //
-        //          y <= y0 + (M - x0)
-        //
-        Definition* limit =
-            RangeBoundaryToDefinition(bound_info.limit()->constraint()->max());
-        BinarySmiOpInstr* loop_length = MakeBinaryOp(
-            Token::kSUB, ConstructUpperBound(limit, point),
-            ConstructLowerBound(bound_info.initial_value(), point));
-        return MakeBinaryOp(Token::kADD,
-                            ConstructUpperBound(info.initial_value(), point),
-                            loop_length);
-      }
+  Definition* InductionVariableUpperBound(PhiInstr* phi,
+                                          LoopInfo* loop,
+                                          InductionVar* induc,
+                                          Instruction* point) {
+    // Test if limit dominates given point.
+    ConstraintInstr* limit = loop->limit();
+    if (!point->IsDominatedBy(limit)) {
+      return phi;
     }
-
-    return phi;
+    // Decide between direct or indirect bound.
+    Definition* bounded_phi = UnwrapConstraint(limit->value()->definition());
+    if (bounded_phi == phi) {
+      // Given a smi bounded loop with smi induction variable
+      //
+      //          x <- phi(x0, x + 1)
+      //
+      // and a constraint x <= M that dominates the given
+      // point we conclude that M is an upper bound for x.
+      return RangeBoundaryToDefinition(limit->constraint()->max());
+    } else {
+      // Given a smi bounded loop with two smi induction variables
+      //
+      //          x <- phi(x0, x + 1)
+      //          y <- phi(y0, y + 1)
+      //
+      // and a constraint x <= M that dominates the given
+      // point we can conclude that
+      //
+      //          y <= y0 + (M - x0)
+      //
+      InductionVar* bounded_induc = GetSmiInduction(loop, bounded_phi);
+      Definition* x0 = GenerateInvariant(bounded_induc->initial());
+      Definition* y0 = GenerateInvariant(induc->initial());
+      Definition* m = RangeBoundaryToDefinition(limit->constraint()->max());
+      BinarySmiOpInstr* loop_length =
+          MakeBinaryOp(Token::kSUB, ConstructUpperBound(m, point),
+                       ConstructLowerBound(x0, point));
+      return MakeBinaryOp(Token::kADD, ConstructUpperBound(y0, point),
+                          loop_length);
+    }
   }
 
-  Definition* InductionVariableLowerBound(PhiInstr* phi, Instruction* point) {
-    // Given induction variable
+  Definition* InductionVariableLowerBound(PhiInstr* phi,
+                                          LoopInfo* loop,
+                                          InductionVar* induc,
+                                          Instruction* point) {
+    // Given a smi bounded loop with smi induction variable
     //
     //          x <- phi(x0, x + 1)
     //
     // we can conclude that LowerBound(x) == x0.
-    const InductionVariableInfo& info = *phi->induction_variable_info();
-    return ConstructLowerBound(info.initial_value(), point);
+    return ConstructLowerBound(GenerateInvariant(induc->initial()), point);
   }
 
   // Try to re-associate binary operations in the floating DAG of operations
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index 0b25eaa..56dc78e 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -538,8 +538,8 @@
   enum JoinOperator { NONE, WIDEN, NARROW };
   static char OpPrefix(JoinOperator op);
 
-  // Collect all values that were proven to be smi in smi_values_ array and all
-  // CheckSmi instructions in smi_check_ array.
+  // Collect all integer values (smi or int), all 64-bit binary
+  // and shift operations, and all check bounds.
   void CollectValues();
 
   // Iterate over smi values and constrain them at branch successors.
@@ -583,8 +583,6 @@
   // Convert mint operations that stay within int32 range into Int32 operations.
   void NarrowMintToInt32();
 
-  void DiscoverSimpleInductionVariables();
-
   // Remove artificial Constraint instructions and replace them with actual
   // unconstrained definitions.
   void RemoveConstraints();
@@ -600,11 +598,11 @@
 
   Range int64_range_;
 
-  // Value that are known to be smi or mint.
+  // All values that are known to be smi or mint.
   GrowableArray<Definition*> values_;
 
+  // All 64-bit binary and shift operations.
   GrowableArray<BinaryInt64OpInstr*> binary_int64_ops_;
-
   GrowableArray<ShiftIntegerOpInstr*> shift_int64_ops_;
 
   // All CheckArrayBound instructions.
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index c1d69a5..79574ea 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -126,10 +126,21 @@
   intptr_t nullable_cid = kDynamicCid;
   bool is_nullable = true;
 
+  if (field.has_pragma()) {
+    const intptr_t cid = MethodRecognizer::ResultCidFromPragma(field);
+    if (cid != kDynamicCid) {
+      nullable_cid = cid;
+      is_nullable = false;
+    } else if (MethodRecognizer::HasNonNullableResultTypeFromPragma(field)) {
+      is_nullable = false;
+    }
+  }
+
   if (field.guarded_cid() != kIllegalCid &&
       field.guarded_cid() != kDynamicCid) {
-    nullable_cid = field.guarded_cid();
-    is_nullable = field.is_nullable();
+    nullable_cid =
+        nullable_cid != kDynamicCid ? nullable_cid : field.guarded_cid();
+    is_nullable = is_nullable && field.is_nullable();
 
     if (thread->isolate()->use_field_guards()) {
       ASSERT(parsed_function != nullptr);
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index f17daa6..19c03ae 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1182,17 +1182,23 @@
 }
 
 CompileType PolymorphicInstanceCallInstr::ComputeType() const {
+  bool is_nullable = CompileType::kNullable;
   if (IsSureToCallSingleRecognizedTarget()) {
     const Function& target = *targets_.TargetAt(0)->target;
-    if (target.recognized_kind() != MethodRecognizer::kUnknown) {
-      return CompileType::FromCid(MethodRecognizer::ResultCid(target));
+    if (target.has_pragma()) {
+      const intptr_t cid = MethodRecognizer::ResultCidFromPragma(target);
+      if (cid != kDynamicCid) {
+        return CompileType::FromCid(cid);
+      } else if (MethodRecognizer::HasNonNullableResultTypeFromPragma(target)) {
+        is_nullable = CompileType::kNonNullable;
+      }
     }
   }
 
   if (Isolate::Current()->can_use_strong_mode_types()) {
     CompileType* type = instance_call()->Type();
     TraceStrongModeType(this, type);
-    return *type;
+    return is_nullable ? *type : type->CopyNonNullable();
   }
 
   return CompileType::Dynamic();
@@ -1207,8 +1213,15 @@
     return *inferred_type;
   }
 
-  if (function_.recognized_kind() != MethodRecognizer::kUnknown) {
-    return CompileType::FromCid(MethodRecognizer::ResultCid(function_));
+  bool is_nullable = CompileType::kNullable;
+  if (function_.has_pragma()) {
+    const intptr_t cid = MethodRecognizer::ResultCidFromPragma(function_);
+    if (cid != kDynamicCid) {
+      return CompileType::FromCid(cid);
+    }
+    if (MethodRecognizer::HasNonNullableResultTypeFromPragma(function_)) {
+      is_nullable = CompileType::kNonNullable;
+    }
   }
 
   if (Isolate::Current()->can_use_strong_mode_types()) {
@@ -1219,8 +1232,8 @@
     // non-instantiated types properly.
     if (result_type.IsInstantiated()) {
       TraceStrongModeType(this, result_type);
-      const bool is_nullable =
-          (inferred_type == NULL) || inferred_type->is_nullable();
+      is_nullable = is_nullable &&
+                    (inferred_type == nullptr || inferred_type->is_nullable());
       return CompileType::FromAbstractType(result_type, is_nullable);
     }
   }
@@ -1319,11 +1332,9 @@
   }
 
   const Isolate* isolate = Isolate::Current();
-  intptr_t cid = kDynamicCid;
   const AbstractType* abstract_type = NULL;
   if (isolate->can_use_strong_mode_types() ||
       (field_type.IsFunctionType() || field_type.HasTypeClass())) {
-    cid = kIllegalCid;  // Abstract type is known, calculate cid lazily.
     abstract_type = &field_type;
     TraceStrongModeType(this, *abstract_type);
   }
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 948259e..1dd24e3 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -187,6 +187,10 @@
             VisitInstanceCall(call);
           }
         }
+      } else if (auto static_call = instr->AsStaticCall()) {
+        // If TFA devirtualized instance calls to static calls we also want to
+        // process them here.
+        VisitStaticCall(static_call);
       } else if (instr->IsPolymorphicInstanceCall()) {
         SpecializePolymorphicInstanceCall(instr->AsPolymorphicInstanceCall());
       }
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 988d0834..daeb0fe 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -270,9 +270,7 @@
   INVOKE_PASS(WriteBarrierElimination);
   INVOKE_PASS(FinalizeGraph);
   INVOKE_PASS(AllocateRegisters);
-  if (mode == kJIT) {
-    INVOKE_PASS(ReorderBlocks);
-  }
+  INVOKE_PASS(ReorderBlocks);
 }
 
 COMPILER_PASS(ComputeSSA, {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 4e54a2b..eadab31 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -639,8 +639,7 @@
   JoinEntryInstr* nsm = BuildJoinEntry();
 
   Fragment failing(nsm);
-  const Code& nsm_handler =
-      Code::ZoneHandle(StubCode::CallClosureNoSuchMethod_entry()->code());
+  const Code& nsm_handler = StubCode::CallClosureNoSuchMethod();
   failing += LoadArgDescriptor();
   failing += TailCall(nsm_handler);
 
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index 19e33c2..872e7f2 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -254,8 +254,6 @@
 }
 
 RawObject* ConstantEvaluator::EvaluateAnnotations() {
-  BailoutIfBackgroundCompilation();
-
   intptr_t list_length = helper_->ReadListLength();  // read list length.
   const Array& metadata_values =
       Array::Handle(Z, Array::New(list_length, H.allocation_space()));
@@ -858,6 +856,10 @@
 }
 
 void ConstantEvaluator::EvaluateConstantExpression() {
+  // Please note that this constants array is constructed exactly once, see
+  // ReadConstantTable() and is immutable from that point on, so there is no
+  // need to guard against concurrent access between mutator and background
+  // compiler.
   KernelConstantsMap constant_map(H.constants().raw());
   result_ ^= constant_map.GetOrDie(helper_->ReadUInt());
   ASSERT(constant_map.Release().raw() == H.constants().raw());
@@ -1042,13 +1044,16 @@
   if (script_.compile_time_constants() == Array::null()) {
     return false;
   }
-  KernelConstantsMap constants(script_.compile_time_constants());
-  *value ^= constants.GetOrNull(kernel_offset + helper_->data_program_offset_,
-                                &is_present);
-  // Mutator compiler thread may add constants while background compiler
-  // is running, and thus change the value of 'compile_time_constants';
-  // do not assert that 'compile_time_constants' has not changed.
-  constants.Release();
+  {
+    // Any access to constants arrays must be locked since mutator and
+    // background compiler can access the array at the same time.
+    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
+
+    KernelConstantsMap constants(script_.compile_time_constants());
+    *value ^= constants.GetOrNull(kernel_offset + helper_->data_program_offset_,
+                                  &is_present);
+    constants.Release();
+  }
   return is_present;
 }
 
@@ -1071,10 +1076,16 @@
         HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
     script_.set_compile_time_constants(array);
   }
-  KernelConstantsMap constants(script_.compile_time_constants());
-  constants.InsertNewOrGetValue(kernel_offset + helper_->data_program_offset_,
-                                value);
-  script_.set_compile_time_constants(constants.Release());
+  {
+    // Any access to constants arrays must be locked since mutator and
+    // background compiler can access the array at the same time.
+    SafepointMutexLocker ml(H.thread()->isolate()->kernel_constants_mutex());
+
+    KernelConstantsMap constants(script_.compile_time_constants());
+    constants.InsertNewOrGetValue(kernel_offset + helper_->data_program_offset_,
+                                  value);
+    script_.set_compile_time_constants(constants.Release());
+  }
 }
 
 ConstantHelper::ConstantHelper(Zone* zone,
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index e5b3cf0..8524fd8 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -35,10 +35,6 @@
   return klass;
 }
 
-bool StreamingFlowGraphBuilder::optimizing() {
-  return flow_graph_builder_->optimizing_;
-}
-
 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
   FieldHelper field_helper(this);
   field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
@@ -1633,25 +1629,30 @@
 Fragment StreamingFlowGraphBuilder::BuildEntryPointsIntrospection() {
   if (!FLAG_enable_testing_pragmas) return Drop();
 
-  Function& function = Function::Handle(parsed_function()->function().raw());
+  auto& function = Function::Handle(Z, parsed_function()->function().raw());
 
   if (function.IsImplicitClosureFunction()) {
-    const Function& parent =
-        Function::ZoneHandle(Z, function.parent_function());
-    const String& func_name = String::ZoneHandle(Z, parent.name());
-    const Class& owner = Class::ZoneHandle(Z, parent.Owner());
+    const auto& parent = Function::Handle(Z, function.parent_function());
+    const auto& func_name = String::Handle(Z, parent.name());
+    const auto& owner = Class::Handle(Z, parent.Owner());
     function = owner.LookupFunction(func_name);
   }
 
-  Object& options = Object::Handle();
-  if (!function.FindPragma(I, Symbols::vm_trace_entrypoints(), &options) ||
+  auto& tmp = Object::Handle(Z);
+  tmp = function.Owner();
+  tmp = Class::Cast(tmp).library();
+  auto& library = Library::Cast(tmp);
+
+  Object& options = Object::Handle(Z);
+  if (!library.FindPragma(H.thread(), function, Symbols::vm_trace_entrypoints(),
+                          &options) ||
       options.IsNull() || !options.IsClosure()) {
     return Drop();
   }
-  Closure& closure = Closure::ZoneHandle(Z, Closure::Cast(options).raw());
+  auto& closure = Closure::ZoneHandle(Z, Closure::Cast(options).raw());
   LocalVariable* entry_point_num = MakeTemporary();
 
-  String& function_name = String::ZoneHandle(
+  auto& function_name = String::ZoneHandle(
       Z, String::New(function.ToLibNamePrefixedQualifiedCString(), Heap::kOld));
   if (parsed_function()->function().IsImplicitClosureFunction()) {
     function_name = String::Concat(
@@ -1669,7 +1670,7 @@
   call_hook += Constant(Function::ZoneHandle(Z, closure.function()));
   call_hook += B->ClosureCall(TokenPosition::kNoSource,
                               /*type_args_len=*/0, /*argument_count=*/3,
-                              /*argument_names=*/Array::Handle());
+                              /*argument_names=*/Array::ZoneHandle(Z));
   call_hook += Drop();  // result of closure call
   call_hook += Drop();  // entrypoint number
   return call_hook;
@@ -3503,11 +3504,6 @@
   }
 }
 
-static bool IsNumberLiteral(Tag tag) {
-  return tag == kNegativeIntLiteral || tag == kPositiveIntLiteral ||
-         tag == kSpecializedIntLiteral || tag == kDoubleLiteral;
-}
-
 Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
   const TokenPosition position = ReadPosition();  // read position.
@@ -3521,39 +3517,6 @@
       call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
 
   const Tag receiver_tag = PeekTag();  // peek tag for receiver.
-  if (IsNumberLiteral(receiver_tag) &&
-      (!optimizing() || constant_evaluator_.IsCached(offset))) {
-    const intptr_t before_branch_offset = ReaderOffset();
-
-    SkipExpression();  // read receiver (it's just a number literal).
-
-    const String& name = ReadNameAsMethodName();  // read name.
-    const Token::Kind token_kind =
-        MethodTokenRecognizer::RecognizeTokenKind(name);
-    intptr_t argument_count = PeekArgumentsCount() + 1;
-
-    if ((argument_count == 1) && (token_kind == Token::kNEGATE)) {
-      const Object& result = Object::ZoneHandle(
-          Z, constant_evaluator_.EvaluateExpressionSafe(offset));
-      if (!result.IsError()) {
-        SkipArguments();               // read arguments.
-        SkipCanonicalNameReference();  // read interface_target_reference.
-        return Constant(result);
-      }
-    } else if ((argument_count == 2) &&
-               Token::IsBinaryArithmeticOperator(token_kind) &&
-               IsNumberLiteral(PeekArgumentsFirstPositionalTag())) {
-      const Object& result = Object::ZoneHandle(
-          Z, constant_evaluator_.EvaluateExpressionSafe(offset));
-      if (!result.IsError()) {
-        SkipArguments();               // read arguments.
-        SkipCanonicalNameReference();  // read interface_target_reference.
-        return Constant(result);
-      }
-    }
-
-    SetOffset(before_branch_offset);
-  }
 
   bool is_unchecked_closure_call = false;
   bool is_unchecked_call = false;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 6a1e201..b16d914 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -54,8 +54,6 @@
   Fragment BuildStatementAt(intptr_t kernel_offset);
 
  private:
-  bool optimizing();
-
   Thread* thread() const { return flow_graph_builder_->thread_; }
 
   FlowGraph* BuildGraphOfFieldInitializer();
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 64485a3..348d98f 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -546,8 +546,8 @@
     call->set_is_known_list_constructor(true);
     return;
   }
-  if (target.recognized_kind() != MethodRecognizer::kUnknown) {
-    intptr_t recognized_cid = MethodRecognizer::ResultCid(target);
+  if (target.has_pragma()) {
+    intptr_t recognized_cid = MethodRecognizer::ResultCidFromPragma(target);
     if (recognized_cid != kDynamicCid) {
       ASSERT((result_type == NULL) || (result_type->cid == kDynamicCid) ||
              (result_type->cid == recognized_cid));
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index bf445f5..4a22001 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -87,7 +87,7 @@
   IntrinsicDesc* intrinsics;
 };
 
-#define DEFINE_INTRINSIC(class_name, function_name, destination, type, fp)     \
+#define DEFINE_INTRINSIC(class_name, function_name, destination, fp)           \
   {#class_name, #function_name},
 
 // clang-format off
@@ -230,7 +230,7 @@
       new FlowGraph(parsed_function, graph_entry, block_id, prologue_info);
   const Function& function = parsed_function.function();
   switch (function.recognized_kind()) {
-#define EMIT_CASE(class_name, function_name, enum_name, type, fp)              \
+#define EMIT_CASE(class_name, function_name, enum_name, fp)                    \
   case MethodRecognizer::k##enum_name:                                         \
     if (!Build_##enum_name(graph)) return false;                               \
     break;
@@ -300,7 +300,7 @@
 #define EMIT_BREAKPOINT()
 #endif
 
-#define EMIT_CASE(class_name, function_name, enum_name, type, fp)              \
+#define EMIT_CASE(class_name, function_name, enum_name, fp)                    \
   case MethodRecognizer::k##enum_name: {                                       \
     compiler->assembler()->Comment("Intrinsic");                               \
     Label normal_ir_body;                                                      \
diff --git a/runtime/vm/compiler/intrinsifier.h b/runtime/vm/compiler/intrinsifier.h
index be8a563..23d5436 100644
--- a/runtime/vm/compiler/intrinsifier.h
+++ b/runtime/vm/compiler/intrinsifier.h
@@ -43,7 +43,7 @@
 
   static bool CanIntrinsify(const Function& function);
 
-#define DECLARE_FUNCTION(class_name, function_name, enum_name, type, fp)       \
+#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
   static void enum_name(Assembler* assembler, Label* normal_ir_body);
 
   ALL_INTRINSICS_LIST(DECLARE_FUNCTION)
@@ -55,7 +55,7 @@
 #undef DECLARE_FUNCTION
 
 #if !defined(TARGET_ARCH_DBC)
-#define DECLARE_FUNCTION(class_name, function_name, enum_name, type, fp)       \
+#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
   static bool Build_##enum_name(FlowGraph* flow_graph);
 
   GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
diff --git a/runtime/vm/compiler/intrinsifier_dbc.cc b/runtime/vm/compiler/intrinsifier_dbc.cc
index 0cad04a..b09a15f 100644
--- a/runtime/vm/compiler/intrinsifier_dbc.cc
+++ b/runtime/vm/compiler/intrinsifier_dbc.cc
@@ -25,7 +25,7 @@
   return -1;
 }
 
-#define DEFINE_FUNCTION(class_name, test_function_name, enum_name, type, fp)   \
+#define DEFINE_FUNCTION(class_name, test_function_name, enum_name, fp)         \
   void Intrinsifier::enum_name(Assembler* assembler, Label* normal_ir_body) {  \
     if (Simulator::IsSupportedIntrinsic(Simulator::k##enum_name##Intrinsic)) { \
       assembler->Intrinsic(Simulator::k##enum_name##Intrinsic);                \
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 972285d..89f360a 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -110,7 +110,7 @@
     FLAG_optimization_counter_threshold = -1;
     FLAG_polymorphic_with_deopt = false;
     FLAG_precompiled_mode = true;
-    FLAG_reorder_basic_blocks = false;
+    FLAG_reorder_basic_blocks = true;
     FLAG_use_field_guards = false;
     FLAG_use_cha_deopt = false;
 
@@ -1018,7 +1018,7 @@
         // The non-optimizing compiler can get an unhandled exception
         // due to OOM or Stack overflow errors, it should not however
         // bail out.
-        ASSERT(error.IsUnhandledException() ||
+        ASSERT(error.IsUnhandledException() || error.IsUnwindError() ||
                (error.IsLanguageError() &&
                 LanguageError::Cast(error).kind() != Report::kBailout));
         return error.raw();
@@ -1362,7 +1362,7 @@
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
     !defined(TARGET_ARCH_IA32)
   if (FLAG_precompiled_mode) {
-    return Precompiler::EvaluateStaticInitializer(field);
+    UNREACHABLE();
   }
 #endif
   ASSERT(field.is_static());
@@ -1436,7 +1436,7 @@
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
     !defined(TARGET_ARCH_IA32)
   if (FLAG_precompiled_mode) {
-    return Precompiler::ExecuteOnce(fragment);
+    UNREACHABLE();
   }
 #endif
   LongJumpScope jump;
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index d3dbb90..be12f08 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -35,20 +35,29 @@
   }
 }
 
-intptr_t MethodRecognizer::ResultCid(const Function& function) {
-  // Use the 'vm:exact-result-type' annotation if available. This can only be
-  // used within the core library, see 'result_type_pragma.md', detail 1.2 for
-  // explanation.
-  Class& cls = Thread::Current()->ClassHandle();
-  Library& lib = Thread::Current()->LibraryHandle();
-  cls = function.Owner();
-  lib = cls.library();
-  const bool can_use_pragma = lib.IsAnyCoreLibrary();
-  cls = Class::null();
+intptr_t MethodRecognizer::ResultCidFromPragma(
+    const Object& function_or_field) {
+  // TODO(vm-team): The caller should only call us if the
+  // function_or_field.has_pragma(). If this method turns out to be a
+  // performance problem nonetheless, we could consider adding a cache.
+  auto T = Thread::Current();
+  auto Z = T->zone();
+  auto& klass = Class::Handle(Z);
+  if (function_or_field.IsFunction()) {
+    auto& function = Function::Cast(function_or_field);
+    ASSERT(function.has_pragma());
+    klass = function.Owner();
+  } else {
+    auto& field = Field::Cast(function_or_field);
+    ASSERT(field.has_pragma());
+    klass = field.Owner();
+  }
+  auto& library = Library::Handle(Z, klass.library());
+  const bool can_use_pragma = library.IsAnyCoreLibrary();
   if (can_use_pragma) {
-    Isolate* I = Isolate::Current();
-    auto& option = Object::Handle();
-    if (function.FindPragma(I, Symbols::vm_exact_result_type(), &option)) {
+    auto& option = Object::Handle(Z);
+    if (library.FindPragma(T, function_or_field,
+                           Symbols::vm_exact_result_type(), &option)) {
       if (option.IsType()) {
         return Type::Cast(option).type_class_id();
       } else if (option.IsString()) {
@@ -68,17 +77,13 @@
           }
         }
         if (!parse_failure && library_end > 0) {
-          auto& libraryUri = String::Handle(
-              String::SubString(str, 0, library_end, Heap::kOld));
-          auto& className = String::Handle(
-              String::SubString(str, library_end + 1,
-                                str.Length() - library_end - 1, Heap::kOld));
-
-          Library& lib = Library::Handle(
-              Library::LookupLibrary(Thread::Current(), libraryUri));
-          if (!lib.IsNull()) {
-            Class& klass =
-                Class::Handle(lib.LookupClassAllowPrivate(className));
+          auto& tmp = String::Handle(Z);
+          tmp = String::SubString(str, 0, library_end, Heap::kOld);
+          library = Library::LookupLibrary(Thread::Current(), tmp);
+          if (!library.IsNull()) {
+            tmp = String::SubString(str, library_end + 1,
+                                    str.Length() - library_end - 1, Heap::kOld);
+            klass = library.LookupClassAllowPrivate(tmp);
             if (!klass.IsNull()) {
               return klass.id();
             }
@@ -88,31 +93,35 @@
     }
   }
 
-  // No result-type annotation can be used, so fall back on the table of
-  // recognized methods.
-  switch (function.recognized_kind()) {
-#define DEFINE_CASE(cname, fname, ename, result_type, fingerprint)             \
-  case k##ename: {                                                             \
-    const intptr_t cid = k##result_type##Cid;                                  \
-    if (cid != kDynamicCid) {                                                  \
-      String& err = String::Handle();                                          \
-      err = function.QualifiedScrubbedName();                                  \
-      err = String::Concat(                                                    \
-          err,                                                                 \
-          String::Handle(String::New(" (MethodRecognizer::k" #ename            \
-                                     ") should be using pragma annotation"     \
-                                     " rather than method recognizer.",        \
-                                     Heap::kOld)),                             \
-          Heap::kOld);                                                         \
-      FATAL(err.ToCString());                                                  \
-    }                                                                          \
-    return cid;                                                                \
+  return kDynamicCid;
+}
+
+bool MethodRecognizer::HasNonNullableResultTypeFromPragma(
+    const Object& function_or_field) {
+  auto T = Thread::Current();
+  auto Z = T->zone();
+  auto& klass = Class::Handle(Z);
+  if (function_or_field.IsFunction()) {
+    auto& function = Function::Cast(function_or_field);
+    ASSERT(function.has_pragma());
+    klass = function.Owner();
+  } else {
+    auto& field = Field::Cast(function_or_field);
+    ASSERT(field.has_pragma());
+    klass = field.Owner();
   }
-    RECOGNIZED_LIST(DEFINE_CASE)
-#undef DEFINE_CASE
-    default:
-      return kDynamicCid;
+  auto& library = Library::Handle(Z, klass.library());
+  const bool can_use_pragma = library.IsAnyCoreLibrary();
+  if (can_use_pragma) {
+    auto& option = Object::Handle(Z);
+    if (library.FindPragma(T, function_or_field,
+                           Symbols::vm_non_nullable_result_type(), &option)) {
+      return true;
+    }
   }
+
+  // If nothing said otherwise, the return type is nullable.
+  return false;
 }
 
 intptr_t MethodRecognizer::MethodKindToReceiverCid(Kind kind) {
@@ -201,8 +210,7 @@
   return kIllegalCid;
 }
 
-#define KIND_TO_STRING(class_name, function_name, enum_name, type, fp)         \
-  #enum_name,
+#define KIND_TO_STRING(class_name, function_name, enum_name, fp) #enum_name,
 static const char* recognized_list_method_name[] = {
     "Unknown", RECOGNIZED_LIST(KIND_TO_STRING)};
 #undef KIND_TO_STRING
@@ -219,7 +227,7 @@
   Libraries(&libs);
   Function& func = Function::Handle();
 
-#define SET_RECOGNIZED_KIND(class_name, function_name, enum_name, type, fp)    \
+#define SET_RECOGNIZED_KIND(class_name, function_name, enum_name, fp)          \
   func = Library::GetFunction(libs, #class_name, #function_name);              \
   if (!func.IsNull()) {                                                        \
     CHECK_FINGERPRINT3(func, class_name, function_name, enum_name, fp);        \
@@ -279,7 +287,7 @@
   GrowableArray<Library*> libs(3);
   Libraries(&libs);
 
-#define ADD_RECOGNIZED_METHOD(class_name, function_name, enum_name, type, fp)  \
+#define ADD_RECOGNIZED_METHOD(class_name, function_name, enum_name, fp)        \
   func = Library::GetFunction(libs, #class_name, #function_name);              \
   methods.Add(func);
 
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index d53528c..c3310b8 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -17,337 +17,307 @@
 // correct fingerprint from the mismatch error (or use Library::GetFunction()
 // and print func.SourceFingerprint()).
 #define OTHER_RECOGNIZED_LIST(V)                                               \
-  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)             \
-  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, Smi, 0x231bbe2e)             \
-  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, Smi, 0x0371785f)           \
-  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, Dynamic, 0x65ab3a20)         \
-  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, Dynamic, 0x0cb0fcf6)       \
-  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, Dynamic, 0x7db75d78)         \
-  V(_TypedList, _getUint64, ByteArrayBaseGetUint64, Dynamic, 0x1487cfc6)       \
-  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, Double, 0x6674ea6f)      \
-  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, Double, 0x236c6e7a)      \
-  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, Float32x4,           \
-    0x5c367ffb)                                                                \
-  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, Int32x4, 0x772d1c0f)     \
-  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, Dynamic, 0x12bae36a)           \
-  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, Dynamic, 0x15821cc9)         \
-  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, Dynamic, 0x1f8237fa)         \
-  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, Dynamic, 0x181e5d16)       \
-  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, Dynamic, 0x7ddb9f87)         \
-  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, Dynamic, 0x74094f8d)       \
-  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, Dynamic, 0x4741396e)         \
-  V(_TypedList, _setUint64, ByteArrayBaseSetUint64, Dynamic, 0x3b398ae4)       \
-  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, Dynamic, 0x03db087b)     \
-  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, Dynamic, 0x38a80b0d)     \
-  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, Dynamic, 0x40052c4e) \
-  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, Dynamic, 0x07b89f54)     \
-  V(::, _toClampedUint8, ConvertIntToClampedUint8, Smi, 0x564b0435)            \
-  V(_StringBase, _interpolate, StringBaseInterpolate, Dynamic, 0x01ecb15a)     \
-  V(_IntegerImplementation, toDouble, IntegerToDouble, Double, 0x05da96ed)     \
-  V(_Double, _add, DoubleAdd, Double, 0x2a38277b)                              \
-  V(_Double, _sub, DoubleSub, Double, 0x4f466391)                              \
-  V(_Double, _mul, DoubleMul, Double, 0x175e4f66)                              \
-  V(_Double, _div, DoubleDiv, Double, 0x0854181b)                              \
-  V(::, min, MathMin, Dynamic, 0x32ebc57d)                                     \
-  V(::, max, MathMax, Dynamic, 0x377e8889)                                     \
-  V(::, _doublePow, MathDoublePow, Double, 0x5add0ec1)                         \
-  V(::, _intPow, MathIntPow, Dynamic, 0x11b45569)                              \
-  V(Float32x4, Float32x4., Float32x4Constructor, Float32x4, 0x26ea459b)        \
-  V(Float32x4, Float32x4.zero, Float32x4Zero, Float32x4, 0x16eca604)           \
-  V(Float32x4, Float32x4.splat, Float32x4Splat, Float32x4, 0x694e83e3)         \
-  V(Float32x4, Float32x4.fromInt32x4Bits, Int32x4ToFloat32x4, Float32x4,       \
-    0x2f62ebd3)                                                                \
-  V(Float32x4, Float32x4.fromFloat64x2, Float64x2ToFloat32x4, Float32x4,       \
-    0x50ed6910)                                                                \
-  V(_Float32x4, shuffle, Float32x4Shuffle, Float32x4, 0x7829101f)              \
-  V(_Float32x4, shuffleMix, Float32x4ShuffleMix, Float32x4, 0x4182c06b)        \
-  V(_Float32x4, get:signMask, Float32x4GetSignMask, Dynamic, 0x1d08b351)       \
-  V(_Float32x4, equal, Float32x4Equal, Int32x4, 0x11adb239)                    \
-  V(_Float32x4, greaterThan, Float32x4GreaterThan, Int32x4, 0x48adaf58)        \
-  V(_Float32x4, greaterThanOrEqual, Float32x4GreaterThanOrEqual, Int32x4,      \
-    0x32db94ca)                                                                \
-  V(_Float32x4, lessThan, Float32x4LessThan, Int32x4, 0x425b000c)              \
-  V(_Float32x4, lessThanOrEqual, Float32x4LessThanOrEqual, Int32x4,            \
-    0x0278c2f8)                                                                \
-  V(_Float32x4, notEqual, Float32x4NotEqual, Int32x4, 0x2987cd26)              \
-  V(_Float32x4, min, Float32x4Min, Float32x4, 0x5ed74b6f)                      \
-  V(_Float32x4, max, Float32x4Max, Float32x4, 0x68696442)                      \
-  V(_Float32x4, scale, Float32x4Scale, Float32x4, 0x704e4122)                  \
-  V(_Float32x4, sqrt, Float32x4Sqrt, Float32x4, 0x2c967a6f)                    \
-  V(_Float32x4, reciprocalSqrt, Float32x4ReciprocalSqrt, Float32x4,            \
-    0x6264bfe8)                                                                \
-  V(_Float32x4, reciprocal, Float32x4Reciprocal, Float32x4, 0x3cd7e819)        \
-  V(_Float32x4, unary-, Float32x4Negate, Float32x4, 0x37accb52)                \
-  V(_Float32x4, abs, Float32x4Abs, Float32x4, 0x471cdd87)                      \
-  V(_Float32x4, clamp, Float32x4Clamp, Float32x4, 0x2cb30492)                  \
-  V(_Float32x4, withX, Float32x4WithX, Float32x4, 0x4e336aff)                  \
-  V(_Float32x4, withY, Float32x4WithY, Float32x4, 0x0a72b910)                  \
-  V(_Float32x4, withZ, Float32x4WithZ, Float32x4, 0x31e93658)                  \
-  V(_Float32x4, withW, Float32x4WithW, Float32x4, 0x60ddc105)                  \
-  V(Float64x2, Float64x2., Float64x2Constructor, Float64x2, 0x43054b9f)        \
-  V(Float64x2, Float64x2.zero, Float64x2Zero, Float64x2, 0x4af12f9d)           \
-  V(Float64x2, Float64x2.splat, Float64x2Splat, Float64x2, 0x134edef0)         \
-  V(Float64x2, Float64x2.fromFloat32x4, Float32x4ToFloat64x2, Float64x2,       \
-    0x17d6b5e4)                                                                \
-  V(_Float64x2, get:x, Float64x2GetX, Double, 0x58c09c58)                      \
-  V(_Float64x2, get:y, Float64x2GetY, Double, 0x3cf5e5b8)                      \
-  V(_Float64x2, unary-, Float64x2Negate, Float64x2, 0x415ca009)                \
-  V(_Float64x2, abs, Float64x2Abs, Float64x2, 0x031f9e47)                      \
-  V(_Float64x2, sqrt, Float64x2Sqrt, Float64x2, 0x77f711dd)                    \
-  V(_Float64x2, get:signMask, Float64x2GetSignMask, Dynamic, 0x27deda4b)       \
-  V(_Float64x2, scale, Float64x2Scale, Float64x2, 0x26830a61)                  \
-  V(_Float64x2, withX, Float64x2WithX, Float64x2, 0x1d2bcaf5)                  \
-  V(_Float64x2, withY, Float64x2WithY, Float64x2, 0x383ed6ac)                  \
-  V(_Float64x2, min, Float64x2Min, Float64x2, 0x28d7ddf6)                      \
-  V(_Float64x2, max, Float64x2Max, Float64x2, 0x0bd74e5b)                      \
-  V(Int32x4, Int32x4., Int32x4Constructor, Int32x4, 0x480555a9)                \
-  V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, Int32x4, 0x36aa6963)        \
-  V(Int32x4, Int32x4.fromFloat32x4Bits, Float32x4ToInt32x4, Int32x4,           \
-    0x6715388a)                                                                \
-  V(_Int32x4, get:flagX, Int32x4GetFlagX, Bool, 0x56396c82)                    \
-  V(_Int32x4, get:flagY, Int32x4GetFlagY, Bool, 0x44704738)                    \
-  V(_Int32x4, get:flagZ, Int32x4GetFlagZ, Bool, 0x20d6ff37)                    \
-  V(_Int32x4, get:flagW, Int32x4GetFlagW, Bool, 0x5045616a)                    \
-  V(_Int32x4, get:signMask, Int32x4GetSignMask, Dynamic, 0x2c1fb2a3)           \
-  V(_Int32x4, shuffle, Int32x4Shuffle, Int32x4, 0x20bc0b16)                    \
-  V(_Int32x4, shuffleMix, Int32x4ShuffleMix, Int32x4, 0x5c7056e1)              \
-  V(_Int32x4, select, Int32x4Select, Float32x4, 0x6b49654f)                    \
-  V(_Int32x4, withFlagX, Int32x4WithFlagX, Int32x4, 0x0ef58fcf)                \
-  V(_Int32x4, withFlagY, Int32x4WithFlagY, Int32x4, 0x6485a9c4)                \
-  V(_Int32x4, withFlagZ, Int32x4WithFlagZ, Int32x4, 0x267acdfa)                \
-  V(_Int32x4, withFlagW, Int32x4WithFlagW, Int32x4, 0x345ac675)                \
-  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, TypedDataUint32Array,     \
-      0x02477157)                                                              \
-  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, Dynamic, 0x4fc8d5e0)      \
-  V(_HashVMBase, get:_data, LinkedHashMap_getData, Array, 0x2d7a70ac)          \
-  V(_HashVMBase, set:_data, LinkedHashMap_setData, Dynamic, 0x0ec032e8)        \
-  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, Smi, 0x088599ed)    \
-  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, Dynamic, 0x5f42ca86)\
-  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, Smi, 0x32f3b13b)    \
-  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, Dynamic, 0x7219c45b)\
-  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, Smi,          \
-    0x558481c2)                                                                \
-  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, Dynamic,      \
-    0x5aa9888d)                                                                \
-  V(::, _classRangeCheck, ClassRangeCheck, Bool, 0x2ae76b84)                   \
-  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, Bool, 0x5acdfb75)    \
+  V(::, identical, ObjectIdentical, 0x49c6e96a)                                \
+  V(ClassID, getID, ClassIDgetID, 0x7b18b257)                                  \
+  V(Object, Object., ObjectConstructor, 0x681617fe)                            \
+  V(List, ., ListFactory, 0x629f8324)                                          \
+  V(_List, ., ObjectArrayAllocate, 0x2121902f)                                 \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x7041895a)                    \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x336fa3ea)                  \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x231bbe2e)                  \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x0371785f)                \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x65ab3a20)                  \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x0cb0fcf6)                \
+  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, 0x7db75d78)                  \
+  V(_TypedList, _getUint64, ByteArrayBaseGetUint64, 0x1487cfc6)                \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x6674ea6f)              \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x236c6e7a)              \
+  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x5c367ffb)          \
+  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x772d1c0f)              \
+  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x12bae36a)                    \
+  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, 0x15821cc9)                  \
+  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x1f8237fa)                  \
+  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, 0x181e5d16)                \
+  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x7ddb9f87)                  \
+  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x74094f8d)                \
+  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, 0x4741396e)                  \
+  V(_TypedList, _setUint64, ByteArrayBaseSetUint64, 0x3b398ae4)                \
+  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x03db087b)              \
+  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
+  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
+  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
+  V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435)                 \
+  V(_StringBase, _interpolate, StringBaseInterpolate, 0x01ecb15a)              \
+  V(_IntegerImplementation, toDouble, IntegerToDouble, 0x05da96ed)             \
+  V(_Double, _add, DoubleAdd, 0x2a38277b)                                      \
+  V(_Double, _sub, DoubleSub, 0x4f466391)                                      \
+  V(_Double, _mul, DoubleMul, 0x175e4f66)                                      \
+  V(_Double, _div, DoubleDiv, 0x0854181b)                                      \
+  V(::, min, MathMin, 0x32ebc57d)                                              \
+  V(::, max, MathMax, 0x377e8889)                                              \
+  V(::, _doublePow, MathDoublePow, 0x5add0ec1)                                 \
+  V(::, _intPow, MathIntPow, 0x11b45569)                                       \
+  V(Float32x4, Float32x4., Float32x4Constructor, 0x26ea459b)                   \
+  V(Float32x4, Float32x4.zero, Float32x4Zero, 0x16eca604)                      \
+  V(Float32x4, Float32x4.splat, Float32x4Splat, 0x694e83e3)                    \
+  V(Float32x4, Float32x4.fromInt32x4Bits, Int32x4ToFloat32x4, 0x2f62ebd3)      \
+  V(Float32x4, Float32x4.fromFloat64x2, Float64x2ToFloat32x4, 0x50ed6910)      \
+  V(_Float32x4, shuffle, Float32x4Shuffle, 0x7829101f)                         \
+  V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 0x4182c06b)                   \
+  V(_Float32x4, get:signMask, Float32x4GetSignMask, 0x1d08b351)                \
+  V(_Float32x4, equal, Float32x4Equal, 0x11adb239)                             \
+  V(_Float32x4, greaterThan, Float32x4GreaterThan, 0x48adaf58)                 \
+  V(_Float32x4, greaterThanOrEqual, Float32x4GreaterThanOrEqual, 0x32db94ca)   \
+  V(_Float32x4, lessThan, Float32x4LessThan, 0x425b000c)                       \
+  V(_Float32x4, lessThanOrEqual, Float32x4LessThanOrEqual, 0x0278c2f8)         \
+  V(_Float32x4, notEqual, Float32x4NotEqual, 0x2987cd26)                       \
+  V(_Float32x4, min, Float32x4Min, 0x5ed74b6f)                                 \
+  V(_Float32x4, max, Float32x4Max, 0x68696442)                                 \
+  V(_Float32x4, scale, Float32x4Scale, 0x704e4122)                             \
+  V(_Float32x4, sqrt, Float32x4Sqrt, 0x2c967a6f)                               \
+  V(_Float32x4, reciprocalSqrt, Float32x4ReciprocalSqrt, 0x6264bfe8)           \
+  V(_Float32x4, reciprocal, Float32x4Reciprocal, 0x3cd7e819)                   \
+  V(_Float32x4, unary-, Float32x4Negate, 0x37accb52)                           \
+  V(_Float32x4, abs, Float32x4Abs, 0x471cdd87)                                 \
+  V(_Float32x4, clamp, Float32x4Clamp, 0x2cb30492)                             \
+  V(_Float32x4, withX, Float32x4WithX, 0x4e336aff)                             \
+  V(_Float32x4, withY, Float32x4WithY, 0x0a72b910)                             \
+  V(_Float32x4, withZ, Float32x4WithZ, 0x31e93658)                             \
+  V(_Float32x4, withW, Float32x4WithW, 0x60ddc105)                             \
+  V(Float64x2, Float64x2., Float64x2Constructor, 0x43054b9f)                   \
+  V(Float64x2, Float64x2.zero, Float64x2Zero, 0x4af12f9d)                      \
+  V(Float64x2, Float64x2.splat, Float64x2Splat, 0x134edef0)                    \
+  V(Float64x2, Float64x2.fromFloat32x4, Float32x4ToFloat64x2, 0x17d6b5e4)      \
+  V(_Float64x2, get:x, Float64x2GetX, 0x58c09c58)                              \
+  V(_Float64x2, get:y, Float64x2GetY, 0x3cf5e5b8)                              \
+  V(_Float64x2, unary-, Float64x2Negate, 0x415ca009)                           \
+  V(_Float64x2, abs, Float64x2Abs, 0x031f9e47)                                 \
+  V(_Float64x2, sqrt, Float64x2Sqrt, 0x77f711dd)                               \
+  V(_Float64x2, get:signMask, Float64x2GetSignMask, 0x27deda4b)                \
+  V(_Float64x2, scale, Float64x2Scale, 0x26830a61)                             \
+  V(_Float64x2, withX, Float64x2WithX, 0x1d2bcaf5)                             \
+  V(_Float64x2, withY, Float64x2WithY, 0x383ed6ac)                             \
+  V(_Float64x2, min, Float64x2Min,  0x28d7ddf6)                                \
+  V(_Float64x2, max, Float64x2Max,  0x0bd74e5b)                                \
+  V(Int32x4, Int32x4., Int32x4Constructor, 0x480555a9)                         \
+  V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 0x36aa6963)                 \
+  V(Int32x4, Int32x4.fromFloat32x4Bits, Float32x4ToInt32x4, 0x6715388a)        \
+  V(_Int32x4, get:flagX, Int32x4GetFlagX, 0x56396c82)                          \
+  V(_Int32x4, get:flagY, Int32x4GetFlagY, 0x44704738)                          \
+  V(_Int32x4, get:flagZ, Int32x4GetFlagZ, 0x20d6ff37)                          \
+  V(_Int32x4, get:flagW, Int32x4GetFlagW, 0x5045616a)                          \
+  V(_Int32x4, get:signMask, Int32x4GetSignMask, 0x2c1fb2a3)                    \
+  V(_Int32x4, shuffle, Int32x4Shuffle, 0x20bc0b16)                             \
+  V(_Int32x4, shuffleMix, Int32x4ShuffleMix, 0x5c7056e1)                       \
+  V(_Int32x4, select, Int32x4Select, 0x6b49654f)                               \
+  V(_Int32x4, withFlagX, Int32x4WithFlagX, 0x0ef58fcf)                         \
+  V(_Int32x4, withFlagY, Int32x4WithFlagY, 0x6485a9c4)                         \
+  V(_Int32x4, withFlagZ, Int32x4WithFlagZ, 0x267acdfa)                         \
+  V(_Int32x4, withFlagW, Int32x4WithFlagW, 0x345ac675)                         \
+  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157)               \
+  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0)               \
+  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7a70ac)                 \
+  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x0ec032e8)                 \
+  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x088599ed)         \
+  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x5f42ca86)         \
+  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x32f3b13b)         \
+  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x7219c45b)         \
+  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2)   \
+  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d)   \
+  V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84)                         \
+  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75)          \
 
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
 #define CORE_LIB_INTRINSIC_LIST(V)                                             \
-  V(_Smi, ~, Smi_bitNegate, Smi, 0x67299f4f)                                   \
-  V(_Smi, get:bitLength, Smi_bitLength, Smi, 0x25b3cb0a)                       \
-  V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, Smi, 0x562d5047)                  \
-  V(_BigIntImpl, _lsh, Bigint_lsh, Dynamic, 0x5b6cfc8b)                        \
-  V(_BigIntImpl, _rsh, Bigint_rsh, Dynamic, 0x6ff14a49)                        \
-  V(_BigIntImpl, _absAdd, Bigint_absAdd, Dynamic, 0x5bf14238)                  \
-  V(_BigIntImpl, _absSub, Bigint_absSub, Dynamic, 0x1de5bd32)                  \
-  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, Smi, 0x6f277966)                      \
-  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, Smi, 0x68e4c8ea)                      \
-  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit, Smi,    \
+  V(_Smi, ~, Smi_bitNegate, 0x67299f4f)                                        \
+  V(_Smi, get:bitLength, Smi_bitLength, 0x25b3cb0a)                            \
+  V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, 0x562d5047)                       \
+  V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b)                                 \
+  V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49)                                 \
+  V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238)                           \
+  V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32)                           \
+  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966)                           \
+  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea)                           \
+  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit,         \
     0x35456d91)                                                                \
-  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, Smi, 0x0f7b0375)   \
-  V(_Double, >, Double_greaterThan, Bool, 0x4f1375a3)                          \
-  V(_Double, >=, Double_greaterEqualThan, Bool, 0x4260c184)                    \
-  V(_Double, <, Double_lessThan, Bool, 0x365d1eba)                             \
-  V(_Double, <=, Double_lessEqualThan, Bool, 0x74b5eb64)                       \
-  V(_Double, ==, Double_equal, Bool, 0x613492fc)                               \
-  V(_Double, +, Double_add, Double, 0x53994370)                                \
-  V(_Double, -, Double_sub, Double, 0x3b69d466)                                \
-  V(_Double, *, Double_mul, Double, 0x2bb9bd5d)                                \
-  V(_Double, /, Double_div, Double, 0x483eee28)                                \
-  V(_Double, get:hashCode, Double_hashCode, Dynamic, 0x702b77b7)               \
-  V(_Double, get:_identityHashCode, Double_identityHash, Dynamic, 0x7bda5549)  \
-  V(_Double, get:isNaN, Double_getIsNaN, Bool, 0x0af9d4a9)                     \
-  V(_Double, get:isInfinite, Double_getIsInfinite, Bool, 0x0f7acb47)           \
-  V(_Double, get:isNegative, Double_getIsNegative, Bool, 0x3a59e7f4)           \
-  V(_Double, _mulFromInteger, Double_mulFromInteger, Double, 0x2017fcf6)       \
-  V(_Double, .fromInteger, DoubleFromInteger, Double, 0x6d234f4b)              \
-  V(_GrowableList, .withData, GrowableArray_Allocate, GrowableObjectArray,     \
-    0x28b2138e)                                                                \
-  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x380184b1)          \
-  V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, Dynamic,          \
-    0x79b8f955)                                                                \
-  V(Object, ==, ObjectEquals, Bool, 0x7b32a55a)                                \
-  V(Object, get:runtimeType, ObjectRuntimeType, Type, 0x00e8ab29)              \
-  V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, Bool, 0x4dc50799) \
-  V(_StringBase, get:hashCode, String_getHashCode, Smi, 0x78c3d446)            \
-  V(_StringBase, get:_identityHashCode, String_identityHash, Smi, 0x0472b1d8)  \
-  V(_StringBase, get:isEmpty, StringBaseIsEmpty, Bool, 0x4a8b29c8)             \
-  V(_StringBase, _substringMatches, StringBaseSubstringMatches, Bool,          \
-    0x46de4f10)                                                                \
-  V(_StringBase, [], StringBaseCharAt, Dynamic, 0x7cbb8603)                    \
-  V(_OneByteString, get:hashCode, OneByteString_getHashCode, Smi, 0x78c3d446)  \
+  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375)        \
+  V(_Double, >, Double_greaterThan, 0x4f1375a3)                                \
+  V(_Double, >=, Double_greaterEqualThan, 0x4260c184)                          \
+  V(_Double, <, Double_lessThan, 0x365d1eba)                                   \
+  V(_Double, <=, Double_lessEqualThan, 0x74b5eb64)                             \
+  V(_Double, ==, Double_equal, 0x613492fc)                                     \
+  V(_Double, +, Double_add, 0x53994370)                                        \
+  V(_Double, -, Double_sub, 0x3b69d466)                                        \
+  V(_Double, *, Double_mul, 0x2bb9bd5d)                                        \
+  V(_Double, /, Double_div, 0x483eee28)                                        \
+  V(_Double, get:hashCode, Double_hashCode, 0x702b77b7)                        \
+  V(_Double, get:_identityHashCode, Double_identityHash, 0x7bda5549)           \
+  V(_Double, get:isNaN, Double_getIsNaN, 0x0af9d4a9)                           \
+  V(_Double, get:isInfinite, Double_getIsInfinite, 0x0f7acb47)                 \
+  V(_Double, get:isNegative, Double_getIsNegative, 0x3a59e7f4)                 \
+  V(_Double, _mulFromInteger, Double_mulFromInteger, 0x2017fcf6)               \
+  V(_Double, .fromInteger, DoubleFromInteger, 0x6d234f4b)                      \
+  V(_GrowableList, .withData, GrowableArray_Allocate, 0x28b2138e)              \
+  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0x380184b1)                   \
+  V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0x79b8f955)       \
+  V(Object, ==, ObjectEquals, 0x7b32a55a)                                      \
+  V(Object, get:runtimeType, ObjectRuntimeType, 0x00e8ab29)                    \
+  V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, 0x4dc50799)       \
+  V(_StringBase, get:hashCode, String_getHashCode, 0x78c3d446)                 \
+  V(_StringBase, get:_identityHashCode, String_identityHash, 0x0472b1d8)       \
+  V(_StringBase, get:isEmpty, StringBaseIsEmpty, 0x4a8b29c8)                   \
+  V(_StringBase, _substringMatches, StringBaseSubstringMatches, 0x46de4f10)    \
+  V(_StringBase, [], StringBaseCharAt, 0x7cbb8603)                             \
+  V(_OneByteString, get:hashCode, OneByteString_getHashCode, 0x78c3d446)       \
   V(_OneByteString, _substringUncheckedNative,                                 \
-    OneByteString_substringUnchecked, OneByteString, 0x3538ad86)               \
-  V(_OneByteString, _setAt, OneByteStringSetAt, Dynamic, 0x11ffddd1)           \
-  V(_OneByteString, _allocate, OneByteString_allocate, OneByteString,          \
-    0x74933376)                                                                \
-  V(_OneByteString, ==, OneByteString_equality, Bool, 0x4eda197e)              \
-  V(_TwoByteString, ==, TwoByteString_equality, Bool, 0x4eda197e)              \
-  V(_Type, get:hashCode, Type_getHashCode, Smi, 0x18d1523f)                    \
-  V(::, _getHash, Object_getHash, Smi, 0x2827856d)                             \
-  V(::, _setHash, Object_setHash, Dynamic, 0x690faebd)                         \
+    OneByteString_substringUnchecked,  0x3538ad86)                             \
+  V(_OneByteString, _setAt, OneByteStringSetAt, 0x11ffddd1)                    \
+  V(_OneByteString, _allocate, OneByteString_allocate,          0x74933376)    \
+  V(_OneByteString, ==, OneByteString_equality, 0x4eda197e)                    \
+  V(_TwoByteString, ==, TwoByteString_equality, 0x4eda197e)                    \
+  V(_Type, get:hashCode, Type_getHashCode, 0x18d1523f)                         \
+  V(::, _getHash, Object_getHash, 0x2827856d)                                  \
+  V(::, _setHash, Object_setHash, 0x690faebd)                                  \
 
 
 #define CORE_INTEGER_LIB_INTRINSIC_LIST(V)                                     \
   V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger,           \
-    Dynamic, 0x6a10c54a)                                                       \
-  V(_IntegerImplementation, +, Integer_add, Dynamic, 0x43d53af7)               \
-  V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger, Dynamic,  \
+    0x6a10c54a)                                                                \
+  V(_IntegerImplementation, +, Integer_add, 0x43d53af7)                        \
+  V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger,           \
     0x3fa4b1ed)                                                                \
-  V(_IntegerImplementation, -, Integer_sub, Dynamic, 0x2dc22e03)               \
+  V(_IntegerImplementation, -, Integer_sub, 0x2dc22e03)                        \
   V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger,           \
-    Dynamic, 0x3216e299)                                                       \
-  V(_IntegerImplementation, *, Integer_mul, Dynamic, 0x4e7a1c24)               \
+    0x3216e299)                                                                \
+  V(_IntegerImplementation, *, Integer_mul, 0x4e7a1c24)                        \
   V(_IntegerImplementation, _moduloFromInteger, Integer_moduloFromInteger,     \
-    Dynamic, 0x6348b974)                                                       \
-  V(_IntegerImplementation, ~/, Integer_truncDivide, Dynamic, 0x4efb2d39)      \
-  V(_IntegerImplementation, unary-, Integer_negate, Dynamic, 0x428bf6fa)       \
+     0x6348b974)                                                               \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x4efb2d39)               \
+  V(_IntegerImplementation, unary-, Integer_negate, 0x428bf6fa)                \
   V(_IntegerImplementation, _bitAndFromInteger, Integer_bitAndFromInteger,     \
-    Dynamic, 0x395b1678)                                                       \
-  V(_IntegerImplementation, &, Integer_bitAnd, Dynamic, 0x5ab35f30)            \
+    0x395b1678)                                                                \
+  V(_IntegerImplementation, &, Integer_bitAnd, 0x5ab35f30)                     \
   V(_IntegerImplementation, _bitOrFromInteger, Integer_bitOrFromInteger,       \
-    Dynamic, 0x6a36b395)                                                       \
-  V(_IntegerImplementation, |, Integer_bitOr, Dynamic, 0x267fa107)             \
+    0x6a36b395)                                                                \
+  V(_IntegerImplementation, |, Integer_bitOr, 0x267fa107)                      \
   V(_IntegerImplementation, _bitXorFromInteger, Integer_bitXorFromInteger,     \
-    Dynamic, 0x72da93f0)                                                       \
-  V(_IntegerImplementation, ^, Integer_bitXor, Dynamic, 0x0c7b0230)            \
+    0x72da93f0)                                                                \
+  V(_IntegerImplementation, ^, Integer_bitXor, 0x0c7b0230)                     \
   V(_IntegerImplementation, _greaterThanFromInteger,                           \
-    Integer_greaterThanFromInt, Bool, 0x4a50ed58)                              \
-  V(_IntegerImplementation, >, Integer_greaterThan, Bool, 0x6599a6e1)          \
-  V(_IntegerImplementation, ==, Integer_equal, Bool, 0x58abc487)               \
-  V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger, Bool,     \
+    Integer_greaterThanFromInt, 0x4a50ed58)                                    \
+  V(_IntegerImplementation, >, Integer_greaterThan, 0x6599a6e1)                \
+  V(_IntegerImplementation, ==, Integer_equal, 0x58abc487)                     \
+  V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger,           \
     0x063be842)                                                                \
-  V(_IntegerImplementation, <, Integer_lessThan, Bool, 0x365d1eba)             \
-  V(_IntegerImplementation, <=, Integer_lessEqualThan, Bool, 0x74b5eb64)       \
-  V(_IntegerImplementation, >=, Integer_greaterEqualThan, Bool, 0x4260c184)    \
-  V(_IntegerImplementation, <<, Integer_shl, Dynamic, 0x371c45fa)              \
-  V(_IntegerImplementation, >>, Integer_sar, Dynamic, 0x2b630578)              \
-  V(_Double, toInt, DoubleToInteger, Dynamic, 0x26ef344b)                      \
+  V(_IntegerImplementation, <, Integer_lessThan, 0x365d1eba)                   \
+  V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x74b5eb64)             \
+  V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x4260c184)          \
+  V(_IntegerImplementation, <<, Integer_shl, 0x371c45fa)                       \
+  V(_IntegerImplementation, >>, Integer_sar, 0x2b630578)                       \
+  V(_Double, toInt, DoubleToInteger, 0x26ef344b)                               \
 
 #define MATH_LIB_INTRINSIC_LIST(V)                                             \
-  V(::, sqrt, MathSqrt, Double, 0x70482cf3)                                    \
-  V(_Random, _nextState, Random_nextState, Dynamic, 0x2842c4d5)                \
+  V(::, sqrt, MathSqrt, 0x70482cf3)                                            \
+  V(_Random, _nextState, Random_nextState, 0x2842c4d5)                         \
 
 #define GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                       \
-  V(::, sin, MathSin, Double, 0x6b7bd98c)                                      \
-  V(::, cos, MathCos, Double, 0x459bf5fe)                                      \
-  V(::, tan, MathTan, Double, 0x3bcd772a)                                      \
-  V(::, asin, MathAsin, Double, 0x2ecc2fcd)                                    \
-  V(::, acos, MathAcos, Double, 0x08cf2212)                                    \
-  V(::, atan, MathAtan, Double, 0x1e2731d5)                                    \
-  V(::, atan2, MathAtan2, Double, 0x39f1fa41)                                  \
+  V(::, sin, MathSin, 0x6b7bd98c)                                              \
+  V(::, cos, MathCos, 0x459bf5fe)                                              \
+  V(::, tan, MathTan, 0x3bcd772a)                                              \
+  V(::, asin, MathAsin, 0x2ecc2fcd)                                            \
+  V(::, acos, MathAcos, 0x08cf2212)                                            \
+  V(::, atan, MathAtan, 0x1e2731d5)                                            \
+  V(::, atan2, MathAtan2, 0x39f1fa41)                                          \
 
 #define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
-  V(Int8List, ., TypedData_Int8Array_factory, TypedDataInt8Array, 0x7e39a3a1)  \
-  V(Uint8List, ., TypedData_Uint8Array_factory, TypedDataUint8Array,           \
-    0x3a79adf7)                                                                \
-  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory,                  \
-    TypedDataUint8ClampedArray, 0x67f38395)                                    \
-  V(Int16List, ., TypedData_Int16Array_factory, TypedDataInt16Array,           \
-    0x6477bda8)                                                                \
-  V(Uint16List, ., TypedData_Uint16Array_factory, TypedDataUint16Array,        \
-    0x5707c5a2)                                                                \
-  V(Int32List, ., TypedData_Int32Array_factory, TypedDataInt32Array,           \
-    0x2b96ec0e)                                                                \
-  V(Uint32List, ., TypedData_Uint32Array_factory,                              \
-    TypedDataUint32Array, 0x0c1c0d62)                                          \
-  V(Int64List, ., TypedData_Int64Array_factory,                                \
-    TypedDataInt64Array, 0x279ab485)                                           \
-  V(Uint64List, ., TypedData_Uint64Array_factory,                              \
-    TypedDataUint64Array, 0x7bcb89c2)                                          \
-  V(Float32List, ., TypedData_Float32Array_factory,                            \
-    TypedDataFloat32Array, 0x43506c09)                                         \
-  V(Float64List, ., TypedData_Float64Array_factory,                            \
-    TypedDataFloat64Array, 0x1fde3eaf)                                         \
-  V(Float32x4List, ., TypedData_Float32x4Array_factory,                        \
-    TypedDataFloat32x4Array, 0x4a4030d6)                                       \
-  V(Int32x4List, ., TypedData_Int32x4Array_factory,                            \
-    TypedDataInt32x4Array, 0x6dd02406)                                         \
-  V(Float64x2List, ., TypedData_Float64x2Array_factory,                        \
-    TypedDataFloat64x2Array, 0x688e4e97)                                       \
+  V(Int8List, ., TypedData_Int8Array_factory, 0x7e39a3a1)                      \
+  V(Uint8List, ., TypedData_Uint8Array_factory, 0x3a79adf7)                    \
+  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 0x67f38395)      \
+  V(Int16List, ., TypedData_Int16Array_factory, 0x6477bda8)                    \
+  V(Uint16List, ., TypedData_Uint16Array_factory, 0x5707c5a2)                  \
+  V(Int32List, ., TypedData_Int32Array_factory, 0x2b96ec0e)                    \
+  V(Uint32List, ., TypedData_Uint32Array_factory, 0x0c1c0d62)                  \
+  V(Int64List, ., TypedData_Int64Array_factory, 0x279ab485)                    \
+  V(Uint64List, ., TypedData_Uint64Array_factory, 0x7bcb89c2)                  \
+  V(Float32List, ., TypedData_Float32Array_factory, 0x43506c09)                \
+  V(Float64List, ., TypedData_Float64Array_factory, 0x1fde3eaf)                \
+  V(Float32x4List, ., TypedData_Float32x4Array_factory, 0x4a4030d6)            \
+  V(Int32x4List, ., TypedData_Int32x4Array_factory, 0x6dd02406)                \
+  V(Float64x2List, ., TypedData_Float64x2Array_factory, 0x688e4e97)            \
 
 #define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
-  V(_Int8List, [], Int8ArrayGetIndexed, Smi, 0x49767a2c)                       \
-  V(_Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x24f42cd0)                  \
-  V(_Uint8List, [], Uint8ArrayGetIndexed, Smi, 0x088d86d4)                     \
-  V(_Uint8List, []=, Uint8ArraySetIndexed, Dynamic, 0x12639541)                \
-  V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, Smi, 0x088d86d4)    \
-  V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, Dynamic,           \
-    0x12639541)                                                                \
-  V(_Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x088d86d4)       \
-  V(_Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x6790dba1)  \
+  V(_Int8List, [], Int8ArrayGetIndexed, 0x49767a2c)                            \
+  V(_Int8List, []=, Int8ArraySetIndexed, 0x24f42cd0)                           \
+  V(_Uint8List, [], Uint8ArrayGetIndexed, 0x088d86d4)                          \
+  V(_Uint8List, []=, Uint8ArraySetIndexed, 0x12639541)                         \
+  V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 0x088d86d4)         \
+  V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, 0x12639541)        \
+  V(_Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 0x088d86d4)            \
+  V(_Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 0x6790dba1)           \
   V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
-    Smi, 0x088d86d4)                                                           \
+    0x088d86d4)                                                                \
   V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
-    Dynamic, 0x6790dba1)                                                       \
-  V(_Int16List, [], Int16ArrayGetIndexed, Smi, 0x5ec64948)                     \
-  V(_Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x0e4e8221)                \
-  V(_Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x5f49d093)                   \
-  V(_Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x2efbc90f)              \
-  V(_Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x4bc0d3dd)                 \
-  V(_Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x1adf9823)                \
-  V(_Uint32List, [], Uint32ArrayGetIndexed, Dynamic, 0x188658ce)               \
-  V(_Uint32List, []=, Uint32ArraySetIndexed, Dynamic, 0x01f51a79)              \
-  V(_Int64List, [], Int64ArrayGetIndexed, Dynamic, 0x51eafb97)                 \
-  V(_Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x376181fb)                \
-  V(_Uint64List, [], Uint64ArrayGetIndexed, Dynamic, 0x4b2a1ba2)               \
-  V(_Uint64List, []=, Uint64ArraySetIndexed, Dynamic, 0x5f881bd4)              \
-  V(_Float64List, [], Float64ArrayGetIndexed, Double, 0x0a714486)              \
-  V(_Float64List, []=, Float64ArraySetIndexed, Dynamic, 0x04937367)            \
-  V(_Float32List, [], Float32ArrayGetIndexed, Double, 0x5ade301f)              \
-  V(_Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x0d5c2e2b)            \
-  V(_Float32x4List, [], Float32x4ArrayGetIndexed, Float32x4, 0x128cddeb)       \
-  V(_Float32x4List, []=, Float32x4ArraySetIndexed, Dynamic, 0x7ad55c72)        \
-  V(_Int32x4List, [], Int32x4ArrayGetIndexed, Int32x4, 0x4b78af9c)             \
-  V(_Int32x4List, []=, Int32x4ArraySetIndexed, Dynamic, 0x31453dab)            \
-  V(_Float64x2List, [], Float64x2ArrayGetIndexed, Float64x2, 0x644a0be1)       \
-  V(_Float64x2List, []=, Float64x2ArraySetIndexed, Dynamic, 0x6b836b0b)        \
-  V(_TypedList, get:length, TypedDataLength, Smi, 0x2091c4d8)                  \
-  V(_Float32x4, get:x, Float32x4ShuffleX, Double, 0x63d1a9fd)                  \
-  V(_Float32x4, get:y, Float32x4ShuffleY, Double, 0x203523d9)                  \
-  V(_Float32x4, get:z, Float32x4ShuffleZ, Double, 0x13190678)                  \
-  V(_Float32x4, get:w, Float32x4ShuffleW, Double, 0x698a38de)                  \
-  V(_Float32x4, *, Float32x4Mul, Float32x4, 0x5dec68b2)                        \
-  V(_Float32x4, -, Float32x4Sub, Float32x4, 0x3ea14461)                        \
-  V(_Float32x4, +, Float32x4Add, Float32x4, 0x7ffcf301)                        \
+    0x6790dba1)                                                                \
+  V(_Int16List, [], Int16ArrayGetIndexed, 0x5ec64948)                          \
+  V(_Int16List, []=, Int16ArraySetIndexed, 0x0e4e8221)                         \
+  V(_Uint16List, [], Uint16ArrayGetIndexed, 0x5f49d093)                        \
+  V(_Uint16List, []=, Uint16ArraySetIndexed, 0x2efbc90f)                       \
+  V(_Int32List, [], Int32ArrayGetIndexed, 0x4bc0d3dd)                          \
+  V(_Int32List, []=, Int32ArraySetIndexed, 0x1adf9823)                         \
+  V(_Uint32List, [], Uint32ArrayGetIndexed, 0x188658ce)                        \
+  V(_Uint32List, []=, Uint32ArraySetIndexed, 0x01f51a79)                       \
+  V(_Int64List, [], Int64ArrayGetIndexed, 0x51eafb97)                          \
+  V(_Int64List, []=, Int64ArraySetIndexed, 0x376181fb)                         \
+  V(_Uint64List, [], Uint64ArrayGetIndexed, 0x4b2a1ba2)                        \
+  V(_Uint64List, []=, Uint64ArraySetIndexed, 0x5f881bd4)                       \
+  V(_Float64List, [], Float64ArrayGetIndexed, 0x0a714486)                      \
+  V(_Float64List, []=, Float64ArraySetIndexed, 0x04937367)                     \
+  V(_Float32List, [], Float32ArrayGetIndexed, 0x5ade301f)                      \
+  V(_Float32List, []=, Float32ArraySetIndexed, 0x0d5c2e2b)                     \
+  V(_Float32x4List, [], Float32x4ArrayGetIndexed, 0x128cddeb)                  \
+  V(_Float32x4List, []=, Float32x4ArraySetIndexed, 0x7ad55c72)                 \
+  V(_Int32x4List, [], Int32x4ArrayGetIndexed, 0x4b78af9c)                      \
+  V(_Int32x4List, []=, Int32x4ArraySetIndexed, 0x31453dab)                     \
+  V(_Float64x2List, [], Float64x2ArrayGetIndexed, 0x644a0be1)                  \
+  V(_Float64x2List, []=, Float64x2ArraySetIndexed, 0x6b836b0b)                 \
+  V(_TypedList, get:length, TypedDataLength, 0x2091c4d8)                       \
+  V(_Float32x4, get:x, Float32x4ShuffleX, 0x63d1a9fd)                          \
+  V(_Float32x4, get:y, Float32x4ShuffleY, 0x203523d9)                          \
+  V(_Float32x4, get:z, Float32x4ShuffleZ, 0x13190678)                          \
+  V(_Float32x4, get:w, Float32x4ShuffleW, 0x698a38de)                          \
+  V(_Float32x4, *, Float32x4Mul, 0x5dec68b2)                                   \
+  V(_Float32x4, -, Float32x4Sub, 0x3ea14461)                                   \
+  V(_Float32x4, +, Float32x4Add, 0x7ffcf301)                                   \
 
 #define GRAPH_CORE_INTRINSICS_LIST(V)                                          \
-  V(_List, get:length, ObjectArrayLength, Smi, 0x25952390)                     \
-  V(_List, [], ObjectArrayGetIndexed, Dynamic, 0x653da02e)                     \
-  V(_List, []=, ObjectArraySetIndexed, Dynamic, 0x16b3d2b0)                    \
-  V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, Dynamic, 0x50d64c75)   \
-  V(_ImmutableList, get:length, ImmutableArrayLength, Smi, 0x25952390)         \
-  V(_ImmutableList, [], ImmutableArrayGetIndexed, Dynamic, 0x653da02e)         \
-  V(_GrowableList, get:length, GrowableArrayLength, Smi, 0x18dd86b4)           \
-  V(_GrowableList, get:_capacity, GrowableArrayCapacity, Smi, 0x2e04be60)      \
-  V(_GrowableList, _setData, GrowableArraySetData, Dynamic, 0x3dbea348)        \
-  V(_GrowableList, _setLength, GrowableArraySetLength, Dynamic, 0x753e55da)    \
-  V(_GrowableList, [], GrowableArrayGetIndexed, Dynamic, 0x446fe1f0)           \
-  V(_GrowableList, []=, GrowableArraySetIndexed, Dynamic, 0x40a462ec)          \
-  V(_GrowableList, _setIndexed, GrowableArraySetIndexedUnchecked, Dynamic,     \
-    0x297083df)                                                                \
-  V(_StringBase, get:length, StringBaseLength, Smi, 0x2a2d03d1)                \
-  V(_OneByteString, codeUnitAt, OneByteStringCodeUnitAt, Smi, 0x55a0a1f3)      \
-  V(_TwoByteString, codeUnitAt, TwoByteStringCodeUnitAt, Smi, 0x55a0a1f3)      \
+  V(_List, get:length, ObjectArrayLength, 0x25952390)                          \
+  V(_List, [], ObjectArrayGetIndexed, 0x653da02e)                              \
+  V(_List, []=, ObjectArraySetIndexed, 0x16b3d2b0)                             \
+  V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, 0x50d64c75)            \
+  V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390)              \
+  V(_ImmutableList, [], ImmutableArrayGetIndexed, 0x653da02e)                  \
+  V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4)                \
+  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60)           \
+  V(_GrowableList, _setData, GrowableArraySetData, 0x3dbea348)                 \
+  V(_GrowableList, _setLength, GrowableArraySetLength, 0x753e55da)             \
+  V(_GrowableList, [], GrowableArrayGetIndexed, 0x446fe1f0)                    \
+  V(_GrowableList, []=, GrowableArraySetIndexed, 0x40a462ec)                   \
+  V(_GrowableList, _setIndexed, GrowableArraySetIndexedUnchecked, 0x297083df)  \
+  V(_StringBase, get:length, StringBaseLength, 0x2a2d03d1)                     \
+  V(_OneByteString, codeUnitAt, OneByteStringCodeUnitAt, 0x55a0a1f3)           \
+  V(_TwoByteString, codeUnitAt, TwoByteStringCodeUnitAt, 0x55a0a1f3)           \
   V(_ExternalOneByteString, codeUnitAt, ExternalOneByteStringCodeUnitAt,       \
-    Smi, 0x55a0a1f3)                                                           \
+    0x55a0a1f3)                                                                \
   V(_ExternalTwoByteString, codeUnitAt, ExternalTwoByteStringCodeUnitAt,       \
-    Smi, 0x55a0a1f3)                                                           \
-  V(_Double, unary-, DoubleFlipSignBit, Double, 0x6db4674f)                    \
-  V(_Double, truncateToDouble, DoubleTruncate, Double, 0x2f27e5d3)             \
-  V(_Double, roundToDouble, DoubleRound, Double, 0x2f89c512)                   \
-  V(_Double, floorToDouble, DoubleFloor, Double, 0x6aa87a5f)                   \
-  V(_Double, ceilToDouble, DoubleCeil, Double, 0x1b045e9e)                     \
-  V(_Double, _modulo, DoubleMod, Double, 0x5b8ceed7)
+    0x55a0a1f3)                                                                \
+  V(_Double, unary-, DoubleFlipSignBit, 0x6db4674f)                            \
+  V(_Double, truncateToDouble, DoubleTruncate, 0x2f27e5d3)                     \
+  V(_Double, roundToDouble, DoubleRound, 0x2f89c512)                           \
+  V(_Double, floorToDouble, DoubleFloor, 0x6aa87a5f)                           \
+  V(_Double, ceilToDouble, DoubleCeil, 0x1b045e9e)                             \
+  V(_Double, _modulo, DoubleMod, 0x5b8ceed7)
 
 
 #define GRAPH_INTRINSICS_LIST(V)                                               \
@@ -356,17 +326,14 @@
   GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                             \
 
 #define DEVELOPER_LIB_INTRINSIC_LIST(V)                                        \
-  V(_UserTag, makeCurrent, UserTag_makeCurrent, Dynamic, 0x0b3066fd)           \
-  V(::, _getDefaultTag, UserTag_defaultTag, Dynamic, 0x69f3f1ad)               \
-  V(::, _getCurrentTag, Profiler_getCurrentTag, Dynamic, 0x05fa99d2)           \
-  V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, Dynamic,           \
-    0x72f13f7a)                                                                \
+  V(_UserTag, makeCurrent, UserTag_makeCurrent, 0x0b3066fd)                    \
+  V(::, _getDefaultTag, UserTag_defaultTag, 0x69f3f1ad)                        \
+  V(::, _getCurrentTag, Profiler_getCurrentTag, 0x05fa99d2)                    \
+  V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, 0x72f13f7a)        \
 
 #define ASYNC_LIB_INTRINSIC_LIST(V)                                            \
-  V(::, _clearAsyncThreadStackTrace, ClearAsyncThreadStackTrace,               \
-    Dynamic, 0x2edd4b25)                                                       \
-  V(::, _setAsyncThreadStackTrace, SetAsyncThreadStackTrace,                   \
-    Dynamic, 0x04f429a7)
+  V(::, _clearAsyncThreadStackTrace, ClearAsyncThreadStackTrace, 0x2edd4b25)   \
+  V(::, _setAsyncThreadStackTrace, SetAsyncThreadStackTrace, 0x04f429a7)       \
 
 #define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                  \
   ASYNC_LIB_INTRINSIC_LIST(V)                                                  \
@@ -549,8 +516,7 @@
  public:
   enum Kind {
     kUnknown,
-#define DEFINE_ENUM_LIST(class_name, function_name, enum_name, type, fp)       \
-  k##enum_name,
+#define DEFINE_ENUM_LIST(class_name, function_name, enum_name, fp) k##enum_name,
     RECOGNIZED_LIST(DEFINE_ENUM_LIST)
 #undef DEFINE_ENUM_LIST
         kNumRecognizedMethods
@@ -560,7 +526,23 @@
   static bool AlwaysInline(const Function& function);
   static bool PolymorphicTarget(const Function& function);
   static intptr_t NumArgsCheckedForStaticCall(const Function& function);
-  static intptr_t ResultCid(const Function& function);
+
+  // Try to find an annotation of the form
+  //   @pragma("vm:exact-result-type", int)
+  //   @pragma("vm:exact-result-type", "dart:core#_Smi")
+  // and return the exact cid if found or kDynamicCid otherwise.
+  //
+  // See [result_type_pragma.md].
+  static intptr_t ResultCidFromPragma(const Object& function_or_field);
+
+  // Try to find an annotation of the form
+  //   @pragma("vm:non-nullable-result-type")
+  // and returns true iff `false` was specified in the annotation.
+  //
+  // See [pragmas.md].
+  static bool HasNonNullableResultTypeFromPragma(
+      const Object& function_or_field);
+
   static intptr_t MethodKindToReceiverCid(Kind kind);
   static const char* KindToCString(Kind kind);
 
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 5e11b77..3ea0f09 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -143,12 +143,6 @@
         "a sim* architecture.");
 #endif  // defined(USING_SIMULATOR) || defined(TARGET_ARCH_DBC)
 
-#if defined(TARGET_OS_WINDOWS)
-    // TODO(34393): The interpreter currently relies on computed gotos, which
-    // aren't supported on Windows.
-    return strdup("--enable-interpreter is not supported on Windows.");
-#endif  // defined(TARGET_OS_WINDOWS)
-
     FLAG_use_field_guards = false;
   }
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 031c7a3..e179fca 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1965,6 +1965,18 @@
   return Api::ClassId(object) == kClosureCid;
 }
 
+DART_EXPORT bool Dart_IsTearOff(Dart_Handle object) {
+  DARTSCOPE(Thread::Current());
+  API_TIMELINE_DURATION(T);
+  const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
+  if (obj.IsClosure()) {
+    const Closure& closure = Closure::Cast(obj);
+    const Function& func = Function::Handle(Z, closure.function());
+    return func.IsImplicitClosureFunction();
+  }
+  return false;
+}
+
 DART_EXPORT bool Dart_IsTypedData(Dart_Handle handle) {
   intptr_t cid = Api::ClassId(handle);
   return RawObject::IsTypedDataClassId(cid) ||
@@ -5052,7 +5064,7 @@
         "because it was not annotated with @pragma('vm:entry-point').\n"
         "ERROR: See "
         "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
-        "aot/entry_point_pragma.md",
+        "aot/entry_point_pragma.md\n",
         String::Handle(klass.UserVisibleName()).ToCString());
     UNREACHABLE();
   }
@@ -5602,105 +5614,6 @@
   return Api::Success();
 }
 
-// --- Dart Front-End (Kernel) support ---
-
-DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate) {
-#if defined(DART_PRECOMPILED_RUNTIME)
-  return false;
-#else
-  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
-  return KernelIsolate::IsKernelIsolate(iso);
-#endif
-}
-
-DART_EXPORT bool Dart_KernelIsolateIsRunning() {
-#if defined(DART_PRECOMPILED_RUNTIME)
-  return false;
-#else
-  return KernelIsolate::IsRunning();
-#endif
-}
-
-DART_EXPORT Dart_Port Dart_KernelPort() {
-#if defined(DART_PRECOMPILED_RUNTIME)
-  return false;
-#else
-  return KernelIsolate::KernelPort();
-#endif
-}
-
-DART_EXPORT Dart_KernelCompilationResult
-Dart_CompileToKernel(const char* script_uri,
-                     const uint8_t* platform_kernel,
-                     intptr_t platform_kernel_size,
-                     bool incremental_compile,
-                     const char* package_config) {
-  API_TIMELINE_DURATION(Thread::Current());
-
-  Dart_KernelCompilationResult result;
-#if defined(DART_PRECOMPILED_RUNTIME)
-  result.status = Dart_KernelCompilationStatus_Unknown;
-  result.error = strdup("Dart_CompileToKernel is unsupported.");
-#else
-  result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
-                                          platform_kernel_size, 0, NULL,
-                                          incremental_compile, package_config);
-  if (result.status == Dart_KernelCompilationStatus_Ok) {
-    Dart_KernelCompilationResult accept_result =
-        KernelIsolate::AcceptCompilation();
-    if (accept_result.status != Dart_KernelCompilationStatus_Ok) {
-      FATAL1(
-          "An error occurred in the CFE while accepting the most recent"
-          " compilation results: %s",
-          accept_result.error);
-    }
-  }
-#endif
-  return result;
-}
-
-DART_EXPORT Dart_KernelCompilationResult
-Dart_CompileSourcesToKernel(const char* script_uri,
-                            const uint8_t* platform_kernel,
-                            intptr_t platform_kernel_size,
-                            int source_files_count,
-                            Dart_SourceFile sources[],
-                            bool incremental_compile,
-                            const char* package_config,
-                            const char* multiroot_filepaths,
-                            const char* multiroot_scheme) {
-  Dart_KernelCompilationResult result;
-#if defined(DART_PRECOMPILED_RUNTIME)
-  result.status = Dart_KernelCompilationStatus_Unknown;
-  result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
-#else
-  result = KernelIsolate::CompileToKernel(
-      script_uri, platform_kernel, platform_kernel_size, source_files_count,
-      sources, incremental_compile, package_config, multiroot_filepaths,
-      multiroot_scheme);
-  if (result.status == Dart_KernelCompilationStatus_Ok) {
-    if (KernelIsolate::AcceptCompilation().status !=
-        Dart_KernelCompilationStatus_Ok) {
-      FATAL(
-          "An error occurred in the CFE while accepting the most recent"
-          " compilation results.");
-    }
-  }
-#endif
-  return result;
-}
-
-DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
-  Dart_KernelCompilationResult result;
-#if defined(DART_PRECOMPILED_RUNTIME)
-  result.status = Dart_KernelCompilationStatus_Unknown;
-  result.error = strdup("Dart_KernelListDependencies is unsupported.");
-#else
-  result = KernelIsolate::ListDependencies();
-#endif
-  return result;
-}
-
 // --- Service support ---
 
 DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 1a3ef8a..3a3c425 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -861,6 +861,60 @@
   EXPECT_STREQ(url, lib_url);
 }
 
+TEST_CASE(DartAPI_IsTearOff) {
+  const char* kScriptChars =
+      "int getInt() { return 1; }\n"
+      "getTearOff() => getInt;\n"
+      "Function foo = () { print('baz'); };\n"
+      "class Baz {\n"
+      "  static int foo() => 42;\n"
+      "  getTearOff() => bar;\n"
+      "  int bar() => 24;\n"
+      "}\n"
+      "Baz getBaz() => Baz();\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  EXPECT_VALID(lib);
+
+  // Check tear-off of top-level static method.
+  Dart_Handle get_tear_off = Dart_GetField(lib, NewString("getTearOff"));
+  EXPECT_VALID(get_tear_off);
+  EXPECT(Dart_IsTearOff(get_tear_off));
+  Dart_Handle tear_off = Dart_InvokeClosure(get_tear_off, 0, NULL);
+  EXPECT_VALID(tear_off);
+  EXPECT(Dart_IsTearOff(tear_off));
+
+  // Check anonymous closures are not considered tear-offs.
+  Dart_Handle anonymous_closure = Dart_GetField(lib, NewString("foo"));
+  EXPECT_VALID(anonymous_closure);
+  EXPECT(!Dart_IsTearOff(anonymous_closure));
+
+  Dart_Handle baz_cls = Dart_GetClass(lib, NewString("Baz"));
+  EXPECT_VALID(baz_cls);
+
+  // Check tear-off for a static method in a class.
+  Dart_Handle closure =
+      Dart_GetStaticMethodClosure(lib, baz_cls, NewString("foo"));
+  EXPECT_VALID(closure);
+  EXPECT(Dart_IsTearOff(closure));
+
+  // Flutter will use Dart_IsTearOff in conjunction with Dart_ClosureFunction
+  // and Dart_FunctionIsStatic to prevent anonymous closures from being used to
+  // generate callback handles. We'll test that case here, just to be sure.
+  Dart_Handle function = Dart_ClosureFunction(closure);
+  EXPECT_VALID(function);
+  bool is_static = false;
+  Dart_Handle result = Dart_FunctionIsStatic(function, &is_static);
+  EXPECT_VALID(result);
+  EXPECT(is_static);
+
+  // Check tear-off for an instance method in a class.
+  Dart_Handle instance = Dart_Invoke(lib, NewString("getBaz"), 0, NULL);
+  EXPECT_VALID(instance);
+  closure = Dart_Invoke(instance, NewString("getTearOff"), 0, NULL);
+  EXPECT_VALID(closure);
+  EXPECT(Dart_IsTearOff(closure));
+}
+
 TEST_CASE(DartAPI_FunctionIsStatic) {
   const char* kScriptChars =
       "int getInt() { return 1; }\n"
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index e348558..677be143 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -167,8 +167,8 @@
 
 // Now Call the invoke stub which will invoke the dart function.
 #if !defined(TARGET_ARCH_DBC)
-  invokestub entrypoint = reinterpret_cast<invokestub>(
-      StubCode::InvokeDartCode_entry()->EntryPoint());
+  invokestub entrypoint =
+      reinterpret_cast<invokestub>(StubCode::InvokeDartCode().EntryPoint());
 #endif
   const Code& code = Code::Handle(zone, function.CurrentCode());
   ASSERT(!code.IsNull());
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 6823611..4fafda8 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -2037,7 +2037,7 @@
         break;
       }
       if (async_stack_trace.CodeAtFrame(i) ==
-          StubCode::AsynchronousGapMarker_entry()->code()) {
+          StubCode::AsynchronousGapMarker().raw()) {
         stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
         // The frame immediately below the asynchronous gap marker is the
         // identical to the frame above the marker. Skip the frame to enhance
@@ -2251,7 +2251,7 @@
         break;
       }
       if (async_stack_trace.CodeAtFrame(i) ==
-          StubCode::AsynchronousGapMarker_entry()->code()) {
+          StubCode::AsynchronousGapMarker().raw()) {
         stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
         // The frame immediately below the asynchronous gap marker is the
         // identical to the frame above the marker. Skip the frame to enhance
@@ -3722,7 +3722,7 @@
   }
   Thread* thread = Thread::Current();
   thread->set_resume_pc(frame->pc());
-  uword deopt_stub_pc = StubCode::DeoptForRewind_entry()->EntryPoint();
+  uword deopt_stub_pc = StubCode::DeoptForRewind().EntryPoint();
   Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(),
                           true /* clear lazy deopt at target */);
   UNREACHABLE();
diff --git a/runtime/vm/debugger_arm.cc b/runtime/vm/debugger_arm.cc
index ee75cd7..3eafa74 100644
--- a/runtime/vm/debugger_arm.cc
+++ b/runtime/vm/debugger_arm.cc
@@ -25,10 +25,10 @@
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = StubCode::ICCallBreakpoint_entry()->code();
+      stub_target = StubCode::ICCallBreakpoint().raw();
       break;
     case RawPcDescriptors::kRuntimeCall:
-      stub_target = StubCode::RuntimeCallBreakpoint_entry()->code();
+      stub_target = StubCode::RuntimeCallBreakpoint().raw();
       break;
     default:
       UNREACHABLE();
diff --git a/runtime/vm/debugger_arm64.cc b/runtime/vm/debugger_arm64.cc
index 4d53e7c..48ed9c2 100644
--- a/runtime/vm/debugger_arm64.cc
+++ b/runtime/vm/debugger_arm64.cc
@@ -25,10 +25,10 @@
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = StubCode::ICCallBreakpoint_entry()->code();
+      stub_target = StubCode::ICCallBreakpoint().raw();
       break;
     case RawPcDescriptors::kRuntimeCall: {
-      stub_target = StubCode::RuntimeCallBreakpoint_entry()->code();
+      stub_target = StubCode::RuntimeCallBreakpoint().raw();
       break;
     }
     default:
diff --git a/runtime/vm/debugger_ia32.cc b/runtime/vm/debugger_ia32.cc
index 8dadc22..d74202c 100644
--- a/runtime/vm/debugger_ia32.cc
+++ b/runtime/vm/debugger_ia32.cc
@@ -33,12 +33,12 @@
     switch (breakpoint_kind_) {
       case RawPcDescriptors::kIcCall:
       case RawPcDescriptors::kUnoptStaticCall: {
-        stub_target = StubCode::ICCallBreakpoint_entry()->code();
+        stub_target = StubCode::ICCallBreakpoint().raw();
         break;
       }
       case RawPcDescriptors::kRuntimeCall: {
         saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
-        stub_target = StubCode::RuntimeCallBreakpoint_entry()->code();
+        stub_target = StubCode::RuntimeCallBreakpoint().raw();
         break;
       }
       default:
diff --git a/runtime/vm/debugger_x64.cc b/runtime/vm/debugger_x64.cc
index a1f395c..39cf91c 100644
--- a/runtime/vm/debugger_x64.cc
+++ b/runtime/vm/debugger_x64.cc
@@ -27,10 +27,10 @@
   switch (breakpoint_kind_) {
     case RawPcDescriptors::kIcCall:
     case RawPcDescriptors::kUnoptStaticCall:
-      stub_target = StubCode::ICCallBreakpoint_entry()->code();
+      stub_target = StubCode::ICCallBreakpoint().raw();
       break;
     case RawPcDescriptors::kRuntimeCall:
-      stub_target = StubCode::RuntimeCallBreakpoint_entry()->code();
+      stub_target = StubCode::RuntimeCallBreakpoint().raw();
       break;
     default:
       UNREACHABLE();
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 7d082c7..7015a75 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -742,8 +742,8 @@
     if (function.IsNull()) {
       *reinterpret_cast<RawObject**>(dest_addr) =
           deopt_context->is_lazy_deopt()
-              ? StubCode::DeoptimizeLazyFromReturn_entry()->code()
-              : StubCode::Deoptimize_entry()->code();
+              ? StubCode::DeoptimizeLazyFromReturn().raw()
+              : StubCode::Deoptimize().raw();
       return;
     }
 
@@ -753,7 +753,7 @@
     // materialization to maintain the invariant that Dart frames always have
     // a pc marker.
     *reinterpret_cast<RawObject**>(dest_addr) =
-        StubCode::FrameAwaitingMaterialization_entry()->code();
+        StubCode::FrameAwaitingMaterialization().raw();
     deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr);
   }
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 123870a..7a857cc 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -449,8 +449,7 @@
         (*pending_deopts)[i].set_pc(program_counter);
 
         // Jump to the deopt stub instead of the catch handler.
-        program_counter =
-            StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint();
+        program_counter = StubCode::DeoptimizeLazyFromThrow().EntryPoint();
         if (FLAG_trace_deoptimization) {
           THR_Print("Throwing to frame scheduled for lazy deopt fp=%" Pp "\n",
                     frame_pointer);
@@ -517,7 +516,7 @@
   thread->set_active_exception(exception_object);
   thread->set_active_stacktrace(stacktrace_object);
   thread->set_resume_pc(remapped_pc);
-  uword run_exception_pc = StubCode::RunExceptionHandler_entry()->EntryPoint();
+  uword run_exception_pc = StubCode::RunExceptionHandler().EntryPoint();
   Exceptions::JumpToFrame(thread, run_exception_pc, stack_pointer,
                           frame_pointer, false /* do not clear deopt */);
 }
@@ -564,8 +563,8 @@
   // to set up the stacktrace object in kStackTraceObjectReg, and to
   // continue execution at the given pc in the given frame.
   typedef void (*ExcpHandler)(uword, uword, uword, Thread*);
-  ExcpHandler func = reinterpret_cast<ExcpHandler>(
-      StubCode::JumpToFrame_entry()->EntryPoint());
+  ExcpHandler func =
+      reinterpret_cast<ExcpHandler>(StubCode::JumpToFrame().EntryPoint());
 
   // Unpoison the stack before we tear it down in the generated stub code.
   uword current_sp = OSThread::GetCurrentStackPointer() - 1024;
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index 12815bf..859174e 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -13,6 +13,11 @@
 
 namespace dart {
 
+DEFINE_FLAG(bool,
+            force_evacuation,
+            false,
+            "Force compaction to move every movable object");
+
 static const intptr_t kBitVectorWordsPerBlock = 1;
 static const intptr_t kBlockSize =
     kObjectAlignment * kBitsPerWord * kBitVectorWordsPerBlock;
@@ -203,6 +208,26 @@
     ASSERT(task_index == num_tasks);
   }
 
+  if (FLAG_force_evacuation) {
+    // Inject empty pages at the beginning of each worker's list to ensure all
+    // objects move and all pages that used to have an object are released.
+    // This can be helpful for finding untracked pointers because it prevents
+    // an untracked pointer from getting lucky with its target not moving.
+    for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
+      const intptr_t pages_per_task = num_pages / num_tasks;
+      for (intptr_t j = 0; j < pages_per_task; j++) {
+        HeapPage* page = heap_->old_space()->AllocatePage(HeapPage::kData,
+                                                          /* link */ false);
+        FreeListElement::AsElement(page->object_start(),
+                                   page->object_end() - page->object_start());
+
+        // The compactor slides down: add the empty pages to the beginning.
+        page->set_next(heads[task_index]);
+        heads[task_index] = page;
+      }
+    }
+  }
+
   {
     ThreadBarrier barrier(num_tasks + 1, heap_->barrier(),
                           heap_->barrier_done());
@@ -251,6 +276,7 @@
       tails[task_index]->set_next(heads[task_index + 1]);
     }
     tails[num_tasks - 1]->set_next(NULL);
+    heap_->old_space()->pages_ = pages = heads[0];
     heap_->old_space()->pages_tail_ = tails[num_tasks - 1];
 
     delete[] heads;
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 18b8fc9..3145090 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -55,14 +55,14 @@
         // code from the function.
         if (FLAG_enable_interpreter && Function::HasBytecode(func)) {
           func->StorePointer(&(func->ptr()->code_),
-                             StubCode::InterpretCall_entry()->code());
-          uword entry_point = StubCode::InterpretCall_entry()->EntryPoint();
+                             StubCode::InterpretCall().raw());
+          uword entry_point = StubCode::InterpretCall().EntryPoint();
           func->ptr()->entry_point_ = entry_point;
           func->ptr()->unchecked_entry_point_ = entry_point;
         } else {
           func->StorePointer(&(func->ptr()->code_),
-                             StubCode::LazyCompile_entry()->code());
-          uword entry_point = StubCode::LazyCompile_entry()->EntryPoint();
+                             StubCode::LazyCompile().raw());
+          uword entry_point = StubCode::LazyCompile().EntryPoint();
           func->ptr()->entry_point_ = entry_point;
           func->ptr()->unchecked_entry_point_ = entry_point;
         }
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index e30089a..8e769bf4 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -288,7 +288,7 @@
   return page_size >> kWordSizeLog2;
 }
 
-HeapPage* PageSpace::AllocatePage(HeapPage::PageType type) {
+HeapPage* PageSpace::AllocatePage(HeapPage::PageType type, bool link) {
   const bool is_exec = (type == HeapPage::kExecutable);
   const intptr_t kVmNameSize = 128;
   char vm_name[kVmNameSize];
@@ -301,31 +301,34 @@
   }
 
   MutexLocker ml(pages_lock_);
-  if (!is_exec) {
-    if (pages_ == NULL) {
-      pages_ = page;
+  if (link) {
+    if (!is_exec) {
+      if (pages_ == NULL) {
+        pages_ = page;
+      } else {
+        pages_tail_->set_next(page);
+      }
+      pages_tail_ = page;
     } else {
-      pages_tail_->set_next(page);
-    }
-    pages_tail_ = page;
-  } else {
-    // Should not allocate executable pages when running from a precompiled
-    // snapshot.
-    ASSERT(Dart::vm_snapshot_kind() != Snapshot::kFullAOT);
+      // Should not allocate executable pages when running from a precompiled
+      // snapshot.
+      ASSERT(Dart::vm_snapshot_kind() != Snapshot::kFullAOT);
 
-    if (exec_pages_ == NULL) {
-      exec_pages_ = page;
-    } else {
-      if (FLAG_write_protect_code) {
-        exec_pages_tail_->WriteProtect(false);
+      if (exec_pages_ == NULL) {
+        exec_pages_ = page;
+      } else {
+        if (FLAG_write_protect_code) {
+          exec_pages_tail_->WriteProtect(false);
+        }
+        exec_pages_tail_->set_next(page);
+        if (FLAG_write_protect_code) {
+          exec_pages_tail_->WriteProtect(true);
+        }
       }
-      exec_pages_tail_->set_next(page);
-      if (FLAG_write_protect_code) {
-        exec_pages_tail_->WriteProtect(true);
-      }
+      exec_pages_tail_ = page;
     }
-    exec_pages_tail_ = page;
   }
+
   IncreaseCapacityInWordsLocked(kPageSizeInWords);
   page->set_object_end(page->memory_->end());
   return page;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 95d8f19..4f93e24 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -436,7 +436,7 @@
                                     bool is_locked);
   // Makes bump block walkable; do not call concurrently with mutator.
   void MakeIterable() const;
-  HeapPage* AllocatePage(HeapPage::PageType type);
+  HeapPage* AllocatePage(HeapPage::PageType type, bool link = true);
   void FreePage(HeapPage* page, HeapPage* previous_page);
   HeapPage* AllocateLargePage(intptr_t size, HeapPage::PageType type);
   void TruncateLargePage(HeapPage* page, intptr_t new_object_size_in_bytes);
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 5a48fb4..f61c467 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -268,8 +268,12 @@
   }
 
   // Append the direct-mapped RO data objects after the clustered snapshot.
+  offset_space_ = vm ? V8SnapshotProfileWriter::kVmData
+                     : V8SnapshotProfileWriter::kIsolateData;
   WriteROData(clustered_stream);
 
+  offset_space_ = vm ? V8SnapshotProfileWriter::kVmText
+                     : V8SnapshotProfileWriter::kIsolateText;
   WriteText(clustered_stream, vm);
 }
 
@@ -278,14 +282,19 @@
 
   // Heap page starts here.
 
+  intptr_t section_start = stream->Position();
+
   stream->WriteWord(next_data_offset_);  // Data length.
   COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
   stream->Align(OS::kMaxPreferredCodeAlignment);
 
+  ASSERT(stream->Position() - section_start == Image::kHeaderSize);
+
   // Heap page objects start here.
 
   for (intptr_t i = 0; i < objects_.length(); i++) {
     const Object& obj = *objects_[i].obj_;
+    AutoTraceImage(section_start, stream, "ROData");
 
     NoSafepointScope no_safepoint;
     uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
@@ -370,10 +379,21 @@
   ObjectStore* object_store = Isolate::Current()->object_store();
 
   TypeTestingStubFinder tts;
+  intptr_t offset = Image::kHeaderSize;
   for (intptr_t i = 0; i < instructions_.length(); i++) {
     const Instructions& insns = *instructions_[i].insns_;
     const Code& code = *instructions_[i].code_;
 
+    if (profile_writer_ != nullptr) {
+      ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot);
+      profile_writer_->SetObjectTypeAndName({offset_space_, offset},
+                                            "Instructions",
+                                            /*name=*/nullptr);
+      profile_writer_->AttributeBytesTo({offset_space_, offset},
+                                        insns.raw()->Size());
+    }
+    offset += insns.raw()->Size();
+
     ASSERT(insns.raw()->Size() % sizeof(uint64_t) == 0);
 
     // 1. Write from the header to the entry point.
@@ -595,6 +615,7 @@
   NoSafepointScope no_safepoint;
   for (intptr_t i = 0; i < instructions_.length(); i++) {
     const Instructions& insns = *instructions_[i].insns_;
+    AutoTraceImage(0, &this->instructions_blob_stream_, "Instructions");
 
     uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
     uword entry = beginning + Instructions::HeaderSize();
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 16f83f7..33c0956 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -5,12 +5,15 @@
 #ifndef RUNTIME_VM_IMAGE_SNAPSHOT_H_
 #define RUNTIME_VM_IMAGE_SNAPSHOT_H_
 
+#include <utility>
+
 #include "platform/assert.h"
 #include "vm/allocation.h"
 #include "vm/datastream.h"
 #include "vm/globals.h"
 #include "vm/growable_array.h"
 #include "vm/hash_map.h"
+#include "vm/v8_snapshot_writer.h"
 
 namespace dart {
 
@@ -120,6 +123,14 @@
 
   void DumpStatistics();
 
+  void SetProfileWriter(V8SnapshotProfileWriter* profile_writer) {
+    profile_writer_ = profile_writer;
+  }
+
+  void ClearProfileWriter() { profile_writer_ = nullptr; }
+
+  void TraceInstructions(const Instructions& instructions);
+
  protected:
   void WriteROData(WriteStream* stream);
   virtual void WriteText(WriteStream* clustered_stream, bool vm) = 0;
@@ -162,10 +173,56 @@
   ObjectOffsetMap shared_instructions_;
   ObjectOffsetMap reuse_instructions_;
 
+  V8SnapshotProfileWriter::IdSpace offset_space_ =
+      V8SnapshotProfileWriter::kSnapshot;
+  V8SnapshotProfileWriter* profile_writer_ = nullptr;
+
+  template <class T>
+  friend class TraceImageObjectScope;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ImageWriter);
 };
 
+#define AutoTraceImage(section_offset, stream, type_name)                      \
+  auto AutoTraceImagObjectScopeVar##__COUNTER__ =                              \
+      TraceImageObjectScope<std::remove_pointer<decltype(stream)>::type>(      \
+          this, section_offset, stream, type_name);
+
+template <typename T>
+class TraceImageObjectScope {
+ public:
+  TraceImageObjectScope(ImageWriter* writer,
+                        intptr_t section_offset,
+                        const T* stream,
+                        const char* type)
+      : writer_(writer),
+        stream_(stream),
+        section_offset_(section_offset),
+        start_offset_(stream_->Position() - section_offset) {
+    if (writer_->profile_writer_ != nullptr) {
+      ASSERT(writer_->offset_space_ != V8SnapshotProfileWriter::kSnapshot);
+      writer_->profile_writer_->SetObjectTypeAndName(
+          {writer_->offset_space_, start_offset_}, type, nullptr);
+    }
+  }
+
+  ~TraceImageObjectScope() {
+    if (writer_->profile_writer_ != nullptr) {
+      ASSERT(writer_->offset_space_ != V8SnapshotProfileWriter::kSnapshot);
+      writer_->profile_writer_->AttributeBytesTo(
+          {writer_->offset_space_, start_offset_},
+          stream_->Position() - section_offset_ - start_offset_);
+    }
+  }
+
+ private:
+  ImageWriter* writer_;
+  const T* stream_;
+  intptr_t section_offset_;
+  intptr_t start_offset_;
+};
+
 class AssemblyImageWriter : public ImageWriter {
  public:
   AssemblyImageWriter(Thread* thread,
diff --git a/runtime/vm/instructions_arm64_test.cc b/runtime/vm/instructions_arm64_test.cc
index 89cca60..4a6528c 100644
--- a/runtime/vm/instructions_arm64_test.cc
+++ b/runtime/vm/instructions_arm64_test.cc
@@ -18,7 +18,7 @@
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
   // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
   __ set_constant_pool_allowed(true);
-  __ BranchLinkPatchable(*StubCode::InvokeDartCode_entry());
+  __ BranchLinkPatchable(StubCode::InvokeDartCode());
   __ ret();
 }
 
@@ -28,7 +28,7 @@
   // before the end of the code buffer.
   uword end = test->payload_start() + test->code().Size();
   CallPattern call(end - Instr::kInstrSize, test->code());
-  EXPECT_EQ(StubCode::InvokeDartCode_entry()->code(), call.TargetCode());
+  EXPECT_EQ(StubCode::InvokeDartCode().raw(), call.TargetCode());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/instructions_arm_test.cc b/runtime/vm/instructions_arm_test.cc
index 44749a7..e9fc409 100644
--- a/runtime/vm/instructions_arm_test.cc
+++ b/runtime/vm/instructions_arm_test.cc
@@ -18,7 +18,7 @@
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
   // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
   __ set_constant_pool_allowed(true);
-  __ BranchLinkPatchable(*StubCode::InvokeDartCode_entry());
+  __ BranchLinkPatchable(StubCode::InvokeDartCode());
   __ Ret();
 }
 
@@ -28,7 +28,7 @@
   // before the end of the code buffer.
   uword end = test->payload_start() + test->code().Size();
   CallPattern call(end - Instr::kInstrSize, test->code());
-  EXPECT_EQ(StubCode::InvokeDartCode_entry()->code(), call.TargetCode());
+  EXPECT_EQ(StubCode::InvokeDartCode().raw(), call.TargetCode());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/instructions_ia32_test.cc b/runtime/vm/instructions_ia32_test.cc
index 7aef6ca..9fcdb39 100644
--- a/runtime/vm/instructions_ia32_test.cc
+++ b/runtime/vm/instructions_ia32_test.cc
@@ -17,14 +17,14 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  __ call(&StubCode::InvokeDartCode_entry()->label());
+  ExternalLabel label(StubCode::InvokeDartCode().EntryPoint());
+  __ call(&label);
   __ ret();
 }
 
 ASSEMBLER_TEST_RUN(Call, test) {
   CallPattern call(test->entry());
-  EXPECT_EQ(StubCode::InvokeDartCode_entry()->EntryPoint(),
-            call.TargetAddress());
+  EXPECT_EQ(StubCode::InvokeDartCode().EntryPoint(), call.TargetAddress());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/instructions_x64_test.cc b/runtime/vm/instructions_x64_test.cc
index 831d694..255b290 100644
--- a/runtime/vm/instructions_x64_test.cc
+++ b/runtime/vm/instructions_x64_test.cc
@@ -15,7 +15,7 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  __ Call(*StubCode::InvokeDartCode_entry());
+  __ Call(StubCode::InvokeDartCode());
   __ ret();
 }
 
@@ -26,8 +26,8 @@
   __ pushq(PP);
   __ LoadPoolPointer();
   prologue_code_size = assembler->CodeSize();
-  __ JmpPatchable(*StubCode::InvokeDartCode_entry(), PP);
-  __ JmpPatchable(*StubCode::AllocateArray_entry(), PP);
+  __ JmpPatchable(StubCode::InvokeDartCode(), PP);
+  __ JmpPatchable(StubCode::AllocateArray(), PP);
   __ popq(PP);
   __ ret();
 }
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 09bee58..a921f60 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -6,7 +6,7 @@
 #include <stdlib.h>
 
 #include "vm/globals.h"
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_OS_WINDOWS)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 
 #include "vm/interpreter.h"
 
@@ -31,7 +31,6 @@
             trace_interpreter_after,
             ULLONG_MAX,
             "Trace interpreter execution after instruction count reached.");
-
 DEFINE_FLAG(charp,
             interpreter_trace_file,
             NULL,
@@ -41,9 +40,6 @@
             100 * MB,
             "Maximum size in bytes of the interpreter trace file");
 
-#define LIKELY(cond) __builtin_expect((cond), 1)
-#define UNLIKELY(cond) __builtin_expect((cond), 0)
-
 // InterpreterSetjmpBuffer are linked together, and the last created one
 // is referenced by the Interpreter. When an exception is thrown, the exception
 // runtime looks at where to jump and finds the corresponding
@@ -761,7 +757,7 @@
 #endif
   ASSERT(Function::HasCode(function));
   RawCode* volatile code = function->ptr()->code_;
-  ASSERT(code != StubCode::LazyCompile_entry()->code());
+  ASSERT(code != StubCode::LazyCompile().raw());
   // TODO(regis): Once we share the same stack, try to invoke directly.
 #if defined(DEBUG)
   if (IsTracingExecution()) {
@@ -773,7 +769,7 @@
   typedef RawObject* (*invokestub)(RawCode * code, RawArray * argdesc,
                                    RawObject * *arg0, Thread * thread);
   invokestub volatile entrypoint = reinterpret_cast<invokestub>(
-      StubCode::InvokeDartCodeFromBytecode_entry()->EntryPoint());
+      StubCode::InvokeDartCodeFromBytecode().EntryPoint());
   RawObject* volatile result;
   Exit(thread, *FP, call_top + 1, *pc);
   {
@@ -1286,6 +1282,7 @@
 
 // Decode opcode and A part of the given value and dispatch to the
 // corresponding bytecode handler.
+#ifdef DART_HAS_COMPUTED_GOTO
 #define DISPATCH_OP(val)                                                       \
   do {                                                                         \
     op = (val);                                                                \
@@ -1293,6 +1290,15 @@
     TRACE_INSTRUCTION                                                          \
     goto* dispatch[op & 0xFF];                                                 \
   } while (0)
+#else
+#define DISPATCH_OP(val)                                                       \
+  do {                                                                         \
+    op = (val);                                                                \
+    rA = ((op >> 8) & 0xFF);                                                   \
+    TRACE_INSTRUCTION                                                          \
+    goto SwitchDispatch;                                                       \
+  } while (0)
+#endif
 
 // Fetch next operation from PC, increment program counter and dispatch.
 #define DISPATCH() DISPATCH_OP(*pc++)
@@ -1580,14 +1586,6 @@
                              intptr_t argc,
                              RawObject* const* argv,
                              Thread* thread) {
-  // Dispatch used to interpret bytecode. Contains addresses of
-  // labels of bytecode handlers. Handlers themselves are defined below.
-  static const void* dispatch[] = {
-#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
-      KERNEL_BYTECODES_LIST(TARGET)
-#undef TARGET
-  };
-
   // Interpreter state (see constants_kbc.h for high-level overview).
   uint32_t* pc;    // Program Counter: points to the next op to execute.
   RawObject** FP;  // Frame Pointer.
@@ -1688,8 +1686,26 @@
   Function& function_h = Function::Handle();
 #endif
 
-  // Enter the dispatch loop.
-  DISPATCH();
+#ifdef DART_HAS_COMPUTED_GOTO
+  static const void* dispatch[] = {
+#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
+      KERNEL_BYTECODES_LIST(TARGET)
+#undef TARGET
+  };
+  DISPATCH();  // Enter the dispatch loop.
+#else
+  DISPATCH();  // Enter the dispatch loop.
+SwitchDispatch:
+  switch (op & 0xFF) {
+#define TARGET(name, fmt, fmta, fmtb, fmtc)                                    \
+  case KernelBytecode::k##name:                                                \
+    goto bc##name;
+    KERNEL_BYTECODES_LIST(TARGET)
+#undef TARGET
+    default:
+      FATAL1("Undefined opcode: %d\n", op);
+  }
+#endif
 
   // KernelBytecode handlers (see constants_kbc.h for bytecode descriptions).
   {
@@ -3007,7 +3023,7 @@
 
   fp_ = reinterpret_cast<RawObject**>(fp);
 
-  if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) {
+  if (pc == StubCode::RunExceptionHandler().EntryPoint()) {
     // The RunExceptionHandler stub is a placeholder.  We implement
     // its behavior here.
     RawObject* raw_exception = thread->active_exception();
@@ -3033,4 +3049,4 @@
 
 }  // namespace dart
 
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_OS_WINDOWS)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 6150561..badbffd 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -83,7 +83,7 @@
   uword get_pc() const { return pc_; }
 
   enum IntrinsicId {
-#define V(test_class_name, test_function_name, enum_name, type, fp)            \
+#define V(test_class_name, test_function_name, enum_name, fp)                  \
   k##enum_name##Intrinsic,
     ALL_INTRINSICS_LIST(V) GRAPH_INTRINSICS_LIST(V)
 #undef V
diff --git a/runtime/vm/interpreter_unsupported.cc b/runtime/vm/interpreter_unsupported.cc
deleted file mode 100644
index 757e9b4..0000000
--- a/runtime/vm/interpreter_unsupported.cc
+++ /dev/null
@@ -1,168 +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.
-
-#include "vm/globals.h"
-#if !defined(DART_PRECOMPILED_RUNTIME) && defined(TARGET_OS_WINDOWS)
-
-#include "vm/interpreter.h"
-
-#include "platform/assert.h"
-#include "vm/object.h"
-
-namespace dart {
-
-IntrinsicHandler Interpreter::intrinsics_[Interpreter::kIntrinsicCount];
-
-void Interpreter::InitOnce() {
-  UNIMPLEMENTED();
-}
-
-Interpreter::Interpreter() {
-  UNIMPLEMENTED();
-}
-
-Interpreter::~Interpreter() {
-  UNIMPLEMENTED();
-}
-
-Interpreter* Interpreter::Current() {
-  UNIMPLEMENTED();
-  return NULL;
-}
-
-#if defined(DEBUG)
-bool Interpreter::IsTracingExecution() const {
-  UNIMPLEMENTED();
-  return false;
-}
-
-void Interpreter::TraceInstruction(uint32_t* pc) const {
-  UNIMPLEMENTED();
-}
-#endif  // defined(DEBUG)
-
-void Interpreter::Exit(Thread* thread,
-                       RawObject** base,
-                       RawObject** frame,
-                       uint32_t* pc) {
-  UNIMPLEMENTED();
-}
-
-void Interpreter::CallRuntime(Thread* thread,
-                              RawObject** base,
-                              RawObject** exit_frame,
-                              uint32_t* pc,
-                              intptr_t argc_tag,
-                              RawObject** args,
-                              RawObject** result,
-                              uword target) {
-  UNIMPLEMENTED();
-}
-
-bool Interpreter::InvokeCompiled(Thread* thread,
-                                 RawFunction* function,
-                                 RawObject** call_base,
-                                 RawObject** call_top,
-                                 uint32_t** pc,
-                                 RawObject*** FP,
-                                 RawObject*** SP) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-bool Interpreter::ProcessInvocation(bool* invoked,
-                                    Thread* thread,
-                                    RawFunction* function,
-                                    RawObject** call_base,
-                                    RawObject** call_top,
-                                    uint32_t** pc,
-                                    RawObject*** FP,
-                                    RawObject*** SP) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-bool Interpreter::Invoke(Thread* thread,
-                         RawObject** call_base,
-                         RawObject** call_top,
-                         uint32_t** pc,
-                         RawObject*** FP,
-                         RawObject*** SP) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-void Interpreter::InlineCacheMiss(int checked_args,
-                                  Thread* thread,
-                                  RawICData* icdata,
-                                  RawObject** args,
-                                  RawObject** top,
-                                  uint32_t* pc,
-                                  RawObject** FP,
-                                  RawObject** SP) {
-  UNIMPLEMENTED();
-}
-
-bool Interpreter::InstanceCall1(Thread* thread,
-                                RawICData* icdata,
-                                RawObject** call_base,
-                                RawObject** top,
-                                uint32_t** pc,
-                                RawObject*** FP,
-                                RawObject*** SP,
-                                bool optimized) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-bool Interpreter::InstanceCall2(Thread* thread,
-                                RawICData* icdata,
-                                RawObject** call_base,
-                                RawObject** top,
-                                uint32_t** pc,
-                                RawObject*** FP,
-                                RawObject*** SP,
-                                bool optimized) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-bool Interpreter::AssertAssignable(Thread* thread,
-                                   uint32_t* pc,
-                                   RawObject** FP,
-                                   RawObject** call_top,
-                                   RawObject** args,
-                                   RawSubtypeTestCache* cache) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-RawObject* Interpreter::Call(const Function& function,
-                             const Array& arguments_descriptor,
-                             const Array& arguments,
-                             Thread* thread) {
-  UNIMPLEMENTED();
-  return NULL;
-}
-
-RawObject* Interpreter::Call(RawFunction* function,
-                             RawArray* argdesc,
-                             intptr_t argc,
-                             RawObject* const* argv,
-                             Thread* thread) {
-  UNIMPLEMENTED();
-  return NULL;
-}
-
-void Interpreter::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
-  UNIMPLEMENTED();
-}
-
-void Interpreter::VisitObjectPointers(ObjectPointerVisitor* visitor) {
-  UNIMPLEMENTED();
-}
-
-}  // namespace dart
-
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) && defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 94187e8..3c3f3d1 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -925,6 +925,8 @@
           new Mutex(NOT_IN_PRODUCT("Isolate::kernel_data_lib_cache_mutex_"))),
       kernel_data_class_cache_mutex_(
           new Mutex(NOT_IN_PRODUCT("Isolate::kernel_data_class_cache_mutex_"))),
+      kernel_constants_mutex_(
+          new Mutex(NOT_IN_PRODUCT("Isolate::kernel_constants_mutex_"))),
       message_handler_(NULL),
       spawn_state_(NULL),
       defer_finalization_count_(0),
@@ -1005,6 +1007,8 @@
   constant_canonicalization_mutex_ = NULL;
   delete megamorphic_lookup_mutex_;
   megamorphic_lookup_mutex_ = NULL;
+  delete kernel_constants_mutex_;
+  kernel_constants_mutex_ = nullptr;
   delete kernel_data_lib_cache_mutex_;
   kernel_data_lib_cache_mutex_ = NULL;
   delete kernel_data_class_cache_mutex_;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index ebb648a..27fde4b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -357,6 +357,10 @@
     return kernel_data_class_cache_mutex_;
   }
 
+  // Any access to constants arrays must be locked since mutator and
+  // background compiler can access the arrays at the same time.
+  Mutex* kernel_constants_mutex() const { return kernel_constants_mutex_; }
+
 #if !defined(PRODUCT)
   Debugger* debugger() const {
     ASSERT(debugger_ != NULL);
@@ -959,6 +963,7 @@
   Mutex* megamorphic_lookup_mutex_;  // Protects megamorphic table lookup.
   Mutex* kernel_data_lib_cache_mutex_;
   Mutex* kernel_data_class_cache_mutex_;
+  Mutex* kernel_constants_mutex_;
   MessageHandler* message_handler_;
   IsolateSpawnState* spawn_state_;
   intptr_t defer_finalization_count_;
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index 082bc48..35e6a7d 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -7,6 +7,7 @@
 
 #include "include/dart_tools_api.h"
 
+#include "bin/kernel_isolate.h"
 #include "vm/globals.h"
 #include "vm/growable_array.h"
 #include "vm/hash_map.h"
diff --git a/runtime/vm/json_writer.cc b/runtime/vm/json_writer.cc
index 7c3aa7f..c3760a8 100644
--- a/runtime/vm/json_writer.cc
+++ b/runtime/vm/json_writer.cc
@@ -298,6 +298,10 @@
   buffer_.AddChar(':');
 }
 
+void JSONWriter::PrintNewline() {
+  buffer_.AddChar('\n');
+}
+
 void JSONWriter::PrintCommaIfNeeded() {
   if (NeedComma()) {
     buffer_.AddChar(',');
diff --git a/runtime/vm/json_writer.h b/runtime/vm/json_writer.h
index b556869..c9d4375 100644
--- a/runtime/vm/json_writer.h
+++ b/runtime/vm/json_writer.h
@@ -74,6 +74,8 @@
 
   void PrintPropertyName(const char* name);
 
+  void PrintNewline();
+
   void AddEscapedUTF8String(const char* s);
   void AddEscapedUTF8String(const char* s, intptr_t len);
 
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index a271351..ed610c5 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -8,6 +8,7 @@
 #include "include/dart_api.h"
 #include "include/dart_native_api.h"
 
+#include "bin/kernel_isolate.h"
 #include "vm/allocation.h"
 #include "vm/dart.h"
 #include "vm/os_thread.h"
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index aab97e8a..b68203a 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -953,9 +953,6 @@
       ReadVMAnnotations(annotation_count, &native_name_unused,
                         &is_potential_native_unused, &has_pragma_annotation);
     }
-    if (has_pragma_annotation) {
-      toplevel_class.set_has_pragma(true);
-    }
     field_helper.SetJustRead(FieldHelper::kAnnotations);
 
     field_helper.ReadUntilExcluding(FieldHelper::kType);
@@ -969,6 +966,7 @@
         Field::NewTopLevel(name, is_final, field_helper.IsConst(), script_class,
                            field_helper.position_, field_helper.end_position_));
     field.set_kernel_offset(field_offset);
+    field.set_has_pragma(has_pragma_annotation);
     const AbstractType& type = T.BuildType();  // read type.
     field.SetFieldType(type);
     ReadInferredType(field, field_offset + library_kernel_offset_);
@@ -1344,9 +1342,6 @@
         ReadVMAnnotations(annotation_count, &native_name_unused,
                           &is_potential_native_unused, &has_pragma_annotation);
       }
-      if (has_pragma_annotation) {
-        klass.set_has_pragma(true);
-      }
       field_helper.SetJustRead(FieldHelper::kAnnotations);
 
       field_helper.ReadUntilExcluding(FieldHelper::kType);
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index f0de736..7c2a30a 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -39,7 +39,7 @@
 #define CHECK_STACK_ALIGNMENT                                                  \
   {                                                                            \
     uword (*func)() = reinterpret_cast<uword (*)()>(                           \
-        StubCode::GetCStackPointer_entry()->EntryPoint());                     \
+        StubCode::GetCStackPointer().EntryPoint());                            \
     uword current_sp = func();                                                 \
     ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()));      \
   }
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index f6ac51b..ff77ded 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -296,8 +296,7 @@
               reinterpret_cast<uword>(LinkNativeCall),
               Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)));
 #endif
-      ASSERT(current_trampoline.raw() ==
-             StubCode::CallBootstrapNative_entry()->code());
+      ASSERT(current_trampoline.raw() == StubCode::CallBootstrapNative().raw());
     }
 #endif
 
@@ -333,7 +332,7 @@
     } else {
       Code& trampoline = Code::Handle(zone);
       if (is_bootstrap_native) {
-        trampoline = StubCode::CallBootstrapNative_entry()->code();
+        trampoline = StubCode::CallBootstrapNative().raw();
 #if defined(USING_SIMULATOR)
         patch_target_function = reinterpret_cast<NativeFunction>(
             Simulator::RedirectExternalReference(
@@ -341,9 +340,9 @@
                 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments));
 #endif  // defined USING_SIMULATOR
       } else if (is_auto_scope) {
-        trampoline = StubCode::CallAutoScopeNative_entry()->code();
+        trampoline = StubCode::CallAutoScopeNative().raw();
       } else {
-        trampoline = StubCode::CallNoScopeNative_entry()->code();
+        trampoline = StubCode::CallNoScopeNative().raw();
       }
       CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
                                      patch_target_function, trampoline);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 34da421..c81689d 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2911,27 +2911,49 @@
   return result.raw();
 }
 
-bool Function::FindPragma(Isolate* I,
-                          const String& pragma_name,
-                          Object* options) const {
-  if (!has_pragma()) return false;
+bool Library::FindPragma(Thread* T,
+                         const Object& obj,
+                         const String& pragma_name,
+                         Object* options) const {
+  auto I = T->isolate();
+  auto Z = T->zone();
+  auto& lib = Library::Handle(Z);
+  if (obj.IsClass()) {
+    auto& klass = Class::Cast(obj);
+    if (!klass.has_pragma()) return false;
+    lib = klass.library();
+  } else if (obj.IsFunction()) {
+    auto& function = Function::Cast(obj);
+    if (!function.has_pragma()) return false;
+    lib = Class::Handle(Z, function.Owner()).library();
+  } else if (obj.IsField()) {
+    auto& field = Field::Cast(obj);
+    if (!field.has_pragma()) return false;
+    lib = Class::Handle(Z, field.Owner()).library();
+  } else {
+    UNREACHABLE();
+  }
 
-  auto& klass = Class::Handle(Owner());
-  auto& lib = Library::Handle(klass.library());
+  Object& metadata_obj = Object::Handle(Z, lib.GetMetadata(obj));
+  if (metadata_obj.IsUnwindError()) {
+    Report::LongJump(UnwindError::Cast(metadata_obj));
+  }
 
-  auto& pragma_class =
-      Class::Handle(Isolate::Current()->object_store()->pragma_class());
+  // If there is a compile-time error while evaluating the metadata, we will
+  // simply claim there was no @pramga annotation.
+  if (metadata_obj.IsNull() || metadata_obj.IsLanguageError()) {
+    return false;
+  }
+  ASSERT(metadata_obj.IsArray());
+
+  auto& metadata = Array::Cast(metadata_obj);
+  auto& pragma_class = Class::Handle(Z, I->object_store()->pragma_class());
   auto& pragma_name_field =
-      Field::Handle(pragma_class.LookupField(Symbols::name()));
+      Field::Handle(Z, pragma_class.LookupField(Symbols::name()));
   auto& pragma_options_field =
-      Field::Handle(pragma_class.LookupField(Symbols::options()));
+      Field::Handle(Z, pragma_class.LookupField(Symbols::options()));
 
-  Array& metadata = Array::Handle();
-  metadata ^= lib.GetMetadata(Function::Handle(raw()));
-
-  if (metadata.IsNull()) return false;
-
-  auto& pragma = Object::Handle();
+  auto& pragma = Object::Handle(Z);
   for (intptr_t i = 0; i < metadata.Length(); ++i) {
     pragma = metadata.At(i);
     if (pragma.clazz() != pragma_class.raw() ||
@@ -3685,6 +3707,18 @@
 
   CLASS_LIST_WITH_NULL(ADD_SET_FIELD)
 #undef ADD_SET_FIELD
+
+#define ADD_SET_FIELD(clazz)                                                   \
+  field_name = Symbols::New(thread, "cid" #clazz "View");                      \
+  field = Field::New(field_name, true, false, true, false, *this,              \
+                     Type::Handle(Type::IntType()), TokenPosition::kMinSource, \
+                     TokenPosition::kMinSource);                               \
+  value = Smi::New(kTypedData##clazz##ViewCid);                                \
+  field.SetStaticValue(value, true);                                           \
+  AddField(field);
+
+  CLASS_LIST_TYPED_DATA(ADD_SET_FIELD)
+#undef ADD_SET_FIELD
 #undef CLASS_LIST_WITH_NULL
 }
 
@@ -5857,10 +5891,10 @@
   NoSafepointScope no_safepoint;
   ASSERT(raw_ptr()->code_ != Code::null());
 #if defined(DART_PRECOMPILED_RUNTIME)
-  return raw_ptr()->code_ != StubCode::LazyCompile_entry()->code();
+  return raw_ptr()->code_ != StubCode::LazyCompile().raw();
 #else
-  return raw_ptr()->code_ != StubCode::LazyCompile_entry()->code() &&
-         raw_ptr()->code_ != StubCode::InterpretCall_entry()->code();
+  return raw_ptr()->code_ != StubCode::LazyCompile().raw() &&
+         raw_ptr()->code_ != StubCode::InterpretCall().raw();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -5914,7 +5948,7 @@
 
   if (FLAG_enable_interpreter) {
     // Set the code entry_point to InterpretCall stub.
-    SetInstructions(Code::Handle(StubCode::InterpretCall_entry()->code()));
+    SetInstructions(StubCode::InterpretCall());
   }
 }
 
@@ -5931,10 +5965,10 @@
   NoSafepointScope no_safepoint;
   ASSERT(function->ptr()->code_ != Code::null());
 #if defined(DART_PRECOMPILED_RUNTIME)
-  return function->ptr()->code_ != StubCode::LazyCompile_entry()->code();
+  return function->ptr()->code_ != StubCode::LazyCompile().raw();
 #else
-  return function->ptr()->code_ != StubCode::LazyCompile_entry()->code() &&
-         function->ptr()->code_ != StubCode::InterpretCall_entry()->code();
+  return function->ptr()->code_ != StubCode::LazyCompile().raw() &&
+         function->ptr()->code_ != StubCode::InterpretCall().raw();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -5947,7 +5981,7 @@
   StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
   StorePointer(&raw_ptr()->bytecode_, Bytecode::null());
 
-  SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
+  SetInstructions(StubCode::LazyCompile());
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -6008,10 +6042,10 @@
     // Set the lazy compile or interpreter call stub code.
     if (FLAG_enable_interpreter && HasBytecode()) {
       TIR_Print("Switched to interpreter call stub for %s\n", ToCString());
-      SetInstructions(Code::Handle(StubCode::InterpretCall_entry()->code()));
+      SetInstructions(StubCode::InterpretCall());
     } else {
       TIR_Print("Switched to lazy compile stub for %s\n", ToCString());
-      SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
+      SetInstructions(StubCode::LazyCompile());
     }
     return;
   }
@@ -7413,8 +7447,7 @@
   result.set_is_optimizable(is_native ? false : true);
   result.set_is_background_optimizable(is_native ? false : true);
   result.set_is_inlinable(true);
-  result.SetInstructionsSafe(
-      Code::Handle(StubCode::LazyCompile_entry()->code()));
+  result.SetInstructionsSafe(StubCode::LazyCompile());
   if (kind == RawFunction::kClosureFunction ||
       kind == RawFunction::kImplicitClosureFunction) {
     ASSERT(space == Heap::kOld);
@@ -12467,7 +12500,7 @@
     CHECK_FINGERPRINT3(func, class_name, function_name, dest, fp);             \
   }
 
-#define CHECK_FINGERPRINTS2(class_name, function_name, dest, type, fp)         \
+#define CHECK_FINGERPRINTS2(class_name, function_name, dest, fp)               \
   CHECK_FINGERPRINTS(class_name, function_name, dest, fp)
 
   all_libs.Add(&Library::ZoneHandle(Library::CoreLibrary()));
@@ -14993,8 +15026,7 @@
   DEBUG_ASSERT(IsMutatorOrAtSafepoint());
   ASSERT(IsFunctionCode());
   ASSERT(instructions() == active_instructions());
-  const Code& new_code =
-      Code::Handle(StubCode::FixCallersTarget_entry()->code());
+  const Code& new_code = StubCode::FixCallersTarget();
   SetActiveInstructions(Instructions::Handle(new_code.instructions()));
   StoreNonPointer(&raw_ptr()->unchecked_entry_point_, raw_ptr()->entry_point_);
 }
@@ -15004,8 +15036,7 @@
   ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(IsAllocationStubCode());
   ASSERT(instructions() == active_instructions());
-  const Code& new_code =
-      Code::Handle(StubCode::FixAllocationStubTarget_entry()->code());
+  const Code& new_code = StubCode::FixAllocationStubTarget();
   SetActiveInstructions(Instructions::Handle(new_code.instructions()));
   StoreNonPointer(&raw_ptr()->unchecked_entry_point_, raw_ptr()->entry_point_);
 #else
@@ -22157,8 +22188,7 @@
           // To account for gap frames.
           frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i));
         }
-      } else if (code_object.raw() ==
-                 StubCode::AsynchronousGapMarker_entry()->code()) {
+      } else if (code_object.raw() == StubCode::AsynchronousGapMarker().raw()) {
         buffer.AddString("<asynchronous suspension>\n");
         // The frame immediately after the asynchronous gap marker is the
         // identical to the frame above the marker. Skip the frame to enhance
@@ -22246,8 +22276,7 @@
           // To account for gap frames.
           frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i));
         }
-      } else if (code.raw() ==
-                 StubCode::AsynchronousGapMarker_entry()->code()) {
+      } else if (code.raw() == StubCode::AsynchronousGapMarker().raw()) {
         buffer.AddString("<asynchronous suspension>\n");
         // The frame immediately after the asynchronous gap marker is the
         // identical to the frame above the marker. Skip the frame to enhance
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 5e72677..2e65d5d 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2234,6 +2234,9 @@
   RawAbstractType* result_type() const { return raw_ptr()->result_type_; }
   void set_result_type(const AbstractType& value) const;
 
+  // The parameters, starting with NumImplicitParameters() parameters which are
+  // only visible to the VM, but not to Dart users.
+  // Note that type checks exclude implicit parameters.
   RawAbstractType* ParameterTypeAt(intptr_t index) const;
   void SetParameterTypeAt(intptr_t index, const AbstractType& value) const;
   RawArray* parameter_types() const { return raw_ptr()->parameter_types_; }
@@ -2280,8 +2283,6 @@
   // Return true if any parent function of this function is generic.
   bool HasGenericParent() const;
 
-  bool FindPragma(Isolate* I, const String& pragma_name, Object* options) const;
-
   // Not thread-safe; must be called in the main thread.
   // Sets function's code and code's function.
   void InstallOptimizedCode(const Code& code) const;
@@ -3825,6 +3826,18 @@
                          const Function& to_fun) const;
   RawObject* GetMetadata(const Object& obj) const;
 
+  // Tries to finds a @pragma annotation on [object].
+  //
+  // If successful returns `true`. If an error happens during constant
+  // evaluation, returns `false.
+  //
+  // WARNING: If the isolate received an [UnwindError] this function will not
+  // return and rather unwinds until the enclosing setjmp() handler.
+  bool FindPragma(Thread* T,
+                  const Object& object,
+                  const String& pragma_name,
+                  Object* options) const;
+
   RawClass* toplevel_class() const { return raw_ptr()->toplevel_class_; }
   void set_toplevel_class(const Class& value) const;
 
@@ -4443,6 +4456,7 @@
   friend class Code;
   friend class AssemblyImageWriter;
   friend class BlobImageWriter;
+  friend class ImageWriter;
 };
 
 class LocalVarDescriptors : public Object {
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 70094af..1034547 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -269,7 +269,7 @@
 }
 
 void OS::Exit(int code) {
-  UNIMPLEMENTED();
+  exit(code);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index fbb891a..4cb44d8 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -622,8 +622,8 @@
 
 #if !defined(TARGET_ARCH_DBC)
       RawCode* marker = PCMarker(in_interpreted_frame);
-      if (marker == StubCode::InvokeDartCode_entry()->code() ||
-          marker == StubCode::InvokeDartCodeFromBytecode_entry()->code()) {
+      if (marker == StubCode::InvokeDartCode().raw() ||
+          marker == StubCode::InvokeDartCodeFromBytecode().raw()) {
         // During the prologue of a function, CallerPC will return the caller's
         // caller. For most frames, the missing PC will be added during profile
         // processing. However, during this stack walk, it can cause us to fail
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index cdb5d63..3f9ef48 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -282,7 +282,9 @@
   SNAPSHOT_WRITER_SUPPORT()                                                    \
   HEAP_PROFILER_SUPPORT()                                                      \
   friend class object##SerializationCluster;                                   \
-  friend class object##DeserializationCluster;
+  friend class object##DeserializationCluster;                                 \
+  friend class Serializer;                                                     \
+  friend class Deserializer;
 
 // RawObject is the base class of all raw objects; even though it carries the
 // tags_ field not all raw objects are allocated in the heap and thus cannot
@@ -1142,6 +1144,7 @@
   RawFunction* parent_function_;  // Enclosing function of this sig. function.
   RawType* signature_type_;
   VISIT_TO(RawObject*, signature_type_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class Function;
 };
@@ -1155,6 +1158,7 @@
   RawString* identifier_;
   RawFunction* target_;
   VISIT_TO(RawObject*, target_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawField : public RawObject {
@@ -1340,6 +1344,7 @@
   RawField* metadata_field_;  // remembers the token pos of metadata if any,
                               // and the metadata values if computed.
   VISIT_TO(RawObject*, metadata_field_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawKernelProgramInfo : public RawObject {
@@ -1475,6 +1480,7 @@
   RawExceptionHandlers* exception_handlers_;
   RawPcDescriptors* pc_descriptors_;
   VISIT_TO(RawObject*, pc_descriptors_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   intptr_t source_positions_binary_offset_;
 
@@ -1796,6 +1802,9 @@
     // 'end' is the address just beyond the last descriptor, so step back.
     return reinterpret_cast<RawObject**>(end - kWordSize);
   }
+  RawObject** to_snapshot(Snapshot::Kind kind, intptr_t num_vars) {
+    return to(num_vars);
+  }
 
   friend class Object;
   friend class RawClosureData;
@@ -1818,6 +1827,7 @@
   RawString* target_name_;
   RawArray* args_descriptor_;
   VISIT_TO(RawObject*, args_descriptor_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawICData : public RawObject {
@@ -1867,6 +1877,7 @@
   RawString* target_name_;     // Name of target function.
   RawArray* args_descriptor_;  // Arguments descriptor.
   VISIT_TO(RawObject*, args_descriptor_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   int32_t filled_entry_count_;
 };
@@ -1902,6 +1913,8 @@
   TokenPosition token_pos_;  // Source position in script_.
   bool report_after_token_;  // Report message at or after the token.
   int8_t kind_;              // Of type Report::Kind.
+
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawUnhandledException : public RawError {
@@ -1911,6 +1924,7 @@
   RawInstance* exception_;
   RawInstance* stacktrace_;
   VISIT_TO(RawObject*, stacktrace_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawUnwindError : public RawError {
@@ -2031,6 +2045,8 @@
   TokenPosition token_pos_;
   int8_t type_state_;
 
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
+
   friend class CidRewriteVisitor;
   friend class RawTypeArguments;
 };
@@ -2042,6 +2058,7 @@
   VISIT_FROM(RawObject*, type_)
   RawAbstractType* type_;  // The referenced type.
   VISIT_TO(RawObject*, type_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawTypeParameter : public RawAbstractType {
@@ -2059,6 +2076,8 @@
   int16_t index_;
   int8_t type_state_;
 
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
+
   friend class CidRewriteVisitor;
 };
 
@@ -2072,6 +2091,7 @@
   RawSmi* hash_;
   RawTypeParameter* type_parameter_;  // For more detailed error reporting.
   VISIT_TO(RawObject*, type_parameter_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class RawMixinAppType : public RawAbstractType {
@@ -2103,6 +2123,8 @@
 
   VISIT_TO(RawCompressed, hash_)
 
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
+
   // Note that instantiator_type_arguments_, function_type_arguments_ and
   // delayed_type_arguments_ are used to instantiate the signature of function_
   // when this closure is involved in a type test. In other words, these fields
@@ -2277,6 +2299,7 @@
   RawSmi* length_;
   RawArray* data_;
   VISIT_TO(RawCompressed, data_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class SnapshotReader;
 };
@@ -2425,6 +2448,7 @@
   RawArray* code_array_;       // Code object for each frame in the stack trace.
   RawArray* pc_offset_array_;  // Offset of PC for each frame.
   VISIT_TO(RawObject*, pc_offset_array_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   // False for pre-allocated stack trace (used in OOM and Stack overflow).
   bool expand_inlined_;
@@ -2458,6 +2482,7 @@
   RawFunction* external_one_byte_sticky_function_;
   RawFunction* external_two_byte_sticky_function_;
   VISIT_TO(RawObject*, external_two_byte_sticky_function_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   intptr_t num_registers_;
 
@@ -2474,6 +2499,7 @@
   RawObject* key_;
   RawObject* value_;
   VISIT_TO(RawObject*, value_)
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   // Linked list is chaining all pending weak properties.
   // Untyped to make it clear that it is not to be visited by GC.
diff --git a/runtime/vm/report.cc b/runtime/vm/report.cc
index f681530..980fedc 100644
--- a/runtime/vm/report.cc
+++ b/runtime/vm/report.cc
@@ -120,6 +120,14 @@
                        TokenPosition token_pos,
                        const char* format,
                        va_list args) {
+  // If an isolate is being killed a [UnwindError] will be propagated up the
+  // stack. In such a case we cannot wrap the unwind error in a new
+  // [LanguageError]. Instead we simply continue propagating the [UnwindError]
+  // upwards.
+  if (prev_error.IsUnwindError()) {
+    LongJump(prev_error);
+    UNREACHABLE();
+  }
   const Error& error = Error::Handle(LanguageError::NewFormattedV(
       prev_error, script, token_pos, Report::AtLocation, kError, Heap::kOld,
       format, args));
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index f5676de..1ff2d59 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1408,8 +1408,7 @@
   }
 
   // Call site is not single target, switch to call using ICData.
-  const Code& stub =
-      Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
+  const Code& stub = StubCode::ICCallThroughCode();
   ASSERT(!Isolate::Current()->compilation_allowed());
   CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
                                      stub);
@@ -1474,8 +1473,7 @@
   }
 
   // Patch to call through stub.
-  const Code& stub =
-      Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
+  const Code& stub = StubCode::ICCallThroughCode();
   ASSERT(!Isolate::Current()->compilation_allowed());
   CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
                                      stub);
@@ -1559,8 +1557,7 @@
       cache.set_entry_point(code.EntryPoint());
       cache.set_lower_limit(lower);
       cache.set_upper_limit(upper);
-      const Code& stub =
-          Code::Handle(zone, StubCode::SingleTargetCall_entry()->code());
+      const Code& stub = StubCode::SingleTargetCall();
       CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, cache,
                                          stub);
       // Return the ICData. The miss stub will jump to continue in the IC call
@@ -1571,8 +1568,7 @@
   }
 
   // Patch to call through stub.
-  const Code& stub =
-      Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
+  const Code& stub = StubCode::ICCallThroughCode();
   ASSERT(!Isolate::Current()->compilation_allowed());
   CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
                                      stub);
@@ -1666,8 +1662,7 @@
         ASSERT(caller_frame->IsDartFrame());
         const Code& caller_code =
             Code::Handle(zone, caller_frame->LookupDartCode());
-        const Code& stub =
-            Code::Handle(zone, StubCode::MegamorphicCall_entry()->code());
+        const Code& stub = StubCode::MegamorphicCall();
 
         CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
                                            cache, stub);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 0c6002c..2c7f573 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -41,9 +41,6 @@
             ULLONG_MAX,
             "Instruction address or instruction count to stop simulator at.");
 
-#define LIKELY(cond) __builtin_expect((cond), 1)
-#define UNLIKELY(cond) __builtin_expect((cond), 0)
-
 // SimulatorSetjmpBuffer are linked together, and the last created one
 // is referenced by the Simulator. When an exception is thrown, the exception
 // runtime looks at where to jump and finds the corresponding
@@ -995,6 +992,7 @@
 
 // Decode opcode and A part of the given value and dispatch to the
 // corresponding bytecode handler.
+#ifdef DART_HAS_COMPUTED_GOTO
 #define DISPATCH_OP(val)                                                       \
   do {                                                                         \
     op = (val);                                                                \
@@ -1002,6 +1000,15 @@
     TRACE_INSTRUCTION                                                          \
     goto* dispatch[op & 0xFF];                                                 \
   } while (0)
+#else
+#define DISPATCH_OP(val)                                                       \
+  do {                                                                         \
+    op = (val);                                                                \
+    rA = ((op >> 8) & 0xFF);                                                   \
+    TRACE_INSTRUCTION                                                          \
+    goto SwitchDispatch;                                                       \
+  } while (0)
+#endif
 
 // Fetch next operation from PC, increment program counter and dispatch.
 #define DISPATCH() DISPATCH_OP(*pc++)
@@ -1203,14 +1210,6 @@
                            const Array& arguments_descriptor,
                            const Array& arguments,
                            Thread* thread) {
-  // Dispatch used to interpret bytecode. Contains addresses of
-  // labels of bytecode handlers. Handlers themselves are defined below.
-  static const void* dispatch[] = {
-#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
-      BYTECODES_LIST(TARGET)
-#undef TARGET
-  };
-
   // Interpreter state (see constants_dbc.h for high-level overview).
   uint32_t* pc;       // Program Counter: points to the next op to execute.
   RawObject** FP;     // Frame Pointer.
@@ -1287,8 +1286,26 @@
   Function& function_h = Function::Handle();
 #endif
 
-  // Enter the dispatch loop.
-  DISPATCH();
+#ifdef DART_HAS_COMPUTED_GOTO
+  static const void* dispatch[] = {
+#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
+      BYTECODES_LIST(TARGET)
+#undef TARGET
+  };
+  DISPATCH();  // Enter the dispatch loop.
+#else
+  DISPATCH();  // Enter the dispatch loop.
+SwitchDispatch:
+  switch (op & 0xFF) {
+#define TARGET(name, fmt, fmta, fmtb, fmtc)                                    \
+  case SimulatorBytecode::k##name:                                             \
+    goto bc##name;
+    BYTECODES_LIST(TARGET)
+#undef TARGET
+    default:
+      FATAL1("Undefined opcode: %d\n", op);
+  }
+#endif
 
   // Bytecode handlers (see constants_dbc.h for bytecode descriptions).
   {
@@ -1374,9 +1391,9 @@
       // Make the DRT_OptimizeInvokedFunction see a stub as its caller for
       // consistency with the other architectures, and to avoid needing to
       // generate a stackmap for the HotCheck pc.
-      const StubEntry* stub = StubCode::OptimizeFunction_entry();
-      FP[kPcMarkerSlotFromFp] = stub->code();
-      pc = reinterpret_cast<uint32_t*>(stub->EntryPoint());
+      const Code& stub = StubCode::OptimizeFunction();
+      FP[kPcMarkerSlotFromFp] = stub.raw();
+      pc = reinterpret_cast<uint32_t*>(stub.EntryPoint());
 
       Exit(thread, FP, FP + 3, pc);
       NativeArguments args(thread, 1, /*argv=*/FP, /*retval=*/FP + 1);
@@ -3971,7 +3988,7 @@
 
   fp_ = reinterpret_cast<RawObject**>(fp);
 
-  if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) {
+  if (pc == StubCode::RunExceptionHandler().EntryPoint()) {
     // The RunExceptionHandler stub is a placeholder.  We implement
     // its behavior here.
     RawObject* raw_exception = thread->active_exception();
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
index 95a0a35..18aee10 100644
--- a/runtime/vm/simulator_dbc.h
+++ b/runtime/vm/simulator_dbc.h
@@ -67,7 +67,7 @@
   uword get_pc() const { return reinterpret_cast<uword>(pc_); }
 
   enum IntrinsicId {
-#define V(test_class_name, test_function_name, enum_name, type, fp)            \
+#define V(test_class_name, test_function_name, enum_name, fp)                  \
   k##enum_name##Intrinsic,
     ALL_INTRINSICS_LIST(V) GRAPH_INTRINSICS_LIST(V)
 #undef V
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 0ffe5da..85ba367 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -114,11 +114,11 @@
     ASSERT(!is_interpreted());
     uword raw_pc =
         *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize));
-    return raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint();
+    return raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint();
   }
   void MarkForLazyDeopt() {
     ASSERT(!is_interpreted());
-    set_pc(StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint());
+    set_pc(StubCode::DeoptimizeLazyFromReturn().EntryPoint());
   }
   void UnmarkForLazyDeopt() {
     // If this frame was marked for lazy deopt, pc_ was computed to be the
@@ -126,8 +126,7 @@
     // Write this value back into the frame.
     ASSERT(!is_interpreted());
     uword original_pc = pc();
-    ASSERT(original_pc !=
-           StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint());
+    ASSERT(original_pc != StubCode::DeoptimizeLazyFromReturn().EntryPoint());
     set_pc(original_pc);
   }
 
@@ -210,8 +209,8 @@
         fp() + ((is_interpreted() ? kKBCSavedCallerPcSlotFromFp
                                   : kSavedCallerPcSlotFromFp) *
                 kWordSize)));
-    ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint());
-    if (raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()) {
+    ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow().EntryPoint());
+    if (raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint()) {
       return isolate()->FindPendingDeopt(GetCallerFp());
     }
     return raw_pc;
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index a16b98d..24415e1 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -104,8 +104,7 @@
   ASSERT(!async_pc_offset_array->IsNull());
   // We start with the asynchronous gap marker.
   ASSERT(async_code_array->At(0) != Code::null());
-  ASSERT(async_code_array->At(0) ==
-         StubCode::AsynchronousGapMarker_entry()->code());
+  ASSERT(async_code_array->At(0) == StubCode::AsynchronousGapMarker().raw());
   const Object& code_object = Object::Handle(async_code_array->At(1));
   if (code_object.IsCode()) {
     *async_function = Code::Cast(code_object).function();
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index aad2c87..95e53c1 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -23,25 +23,12 @@
 
 DECLARE_FLAG(bool, enable_interpreter);
 
-StubEntry* StubCode::entries_[kNumStubEntries] = {
-#define STUB_CODE_DECLARE(name) NULL,
+Code* StubCode::entries_[kNumStubEntries] = {
+#define STUB_CODE_DECLARE(name) nullptr,
     VM_STUB_CODE_LIST(STUB_CODE_DECLARE)
 #undef STUB_CODE_DECLARE
 };
 
-StubEntry::StubEntry(const Code& code)
-    : code_(code.raw()),
-      entry_point_(code.EntryPoint()),
-      monomorphic_entry_point_(code.MonomorphicEntryPoint()),
-      size_(code.Size()),
-      label_(code.EntryPoint()) {}
-
-// Visit all object pointers.
-void StubEntry::VisitObjectPointers(ObjectPointerVisitor* visitor) {
-  ASSERT(visitor != NULL);
-  visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
-}
-
 #if defined(DART_PRECOMPILED_RUNTIME)
 void StubCode::Init() {
   // Stubs will be loaded from the snapshot.
@@ -55,19 +42,17 @@
 #else
 
 #define STUB_CODE_GENERATE(name)                                               \
-  code ^= Generate("_stub_" #name, &object_pool_wrapper,                       \
-                   StubCode::Generate##name##Stub);                            \
-  entries_[k##name##Index] = new StubEntry(code);
+  entries_[k##name##Index] = Code::ReadOnlyHandle();                           \
+  *entries_[k##name##Index] = Generate("_stub_" #name, &object_pool_wrapper,   \
+                                       StubCode::Generate##name##Stub);
 
 #define STUB_CODE_SET_OBJECT_POOL(name)                                        \
-  code = entries_[k##name##Index]->code();                                     \
-  code.set_object_pool(object_pool.raw());
+  entries_[k##name##Index]->set_object_pool(object_pool.raw());
 
 void StubCode::Init() {
   ObjectPoolWrapper object_pool_wrapper;
 
   // Generate all the stubs.
-  Code& code = Code::Handle();
   VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
 
   const ObjectPool& object_pool =
@@ -78,9 +63,7 @@
 #undef STUB_CODE_GENERATE
 #undef STUB_CODE_SET_OBJECT_POOL
 
-#define STUB_CODE_CLEANUP(name)                                                \
-  delete entries_[k##name##Index];                                             \
-  entries_[k##name##Index] = NULL;
+#define STUB_CODE_CLEANUP(name) entries_[k##name##Index] = nullptr;
 
 void StubCode::Cleanup() {
   VM_STUB_CODE_LIST(STUB_CODE_CLEANUP);
@@ -117,7 +100,7 @@
 
 bool StubCode::HasBeenInitialized() {
   // Use AsynchronousGapMarker as canary.
-  return StubCode::AsynchronousGapMarker_entry() != NULL;
+  return entries_[kAsynchronousGapMarkerIndex] != nullptr;
 }
 
 bool StubCode::InInvocationStub(uword pc, bool is_interpreted_frame) {
@@ -130,7 +113,7 @@
       return Interpreter::IsEntryFrameMarker(pc);
     }
     {
-      uword entry = StubCode::InvokeDartCodeFromBytecode_entry()->EntryPoint();
+      uword entry = StubCode::InvokeDartCodeFromBytecode().EntryPoint();
       uword size = StubCode::InvokeDartCodeFromBytecodeSize();
       if ((pc >= entry) && (pc < (entry + size))) {
         return true;
@@ -138,7 +121,7 @@
     }
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-  uword entry = StubCode::InvokeDartCode_entry()->EntryPoint();
+  uword entry = StubCode::InvokeDartCode().EntryPoint();
   uword size = StubCode::InvokeDartCodeSize();
   return (pc >= entry) && (pc < (entry + size));
 #else
@@ -156,7 +139,7 @@
 bool StubCode::InJumpToFrameStub(uword pc) {
 #if !defined(TARGET_ARCH_DBC)
   ASSERT(HasBeenInitialized());
-  uword entry = StubCode::JumpToFrame_entry()->EntryPoint();
+  uword entry = StubCode::JumpToFrame().EntryPoint();
   uword size = StubCode::JumpToFrameSize();
   return (pc >= entry) && (pc < (entry + size));
 #else
@@ -173,7 +156,7 @@
   const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
   ASSERT(error.IsNull());
   if (cls.id() == kArrayCid) {
-    return AllocateArray_entry()->code();
+    return AllocateArray().raw();
   }
   Code& stub = Code::Handle(zone, cls.allocation_stub());
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -274,35 +257,34 @@
 }
 #endif  // !defined(TARGET_ARCH_DBC)
 
-const StubEntry* StubCode::UnoptimizedStaticCallEntry(
-    intptr_t num_args_tested) {
+const Code& StubCode::UnoptimizedStaticCallEntry(intptr_t num_args_tested) {
 // These stubs are not used by DBC.
 #if !defined(TARGET_ARCH_DBC)
   switch (num_args_tested) {
     case 0:
-      return ZeroArgsUnoptimizedStaticCall_entry();
+      return ZeroArgsUnoptimizedStaticCall();
     case 1:
-      return OneArgUnoptimizedStaticCall_entry();
+      return OneArgUnoptimizedStaticCall();
     case 2:
-      return TwoArgsUnoptimizedStaticCall_entry();
+      return TwoArgsUnoptimizedStaticCall();
     default:
       UNIMPLEMENTED();
-      return NULL;
+      return Code::Handle();
   }
 #else
-  return NULL;
+  return Code::Handle();
 #endif
 }
 
 const char* StubCode::NameOfStub(uword entry_point) {
 #define VM_STUB_CODE_TESTER(name)                                              \
-  if ((name##_entry() != NULL) &&                                              \
-      (entry_point == name##_entry()->EntryPoint())) {                         \
+  if (entries_[k##name##Index] != nullptr &&                                   \
+      entries_[k##name##Index]->EntryPoint() == entry_point) {                 \
     return "" #name;                                                           \
   }
   VM_STUB_CODE_LIST(VM_STUB_CODE_TESTER);
 #undef VM_STUB_CODE_TESTER
-  return NULL;
+  return nullptr;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index ca61e06..637371b 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -118,32 +118,6 @@
 // using Smi 0 instead of Object::null() is slightly more efficient, since a Smi
 // does not require relocation.
 
-// class StubEntry is used to describe stub methods generated in dart to
-// abstract out common code executed from generated dart code.
-class StubEntry {
- public:
-  explicit StubEntry(const Code& code);
-  ~StubEntry() {}
-
-  const ExternalLabel& label() const { return label_; }
-  uword EntryPoint() const { return entry_point_; }
-  uword MonomorphicEntryPoint() const { return monomorphic_entry_point_; }
-  RawCode* code() const { return code_; }
-  intptr_t Size() const { return size_; }
-
-  // Visit all object pointers.
-  void VisitObjectPointers(ObjectPointerVisitor* visitor);
-
- private:
-  RawCode* code_;
-  uword entry_point_;
-  uword monomorphic_entry_point_;
-  intptr_t size_;
-  ExternalLabel label_;
-
-  DISALLOW_COPY_AND_ASSIGN(StubEntry);
-};
-
 // class StubCode is used to maintain the lifecycle of stubs.
 class StubCode : public AllStatic {
  public:
@@ -169,8 +143,8 @@
 
 // Define the shared stub code accessors.
 #define STUB_CODE_ACCESSOR(name)                                               \
-  static const StubEntry* name##_entry() { return entries_[k##name##Index]; }  \
-  static intptr_t name##Size() { return name##_entry()->Size(); }
+  static const Code& name() { return *entries_[k##name##Index]; }              \
+  static intptr_t name##Size() { return name().Size(); }
   VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR);
 #undef STUB_CODE_ACCESSOR
 
@@ -181,13 +155,15 @@
   static void GenerateBuildMethodExtractorStub(Assembler* assembler);
 #endif
 
-  static const StubEntry* UnoptimizedStaticCallEntry(intptr_t num_args_tested);
+  static const Code& UnoptimizedStaticCallEntry(intptr_t num_args_tested);
 
   static const intptr_t kNoInstantiator = 0;
   static const intptr_t kInstantiationSizeInWords = 3;
 
-  static StubEntry* EntryAt(intptr_t index) { return entries_[index]; }
-  static void EntryAtPut(intptr_t index, StubEntry* entry) {
+  static const Code& EntryAt(intptr_t index) { return *entries_[index]; }
+  static void EntryAtPut(intptr_t index, Code* entry) {
+    ASSERT(entry->IsReadOnlyHandle());
+    ASSERT(entries_[index] == nullptr);
     entries_[index] = entry;
   }
   static intptr_t NumEntries() { return kNumStubEntries; }
@@ -195,8 +171,6 @@
  private:
   friend class MegamorphicCacheTable;
 
-  static const intptr_t kStubCodeSize = 4 * KB;
-
   enum {
 #define STUB_CODE_ENTRY(name) k##name##Index,
     VM_STUB_CODE_LIST(STUB_CODE_ENTRY)
@@ -204,7 +178,7 @@
         kNumStubEntries
   };
 
-  static StubEntry* entries_[kNumStubEntries];
+  static Code* entries_[kNumStubEntries];
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 #define STUB_CODE_GENERATE(name)                                               \
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 7209ac5..2d04003 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -180,8 +180,7 @@
 
   const intptr_t kReceiverOffset = compiler_frame_layout.param_end_from_fp + 1;
 
-  const auto& context_allocation_stub =
-      Code::ZoneHandle(StubCode::AllocateContext_entry()->code());
+  const auto& context_allocation_stub = StubCode::AllocateContext();
 
   __ EnterStubFrame();
 
@@ -531,7 +530,7 @@
   __ LoadObject(R1, Object::null_object());
   // R1: null element type for raw Array.
   // R2: smi-tagged argument count, may be zero.
-  __ BranchLink(*StubCode::AllocateArray_entry());
+  __ BranchLink(StubCode::AllocateArray());
   // R0: newly allocated array.
   // R2: smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(R0);  // Array is in R0 and on top of stack.
@@ -2399,7 +2398,7 @@
   __ Bind(&is_simple_case);
   {
     __ PushList(kRegsToSave);
-    __ BranchLink(*StubCode::Subtype2TestCache_entry());
+    __ BranchLink(StubCode::Subtype2TestCache());
     __ CompareObject(R1, Bool::True());
     __ PopList(kRegsToSave);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
@@ -2409,7 +2408,7 @@
   __ Bind(&is_complex_case);
   {
     __ PushList(kRegsToSave);
-    __ BranchLink(*StubCode::Subtype6TestCache_entry());
+    __ BranchLink(StubCode::Subtype6TestCache());
     __ CompareObject(R1, Bool::True());
     __ PopList(kRegsToSave);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index f1ff4f6..384b31a 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -202,8 +202,7 @@
 
   const intptr_t kReceiverOffset = compiler_frame_layout.param_end_from_fp + 1;
 
-  const auto& context_allocation_stub =
-      Code::ZoneHandle(StubCode::AllocateContext_entry()->code());
+  const auto& context_allocation_stub = StubCode::AllocateContext();
 
   __ EnterStubFrame();
 
@@ -580,7 +579,7 @@
   __ LoadObject(R1, Object::null_object());
   // R1: null element type for raw Array.
   // R2: smi-tagged argument count, may be zero.
-  __ BranchLink(*StubCode::AllocateArray_entry());
+  __ BranchLink(StubCode::AllocateArray());
   // R0: newly allocated array.
   // R2: smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(R0);  // Array is in R0 and on top of stack.
@@ -2666,7 +2665,7 @@
   __ Bind(&is_simple_case);
   {
     __ PushPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
-    __ BranchLink(*StubCode::Subtype2TestCache_entry());
+    __ BranchLink(StubCode::Subtype2TestCache());
     __ CompareObject(R1, Bool::True());
     __ PopPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
@@ -2676,7 +2675,7 @@
   __ Bind(&is_complex_case);
   {
     __ PushPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
-    __ BranchLink(*StubCode::Subtype6TestCache_entry());
+    __ BranchLink(StubCode::Subtype6TestCache());
     __ CompareObject(R1, Bool::True());
     __ PopPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index bab20db..93884e2 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -330,7 +330,7 @@
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ movl(ECX, raw_null);  // Null element type for raw Array.
-  __ Call(*StubCode::AllocateArray_entry());
+  __ Call(StubCode::AllocateArray());
   __ SmiUntag(EDX);
   // EAX: newly allocated array.
   // EDX: length of the array (was preserved by the stub).
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 1ce8502..9033c2a 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -171,8 +171,7 @@
 
   const intptr_t kReceiverOffset = compiler_frame_layout.param_end_from_fp + 1;
 
-  const auto& context_allocation_stub =
-      Code::ZoneHandle(StubCode::AllocateContext_entry()->code());
+  const auto& context_allocation_stub = StubCode::AllocateContext();
 
   __ EnterStubFrame();
 
@@ -500,7 +499,7 @@
   __ LoadObject(R12, Object::null_object());
   // Allocate array to store arguments of caller.
   __ movq(RBX, R12);  // Null element type for raw Array.
-  __ Call(*StubCode::AllocateArray_entry());
+  __ Call(StubCode::AllocateArray());
   __ SmiUntag(R10);
   // RAX: newly allocated array.
   // R10: length of the array (was preserved by the stub).
@@ -2675,7 +2674,7 @@
 
   __ Bind(&is_simple_case);
   {
-    __ Call(*StubCode::Subtype2TestCache_entry());
+    __ Call(StubCode::Subtype2TestCache());
     __ CompareObject(R8, Bool::True());
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     __ Jump(&call_runtime);
@@ -2683,7 +2682,7 @@
 
   __ Bind(&is_complex_case);
   {
-    __ Call(*StubCode::Subtype6TestCache_entry());
+    __ Call(StubCode::Subtype6TestCache());
     __ CompareObject(R8, Bool::True());
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     // Fall through to runtime_call
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 87ac83d..38bfdf5 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -412,6 +412,7 @@
   V(_UserTag, "_UserTag")                                                      \
   V(Default, "Default")                                                        \
   V(ClassID, "ClassID")                                                        \
+  V(getID, "getID")                                                            \
   V(DartIsVM, "dart.isVM")                                                     \
   V(stack, ":stack")                                                           \
   V(stack_pointer, ":stack_pointer")                                           \
@@ -456,6 +457,7 @@
   V(DebugProcedureName, ":Eval")                                               \
   V(DebugClassName, "#DebugClass")                                             \
   V(vm_entry_point, "vm:entry-point")                                          \
+  V(vm_non_nullable_result_type, "vm:non-nullable-result-type")                \
   V(vm_exact_result_type, "vm:exact-result-type")                              \
   V(Get, "get")                                                                \
   V(Set, "set")                                                                \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 740e8ef..65feb3b 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -213,7 +213,7 @@
     defined(TARGET_ARCH_X64)
   for (intptr_t i = 0; i < kNumberOfDartAvailableCpuRegs; ++i) {
     write_barrier_wrappers_entry_points_[i] =
-        StubCode::WriteBarrierWrappers_entry()->EntryPoint() +
+        StubCode::WriteBarrierWrappers().EntryPoint() +
         i * kStoreBufferWrapperSize;
   }
 #endif
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 2041022..5b0ab13 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -85,41 +85,36 @@
 #define CACHED_VM_STUBS_LIST(V)
 #else
 #define CACHED_VM_STUBS_LIST(V)                                                \
-  V(RawCode*, write_barrier_code_, StubCode::WriteBarrier_entry()->code(),     \
+  V(RawCode*, write_barrier_code_, StubCode::WriteBarrier().raw(), NULL)       \
+  V(RawCode*, array_write_barrier_code_, StubCode::ArrayWriteBarrier().raw(),  \
     NULL)                                                                      \
-  V(RawCode*, array_write_barrier_code_,                                       \
-    StubCode::ArrayWriteBarrier_entry()->code(), NULL)                         \
-  V(RawCode*, fix_callers_target_code_,                                        \
-    StubCode::FixCallersTarget_entry()->code(), NULL)                          \
+  V(RawCode*, fix_callers_target_code_, StubCode::FixCallersTarget().raw(),    \
+    NULL)                                                                      \
   V(RawCode*, fix_allocation_stub_code_,                                       \
-    StubCode::FixAllocationStubTarget_entry()->code(), NULL)                   \
-  V(RawCode*, invoke_dart_code_stub_,                                          \
-    StubCode::InvokeDartCode_entry()->code(), NULL)                            \
+    StubCode::FixAllocationStubTarget().raw(), NULL)                           \
+  V(RawCode*, invoke_dart_code_stub_, StubCode::InvokeDartCode().raw(), NULL)  \
   V(RawCode*, invoke_dart_code_from_bytecode_stub_,                            \
-    StubCode::InvokeDartCodeFromBytecode_entry()->code(), NULL)                \
-  V(RawCode*, call_to_runtime_stub_, StubCode::CallToRuntime_entry()->code(),  \
-    NULL)                                                                      \
+    StubCode::InvokeDartCodeFromBytecode().raw(), NULL)                        \
+  V(RawCode*, call_to_runtime_stub_, StubCode::CallToRuntime().raw(), NULL)    \
   V(RawCode*, null_error_shared_without_fpu_regs_stub_,                        \
-    StubCode::NullErrorSharedWithoutFPURegs_entry()->code(), NULL)             \
+    StubCode::NullErrorSharedWithoutFPURegs().raw(), NULL)                     \
   V(RawCode*, null_error_shared_with_fpu_regs_stub_,                           \
-    StubCode::NullErrorSharedWithFPURegs_entry()->code(), NULL)                \
+    StubCode::NullErrorSharedWithFPURegs().raw(), NULL)                        \
   V(RawCode*, stack_overflow_shared_without_fpu_regs_stub_,                    \
-    StubCode::StackOverflowSharedWithoutFPURegs_entry()->code(), NULL)         \
+    StubCode::StackOverflowSharedWithoutFPURegs().raw(), NULL)                 \
   V(RawCode*, stack_overflow_shared_with_fpu_regs_stub_,                       \
-    StubCode::StackOverflowSharedWithFPURegs_entry()->code(), NULL)            \
-  V(RawCode*, monomorphic_miss_stub_,                                          \
-    StubCode::MonomorphicMiss_entry()->code(), NULL)                           \
+    StubCode::StackOverflowSharedWithFPURegs().raw(), NULL)                    \
+  V(RawCode*, monomorphic_miss_stub_, StubCode::MonomorphicMiss().raw(), NULL) \
   V(RawCode*, ic_lookup_through_code_stub_,                                    \
-    StubCode::ICCallThroughCode_entry()->code(), NULL)                         \
-  V(RawCode*, deoptimize_stub_, StubCode::Deoptimize_entry()->code(), NULL)    \
+    StubCode::ICCallThroughCode().raw(), NULL)                                 \
+  V(RawCode*, deoptimize_stub_, StubCode::Deoptimize().raw(), NULL)            \
   V(RawCode*, lazy_deopt_from_return_stub_,                                    \
-    StubCode::DeoptimizeLazyFromReturn_entry()->code(), NULL)                  \
+    StubCode::DeoptimizeLazyFromReturn().raw(), NULL)                          \
   V(RawCode*, lazy_deopt_from_throw_stub_,                                     \
-    StubCode::DeoptimizeLazyFromThrow_entry()->code(), NULL)                   \
-  V(RawCode*, slow_type_test_stub_, StubCode::SlowTypeTest_entry()->code(),    \
-    NULL)                                                                      \
+    StubCode::DeoptimizeLazyFromThrow().raw(), NULL)                           \
+  V(RawCode*, slow_type_test_stub_, StubCode::SlowTypeTest().raw(), NULL)      \
   V(RawCode*, lazy_specialize_type_test_stub_,                                 \
-    StubCode::LazySpecializeTypeTest_entry()->code(), NULL)
+    StubCode::LazySpecializeTypeTest().raw(), NULL)
 
 #endif
 
@@ -144,25 +139,25 @@
 #define CACHED_VM_STUBS_ADDRESSES_LIST(V)
 #else
 #define CACHED_VM_STUBS_ADDRESSES_LIST(V)                                      \
-  V(uword, write_barrier_entry_point_,                                         \
-    StubCode::WriteBarrier_entry()->EntryPoint(), 0)                           \
+  V(uword, write_barrier_entry_point_, StubCode::WriteBarrier().EntryPoint(),  \
+    0)                                                                         \
   V(uword, array_write_barrier_entry_point_,                                   \
-    StubCode::ArrayWriteBarrier_entry()->EntryPoint(), 0)                      \
+    StubCode::ArrayWriteBarrier().EntryPoint(), 0)                             \
   V(uword, call_to_runtime_entry_point_,                                       \
-    StubCode::CallToRuntime_entry()->EntryPoint(), 0)                          \
+    StubCode::CallToRuntime().EntryPoint(), 0)                                 \
   V(uword, null_error_shared_without_fpu_regs_entry_point_,                    \
-    StubCode::NullErrorSharedWithoutFPURegs_entry()->EntryPoint(), 0)          \
+    StubCode::NullErrorSharedWithoutFPURegs().EntryPoint(), 0)                 \
   V(uword, null_error_shared_with_fpu_regs_entry_point_,                       \
-    StubCode::NullErrorSharedWithFPURegs_entry()->EntryPoint(), 0)             \
+    StubCode::NullErrorSharedWithFPURegs().EntryPoint(), 0)                    \
   V(uword, stack_overflow_shared_without_fpu_regs_entry_point_,                \
-    StubCode::StackOverflowSharedWithoutFPURegs_entry()->EntryPoint(), 0)      \
+    StubCode::StackOverflowSharedWithoutFPURegs().EntryPoint(), 0)             \
   V(uword, stack_overflow_shared_with_fpu_regs_entry_point_,                   \
-    StubCode::StackOverflowSharedWithFPURegs_entry()->EntryPoint(), 0)         \
+    StubCode::StackOverflowSharedWithFPURegs().EntryPoint(), 0)                \
   V(uword, megamorphic_call_checked_entry_,                                    \
-    StubCode::MegamorphicCall_entry()->EntryPoint(), 0)                        \
-  V(uword, monomorphic_miss_entry_,                                            \
-    StubCode::MonomorphicMiss_entry()->EntryPoint(), 0)                        \
-  V(uword, deoptimize_entry_, StubCode::Deoptimize_entry()->EntryPoint(), 0)
+    StubCode::MegamorphicCall().EntryPoint(), 0)                               \
+  V(uword, monomorphic_miss_entry_, StubCode::MonomorphicMiss().EntryPoint(),  \
+    0)                                                                         \
+  V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)
 
 #endif
 
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 1f849fd..ae8855e 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -105,21 +105,20 @@
 
   if (type.raw() == Type::ObjectType() || type.raw() == Type::DynamicType() ||
       type.raw() == Type::VoidType()) {
-    return Code::InstructionsOf(StubCode::TopTypeTypeTest_entry()->code());
+    return StubCode::TopTypeTypeTest().instructions();
   }
 
   if (type.IsTypeRef()) {
-    return Code::InstructionsOf(StubCode::TypeRefTypeTest_entry()->code());
+    return StubCode::TypeRefTypeTest().instructions();
   }
 
   if (type.IsType() || type.IsTypeParameter()) {
     const bool should_specialize = !FLAG_precompiled_mode && lazy_specialize;
-    return Code::InstructionsOf(
-        should_specialize ? StubCode::LazySpecializeTypeTest_entry()->code()
-                          : StubCode::DefaultTypeTest_entry()->code());
+    return should_specialize ? StubCode::LazySpecializeTypeTest().instructions()
+                             : StubCode::DefaultTypeTest().instructions();
   } else {
     ASSERT(type.IsBoundedType() || type.IsMixinAppType());
-    return Code::InstructionsOf(StubCode::UnreachableTypeTest_entry()->code());
+    return StubCode::UnreachableTypeTest().instructions();
   }
 }
 
@@ -145,11 +144,11 @@
   ASSERT(StubCode::HasBeenInitialized());
 
   if (type.IsTypeRef()) {
-    return Code::InstructionsOf(StubCode::TypeRefTypeTest_entry()->code());
+    return StubCode::TypeRefTypeTest().instructions();
   }
 
   if (type.raw() == Type::ObjectType() || type.raw() == Type::DynamicType()) {
-    return Code::InstructionsOf(StubCode::TopTypeTypeTest_entry()->code());
+    return StubCode::TopTypeTypeTest().instructions();
   }
 
   if (type.IsCanonical()) {
@@ -168,14 +167,13 @@
         array_.Add(instr_);
       } else {
         // Fall back to default.
-        instr_ =
-            Code::InstructionsOf(StubCode::DefaultTypeTest_entry()->code());
+        instr_ = StubCode::DefaultTypeTest().instructions();
       }
 #else
       // In the precompiled runtime we cannot lazily create new optimized type
       // testing stubs, so if we cannot find one, we'll just return the default
       // one.
-      instr_ = Code::InstructionsOf(StubCode::DefaultTypeTest_entry()->code());
+      instr_ = StubCode::DefaultTypeTest().instructions();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
       return instr_.raw();
     }
@@ -199,23 +197,23 @@
 RawInstructions* TypeTestingStubFinder::LookupByAddresss(
     uword entry_point) const {
   // First test the 4 common ones:
-  code_ = StubCode::DefaultTypeTest_entry()->code();
+  code_ = StubCode::DefaultTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return code_.instructions();
   }
-  code_ = StubCode::LazySpecializeTypeTest_entry()->code();
+  code_ = StubCode::LazySpecializeTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return code_.instructions();
   }
-  code_ = StubCode::TopTypeTypeTest_entry()->code();
+  code_ = StubCode::TopTypeTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return code_.instructions();
   }
-  code_ = StubCode::TypeRefTypeTest_entry()->code();
+  code_ = StubCode::TypeRefTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return code_.instructions();
   }
-  code_ = StubCode::UnreachableTypeTest_entry()->code();
+  code_ = StubCode::UnreachableTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return code_.instructions();
   }
@@ -227,23 +225,23 @@
 const char* TypeTestingStubFinder::StubNameFromAddresss(
     uword entry_point) const {
   // First test the 4 common ones:
-  code_ = StubCode::DefaultTypeTest_entry()->code();
+  code_ = StubCode::DefaultTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return "TypeTestingStub_Default";
   }
-  code_ = StubCode::LazySpecializeTypeTest_entry()->code();
+  code_ = StubCode::LazySpecializeTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return "TypeTestingStub_LazySpecialize";
   }
-  code_ = StubCode::TopTypeTypeTest_entry()->code();
+  code_ = StubCode::TopTypeTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return "TypeTestingStub_Top";
   }
-  code_ = StubCode::TypeRefTypeTest_entry()->code();
+  code_ = StubCode::TypeRefTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return "TypeTestingStub_Ref";
   }
-  code_ = StubCode::UnreachableTypeTest_entry()->code();
+  code_ = StubCode::UnreachableTypeTest().raw();
   if (entry_point == code_.EntryPoint()) {
     return "TypeTestingStub_Unreachable";
   }
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 6c53746..e99f521 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -9,6 +9,7 @@
 
 #include "platform/globals.h"
 
+#include "bin/kernel_isolate.h"
 #include "vm/dart.h"
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
diff --git a/runtime/vm/v8_snapshot_writer.cc b/runtime/vm/v8_snapshot_writer.cc
new file mode 100644
index 0000000..e945ca0
--- /dev/null
+++ b/runtime/vm/v8_snapshot_writer.cc
@@ -0,0 +1,290 @@
+// 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.
+
+#if defined(DART_PRECOMPILER)
+
+#include "vm/v8_snapshot_writer.h"
+
+#include "vm/dart.h"
+#include "vm/os.h"
+
+namespace dart {
+
+const char* ZoneString(Zone* Z, const char* str) {
+  const intptr_t len = strlen(str) + 1;
+  char* dest = Z->Alloc<char>(len);
+  snprintf(dest, len, "%s", str);
+  return dest;
+}
+
+V8SnapshotProfileWriter::V8SnapshotProfileWriter(Zone* zone)
+    : zone_(zone),
+      node_types_(zone_),
+      edge_types_(zone_),
+      strings_(zone),
+      roots_(zone_, 100) {
+  node_types_.Insert({"Unknown", kUnknown});
+  node_types_.Insert({"ArtificialRoot", kArtificialRoot});
+
+  edge_types_.Insert({"context", kContext});
+  edge_types_.Insert({"element", kElement});
+  edge_types_.Insert({"property", kProperty});
+  edge_types_.Insert({"internal", kInternal});
+  edge_types_.Insert({"hidden", kHidden});
+  edge_types_.Insert({"shortcut", kShortcut});
+  edge_types_.Insert({"weak", kWeak});
+  edge_types_.Insert({"extra", kExtra});
+
+  strings_.Insert({"<unknown>", kUnknownString});
+  strings_.Insert({"<object>", kObjectString});
+  strings_.Insert({"<property>", kPropertyString});
+  strings_.Insert({"<artificial root>", kArtificialRootString});
+}
+
+void V8SnapshotProfileWriter::SetObjectTypeAndName(ObjectId object_id,
+                                                   const char* type,
+                                                   const char* name) {
+  ASSERT(type != nullptr);
+  NodeInfo* info = EnsureId(object_id);
+
+  if (!node_types_.HasKey(type)) {
+    node_types_.Insert({ZoneString(zone_, type), node_types_.Size()});
+  }
+
+  intptr_t type_id = node_types_.LookupValue(type);
+  ASSERT(info->type == kUnknown || info->type == type_id);
+  info->type = type_id;
+
+  if (name != nullptr) {
+    info->name = EnsureString(name);
+  } else {
+    info->name = EnsureString(type);
+  }
+}
+
+void V8SnapshotProfileWriter::AttributeBytesTo(ObjectId object_id,
+                                               size_t num_bytes) {
+  EnsureId(object_id)->self_size += num_bytes;
+}
+
+void V8SnapshotProfileWriter::AttributeReferenceTo(ObjectId object_id,
+                                                   ObjectId to_object_id) {
+  EnsureId(to_object_id);
+  NodeInfo* info = EnsureId(object_id);
+
+#if defined(DEBUG)
+  // We should never add a reference twice.
+  for (intptr_t i = 0; i < info->edges->length(); ++i) {
+    ASSERT(info->edges->At(i).to_node != object_id);
+  }
+#endif
+
+  info->edges->Add(EdgeInfo{to_object_id});
+  ++edge_count_;
+}
+
+V8SnapshotProfileWriter::NodeInfo V8SnapshotProfileWriter::DefaultNode(
+    ObjectId object_id) {
+  return {
+      kUnknown,
+      kUnknownString,
+      object_id,
+      0,
+      new (zone_) ZoneGrowableArray<EdgeInfo>(zone_, 0),
+      -1,
+  };
+}
+
+V8SnapshotProfileWriter::NodeInfo V8SnapshotProfileWriter::ArtificialRoot() {
+  return {
+      kArtificialRoot, kArtificialRootString, {kArtificial, 0}, 0, nullptr, 0,
+  };
+}
+
+V8SnapshotProfileWriter::NodeInfo* V8SnapshotProfileWriter::EnsureId(
+    ObjectId object_id) {
+  if (!nodes_.HasKey(object_id)) {
+    NodeInfo info = DefaultNode(object_id);
+    nodes_.Insert({object_id, info});
+  }
+  return &nodes_.Lookup(object_id)->value;
+}
+
+intptr_t V8SnapshotProfileWriter::EnsureString(const char* str) {
+  if (!strings_.HasKey(str)) {
+    strings_.Insert({ZoneString(zone_, str), strings_.Size()});
+    return strings_.Size() - 1;
+  }
+  return strings_.LookupValue(str);
+}
+
+void V8SnapshotProfileWriter::WriteNodeInfo(JSONWriter* writer,
+                                            const NodeInfo& info) {
+  writer->PrintValue(info.type);
+  writer->PrintValue(info.name);
+  writer->PrintValue(NodeIdFor(info.id));
+  writer->PrintValue(info.self_size);
+  // The artificial root has 'nullptr' edges, it actually points to all the
+  // roots.
+  writer->PrintValue64(info.edges != nullptr ? info.edges->length()
+                                             : roots_.length());
+  writer->PrintNewline();
+}
+
+void V8SnapshotProfileWriter::WriteEdgeInfo(JSONWriter* writer,
+                                            const EdgeInfo& info) {
+  writer->PrintValue64(kProperty);  // type, not really used atm
+  writer->PrintValue64(
+      kPropertyString);  // name_or_index, not really used either
+  writer->PrintValue64(nodes_.LookupValue(info.to_node).offset);
+  writer->PrintNewline();
+}
+
+void V8SnapshotProfileWriter::AddRoot(ObjectId object_id) {
+  EnsureId(object_id);
+  roots_.Add(object_id);
+}
+
+void V8SnapshotProfileWriter::WriteStringsTable(
+    JSONWriter* writer,
+    const DirectChainedHashMap<StringToIntMapTraits>& map) {
+  const char** strings = zone_->Alloc<const char*>(map.Size());
+  StringToIntMapTraits::Pair* pair = nullptr;
+  auto it = map.GetIterator();
+  while ((pair = it.Next()) != nullptr) {
+    ASSERT(pair->value >= 0 && pair->value < map.Size());
+    strings[pair->value] = pair->key;
+  }
+  for (intptr_t i = 0; i < map.Size(); ++i) {
+    writer->PrintValue(strings[i]);
+    writer->PrintNewline();
+  }
+}
+
+void V8SnapshotProfileWriter::Write(JSONWriter* writer) {
+  writer->OpenObject();
+
+  writer->OpenObject("snapshot");
+  {
+    writer->OpenObject("meta");
+
+    {
+      writer->OpenArray("node_fields");
+      writer->PrintValue("type");
+      writer->PrintValue("name");
+      writer->PrintValue("id");
+      writer->PrintValue("self_size");
+      writer->PrintValue("edge_count");
+      writer->CloseArray();
+    }
+
+    {
+      writer->OpenArray("node_types");
+      {
+        writer->OpenArray();
+        WriteStringsTable(writer, node_types_);
+        writer->CloseArray();
+      }
+      writer->CloseArray();
+    }
+
+    {
+      writer->OpenArray("edge_fields");
+      writer->PrintValue("type");
+      writer->PrintValue("name_or_index");
+      writer->PrintValue("to_node");
+      writer->CloseArray();
+    }
+
+    {
+      writer->OpenArray("edge_types");
+      {
+        writer->OpenArray();
+        WriteStringsTable(writer, edge_types_);
+        writer->CloseArray();
+      }
+      writer->CloseArray();
+    }
+
+    writer->CloseObject();
+
+    writer->PrintProperty64("node_count",
+                            nodes_.Size() + 1 /* artificial root */);
+    writer->PrintProperty64("edge_count", edge_count_ + roots_.length());
+  }
+  writer->CloseObject();
+
+  {
+    writer->OpenArray("nodes");
+    // Write the artificial root node.
+    WriteNodeInfo(writer, ArtificialRoot());
+    intptr_t offset = kNumNodeFields;
+    ObjectIdToNodeInfoTraits::Pair* entry = nullptr;
+    auto it = nodes_.GetIterator();
+    while ((entry = it.Next()) != nullptr) {
+      ASSERT(entry->key == entry->value.id);
+      entry->value.offset = offset;
+      WriteNodeInfo(writer, entry->value);
+      offset += kNumNodeFields;
+    }
+    writer->CloseArray();
+  }
+
+  {
+    writer->OpenArray("edges");
+
+    // Write references from the artificial root to the actual roots.
+    for (ObjectId root : roots_) {
+      WriteEdgeInfo(writer, {root});
+    }
+
+    ObjectIdToNodeInfoTraits::Pair* entry = nullptr;
+    auto it = nodes_.GetIterator();
+    while ((entry = it.Next()) != nullptr) {
+      for (intptr_t i = 0; i < entry->value.edges->length(); ++i) {
+        WriteEdgeInfo(writer, entry->value.edges->At(i));
+      }
+    }
+
+    writer->CloseArray();
+  }
+
+  {
+    writer->OpenArray("strings");
+    WriteStringsTable(writer, strings_);
+    writer->CloseArray();
+  }
+
+  writer->CloseObject();
+}
+
+void V8SnapshotProfileWriter::Write(const char* filename) {
+  JSONWriter json;
+  Write(&json);
+
+  auto file_open = Dart::file_open_callback();
+  auto file_write = Dart::file_write_callback();
+  auto file_close = Dart::file_close_callback();
+  if ((file_open == nullptr) || (file_write == nullptr) ||
+      (file_close == nullptr)) {
+    OS::PrintErr("Could not access file callbacks to write snapshot profile.");
+    return;
+  }
+
+  auto file = file_open(filename, /*write=*/true);
+  if (file == nullptr) {
+    OS::PrintErr("Failed to open file %s\n", filename);
+  } else {
+    char* output = nullptr;
+    intptr_t output_length = 0;
+    json.Steal(&output, &output_length);
+    file_write(output, output_length, file);
+    free(output);
+    file_close(file);
+  }
+}
+
+}  // namespace dart
+
+#endif
diff --git a/runtime/vm/v8_snapshot_writer.h b/runtime/vm/v8_snapshot_writer.h
new file mode 100644
index 0000000..c506b2e
--- /dev/null
+++ b/runtime/vm/v8_snapshot_writer.h
@@ -0,0 +1,201 @@
+// 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.
+
+#ifndef RUNTIME_VM_V8_SNAPSHOT_WRITER_H_
+#define RUNTIME_VM_V8_SNAPSHOT_WRITER_H_
+
+#include <utility>
+
+#include "platform/assert.h"
+#include "vm/allocation.h"
+#include "vm/hash_map.h"
+#include "vm/json_writer.h"
+
+namespace dart {
+
+struct StringToIntMapTraits {
+  typedef char const* Key;
+  typedef intptr_t Value;
+
+  struct Pair {
+    Key key;
+    Value value;
+    Pair() : key(nullptr), value(-1) {}
+    Pair(Key k, Value v) : key(k), value(v) {}
+  };
+
+  static Value ValueOf(Pair pair) { return pair.value; }
+
+  static Key KeyOf(Pair pair) { return pair.key; }
+
+  static size_t Hashcode(Key key) {
+    /// SAMIR_TODO
+    return 0;
+  }
+
+  static bool IsKeyEqual(Pair x, Key y) { return strcmp(x.key, y) == 0; }
+};
+
+class V8SnapshotProfileWriter : public ZoneAllocated {
+ public:
+  enum IdSpace {
+    kSnapshot = 0,  // Can be VM or Isolate heap, they share ids.
+    kVmText = 1,
+    kIsolateText = 2,
+    kVmData = 3,
+    kIsolateData = 4,
+    kArtificial = 5,  // Artificial objects (e.g. the global root).
+    kIdSpaceBits = 3,
+  };
+
+  typedef std::pair<IdSpace, intptr_t> ObjectId;
+
+#if !defined(DART_PRECOMPILER)
+  explicit V8SnapshotProfileWriter(Zone* zone) {}
+  virtual ~V8SnapshotProfileWriter() {}
+
+  void SetObjectTypeAndName(ObjectId object_id,
+                            const char* type,
+                            const char* name) {}
+  void AttributeBytesTo(ObjectId object_id, size_t num_bytes) {}
+  void AttributeReferenceTo(ObjectId object_id, ObjectId to_object_id) {}
+  void AddRoot(ObjectId object_id) {}
+#else
+  explicit V8SnapshotProfileWriter(Zone* zone);
+  virtual ~V8SnapshotProfileWriter() {}
+
+  // Records that the object referenced by 'object_id' has type 'type'. The
+  // 'type' for all 'Instance's should be 'Instance', not the user-visible type
+  // and use 'name' for the real type instead.
+  void SetObjectTypeAndName(ObjectId object_id,
+                            const char* type,
+                            const char* name);
+
+  // Charges 'num_bytes'-many bytes to 'object_id'. In a clustered snapshot,
+  // objects can have their data spread across multiple sections, so this can be
+  // called multiple times for the same object.
+  void AttributeBytesTo(ObjectId object_id, size_t num_bytes);
+
+  // Records that a reference to the object with id 'to_object_id' was written
+  // in order to serialize the object with id 'object_id'. This does not affect
+  // the number of bytes charged to 'object_id'.
+  void AttributeReferenceTo(ObjectId object_id, ObjectId to_object_id);
+
+  // Marks an object as being a root in the graph. Used for analysis of the
+  // graph.
+  void AddRoot(ObjectId object_id);
+
+  // Write to a file in the V8 Snapshot Profile (JSON/.heapsnapshot) format.
+  void Write(const char* file);
+
+ private:
+  static constexpr intptr_t kNumNodeFields = 5;
+  static constexpr intptr_t kNumEdgeFields = 3;
+
+  struct EdgeInfo {
+    // 'type' and 'name_or_index' aren't supported yet.
+    ObjectId to_node;
+  };
+
+  struct NodeInfo {
+    intptr_t type;
+    intptr_t name;
+    ObjectId id;
+    intptr_t self_size;
+    ZoneGrowableArray<EdgeInfo>* edges = nullptr;
+    // Populated during serialization.
+    intptr_t offset = -1;
+    // 'trace_node_id' isn't supported.
+    // 'edge_count' is computed on-demand.
+
+    // Used for testing sentinel in the hashtable.
+    bool operator!=(const NodeInfo& other) { return id != other.id; }
+    bool operator==(const NodeInfo& other) { return !(*this != other); }
+
+    NodeInfo(intptr_t type,
+             intptr_t name,
+             ObjectId id,
+             intptr_t self_size,
+             ZoneGrowableArray<EdgeInfo>* edges,
+             intptr_t offset)
+        : type(type),
+          name(name),
+          id(id),
+          self_size(self_size),
+          edges(edges),
+          offset(offset) {}
+  };
+
+  NodeInfo DefaultNode(ObjectId object_id);
+  static NodeInfo ArtificialRoot();
+
+  NodeInfo* EnsureId(ObjectId object_id);
+  intptr_t EnsureString(const char* str);
+  static intptr_t NodeIdFor(ObjectId id) {
+    return (id.second << kIdSpaceBits) | id.first;
+  }
+
+  enum ConstantStrings {
+    kUnknownString = 0,
+    kPropertyString = 1,
+    kObjectString = 2,
+    kArtificialRootString = 3,
+  };
+
+  enum ConstantEdgeTypes {
+    kContext = 0,
+    kElement = 1,
+    kProperty = 2,
+    kInternal = 3,
+    kHidden = 4,
+    kShortcut = 5,
+    kWeak = 6,
+    kExtra = 7,
+  };
+
+  enum ConstantNodeTypes {
+    kUnknown = 0,
+    kArtificialRoot = 1,
+  };
+
+  struct ObjectIdToNodeInfoTraits {
+    typedef ObjectId Key;
+    typedef NodeInfo Value;
+
+    struct Pair {
+      Key key;
+      Value value;
+      Pair()
+          : key{kSnapshot, -1}, value{0, 0, {kSnapshot, -1}, 0, nullptr, -1} {};
+      Pair(Key k, Value v) : key(k), value(v) {}
+    };
+
+    static Key KeyOf(const Pair& pair) { return pair.key; }
+
+    static Value ValueOf(const Pair& pair) { return pair.value; }
+
+    static size_t Hashcode(Key key) { return NodeIdFor(key); }
+
+    static bool IsKeyEqual(const Pair& x, Key y) { return x.key == y; }
+  };
+
+  Zone* zone_;
+  void Write(JSONWriter* writer);
+  void WriteNodeInfo(JSONWriter* writer, const NodeInfo& info);
+  void WriteEdgeInfo(JSONWriter* writer, const EdgeInfo& info);
+  void WriteStringsTable(JSONWriter* writer,
+                         const DirectChainedHashMap<StringToIntMapTraits>& map);
+
+  DirectChainedHashMap<ObjectIdToNodeInfoTraits> nodes_;
+  DirectChainedHashMap<StringToIntMapTraits> node_types_;
+  DirectChainedHashMap<StringToIntMapTraits> edge_types_;
+  DirectChainedHashMap<StringToIntMapTraits> strings_;
+  ZoneGrowableArray<ObjectId> roots_;
+  size_t edge_count_ = 0;
+#endif
+};
+
+}  // namespace dart
+
+#endif  //  RUNTIME_VM_V8_SNAPSHOT_WRITER_H_
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 50882d9..b0e7872 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -119,7 +119,6 @@
   "instructions_x64.h",
   "interpreter.cc",
   "interpreter.h",
-  "interpreter_unsupported.cc",
   "isolate.cc",
   "isolate.h",
   "isolate_reload.cc",
@@ -278,9 +277,9 @@
   "stack_frame.h",
   "stack_frame_arm.h",
   "stack_frame_arm64.h",
-  "stack_frame_dbc",
+  "stack_frame_dbc.h",
   "stack_frame_ia32.h",
-  "stack_frame_kbc",
+  "stack_frame_kbc.h",
   "stack_frame_x64.h",
   "stack_trace.cc",
   "stack_trace.h",
@@ -333,6 +332,8 @@
   "unicode_data.cc",
   "uri.cc",
   "uri.h",
+  "v8_snapshot_writer.cc",
+  "v8_snapshot_writer.h",
   "virtual_memory.cc",
   "virtual_memory.h",
   "virtual_memory_android.cc",
diff --git a/sdk/lib/_http/websocket_impl.dart b/sdk/lib/_http/websocket_impl.dart
index 330f9ea..e27ab20 100644
--- a/sdk/lib/_http/websocket_impl.dart
+++ b/sdk/lib/_http/websocket_impl.dart
@@ -732,12 +732,13 @@
 
   void addFrame(int opcode, List<int> data) {
     createFrame(
-        opcode,
-        data,
-        webSocket._serverSide,
-        _deflateHelper != null &&
-            (opcode == _WebSocketOpcode.TEXT ||
-                opcode == _WebSocketOpcode.BINARY)).forEach((e) {
+            opcode,
+            data,
+            webSocket._serverSide,
+            _deflateHelper != null &&
+                (opcode == _WebSocketOpcode.TEXT ||
+                    opcode == _WebSocketOpcode.BINARY))
+        .forEach((e) {
       _eventSink.add(e);
     });
   }
@@ -1204,9 +1205,7 @@
   }
 
   void addUtf8Text(List<int> bytes) {
-    if (bytes is! List<int>) {
-      throw new ArgumentError.value(bytes, "bytes", "Is not a list of bytes");
-    }
+    ArgumentError.checkNotNull(bytes, "bytes");
     _sink.add(new _EncodedString(bytes));
   }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
index 2d234a4..afb5062 100644
--- a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
@@ -496,3 +496,13 @@
     return null;
   }
 }
+
+@patch
+int _scanOneByteCharacters(List<int> units, int from, int endIndex) {
+  final to = endIndex;
+  for (var i = from; i < to; i++) {
+    final unit = units[i];
+    if ((unit & _ONE_BYTE_LIMIT) != unit) return i - from;
+  }
+  return to - from;
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 14bf26d..0f14426 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -274,45 +274,42 @@
       "because it is not included in a @MirrorsUsed annotation.");
 }
 
-/// Helper to print the given method information to the console the first
-/// time it is called with it.
+/// Helper used to instrument calls when the compiler is invoked with
+/// `--experiment-call-instrumentation`.
+///
+/// By default, whenever a method is invoked for the first time, it prints an id
+/// and the method name to the console. This can be overriden by adding a top
+/// level `dartCallInstrumentation` hook in JavaScript.
 @NoInline()
-void consoleTraceHelper(String method) {
-  if (JS('bool', '!this.cache')) {
-    JS('', 'this.cache = Object.create(null)');
-  }
-  if (JS('bool', '!this.cache[#]', method)) {
-    JS('', 'console.log(#)', method);
-    JS('', 'this.cache[#] = true', method);
-  }
-}
-
-List _traceBuffer;
-
-/// Helper to send coverage information as a POST request to a server.
-@NoInline()
-void postTraceHelper(int id, String name) {
-  // Note: we can't move this initialization to the declaration of
-  // [_traceBuffer] because [postTraceHelper] is called very early on functions
-  // that define constants, this happens before getters and setters are expanded
-  // and before main starts executing. This initialization here allows us to
-  // skip the lazy field initialization logic.
-  if (_traceBuffer == null) _traceBuffer = JS('JSArray', '[]');
-  if (JS('bool', '#.length == 0', _traceBuffer)) {
-    JS(
-        '',
-        r'''
-      window.setTimeout((function(buffer) {
-        return function() {
-          var xhr = new XMLHttpRequest();
-          xhr.open("POST", "/coverage_uri_to_amend_by_server");
-          xhr.send(JSON.stringify(buffer));
-          buffer.length = 0;
-        };
-      })(#), 1000)''',
-        _traceBuffer);
-  }
-  JS('', '#.push([#, #])', _traceBuffer, id, name);
+void traceHelper(dynamic /*int*/ id, dynamic /*String*/ qualifiedName) {
+  // Note: this method is written mostly in JavaScript to prevent a stack
+  // overflow. In particular, we use dynamic argument types because with with
+  // types, traceHelper would include type checks for the parameter types, those
+  // checks (intTypeCheck, stringTypeCheck) are themselves calls that end up
+  // invoking this traceHelper and produce a stack overflow.  Similarly if we
+  // had Dart code below using, for example, string interpolation, we would
+  // include extra calls to the Dart runtime that could also trigger a stack
+  // overflow. This approach here is simpler than making the compiler smart
+  // about how to generate traceHelper calls more carefully.
+  JS(
+      '',
+      r'''
+      (function (id, name) {
+        var hook = self.dartCallInstrumentation;
+        if (typeof hook === "function") {
+          hook(id, name);
+          return;
+        }
+        if (!this.callInstrumentationCache) {
+          this.callInstrumentationCache = Object.create(null);
+        }
+        if (!this.callInstrumentationCache[id]) {
+          console.log(id, name);
+          this.callInstrumentationCache[id] = true;
+        }
+      })(#, #)''',
+      id,
+      qualifiedName);
 }
 
 class JSInvocationMirror implements Invocation {
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index c968cbd..b9d22c1 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -224,9 +224,6 @@
       var result = computation();
       if (result is Future<T>) {
         return result;
-      } else if (result is Future) {
-        // TODO(lrn): Remove this case for Dart 2.0.
-        return new _Future<T>.immediate(result);
       } else {
         return new _Future<T>.value(result);
       }
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 798e63f..f77ca2c 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1423,7 +1423,8 @@
    * with a [RangeError].
    */
   Future<T> elementAt(int index) {
-    if (index is! int || index < 0) throw new ArgumentError(index);
+    ArgumentError.checkNotNull(index, "index");
+    RangeError.checkNotNegative(index, "index");
     _Future<T> future = new _Future<T>();
     StreamSubscription subscription;
     int elementIndex = 0;
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 956de3b..51497e0 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -363,7 +363,7 @@
     if (_cancelOnError) {
       _state |= _STATE_WAIT_FOR_CANCEL;
       _cancel();
-      if (_cancelFuture is Future &&
+      if (_cancelFuture != null &&
           !identical(_cancelFuture, Future._nullFuture)) {
         _cancelFuture.whenComplete(sendError);
       } else {
@@ -392,7 +392,7 @@
 
     _cancel();
     _state |= _STATE_WAIT_FOR_CANCEL;
-    if (_cancelFuture is Future &&
+    if (_cancelFuture != null &&
         !identical(_cancelFuture, Future._nullFuture)) {
       _cancelFuture.whenComplete(sendDone);
     } else {
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 31d5bab..e526179 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -26,7 +26,7 @@
 void _cancelAndError(StreamSubscription subscription, _Future future, error,
     StackTrace stackTrace) {
   var cancelFuture = subscription.cancel();
-  if (cancelFuture is Future && !identical(cancelFuture, Future._nullFuture)) {
+  if (cancelFuture != null && !identical(cancelFuture, Future._nullFuture)) {
     cancelFuture.whenComplete(() => future._completeError(error, stackTrace));
   } else {
     future._completeError(error, stackTrace);
@@ -57,7 +57,7 @@
   before completing with a value. */
 void _cancelAndValue(StreamSubscription subscription, _Future future, value) {
   var cancelFuture = subscription.cancel();
-  if (cancelFuture is Future && !identical(cancelFuture, Future._nullFuture)) {
+  if (cancelFuture != null && !identical(cancelFuture, Future._nullFuture)) {
     cancelFuture.whenComplete(() => future._complete(value));
   } else {
     future._complete(value);
@@ -306,7 +306,7 @@
         super(source) {
     // This test is done early to avoid handling an async error
     // in the _handleData method.
-    if (count is! int) throw new ArgumentError(count);
+    ArgumentError.checkNotNull(count, "count");
   }
 
   StreamSubscription<T> _createSubscription(void onData(T data),
@@ -397,7 +397,8 @@
         super(source) {
     // This test is done early to avoid handling an async error
     // in the _handleData method.
-    if (count is! int || count < 0) throw new ArgumentError(count);
+    ArgumentError.checkNotNull(count, "count");
+    RangeError.checkNotNegative(count, "count");
   }
 
   StreamSubscription<T> _createSubscription(void onData(T data),
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index 186bbe6..aa2f088 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -89,6 +89,10 @@
 
   /**
    * Cancels the timer.
+   *
+   * Once a [Timer] has been canceled, the callback function will not be called
+   * by the timer. Calling [cancel] more than once on a [Timer] is allowed, and
+   * will have no further effect.
    */
   void cancel();
 
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index dc84459..b7b5497 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -199,7 +199,7 @@
   }
 
   E elementAt(int index) {
-    if (index is! int) throw new ArgumentError.notNull("index");
+    ArgumentError.checkNotNull(index, "index");
     RangeError.checkNotNegative(index, "index");
     int elementIndex = 0;
     for (E element in this) {
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 4b50c6a..0c01350 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -486,15 +486,12 @@
   }
 
   void insert(int index, E element) {
+    ArgumentError.checkNotNull(index, "index");
     RangeError.checkValueInInterval(index, 0, length, "index");
     if (index == this.length) {
       add(element);
       return;
     }
-    // We are modifying the length just below the is-check. Without the check
-    // Array.copy could throw an exception, leaving the list in a bad state
-    // (with a length that has been increased, but without a new element).
-    if (index is! int) throw new ArgumentError(index);
     this.length++;
     setRange(index + 1, this.length, this, index);
     this[index] = element;
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 0d986f9..c63bf30 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -276,7 +276,7 @@
   }
 
   E elementAt(int index) {
-    if (index is! int) throw new ArgumentError.notNull("index");
+    ArgumentError.checkNotNull(index, "index");
     RangeError.checkNotNegative(index, "index");
     int elementIndex = 0;
     for (E element in this) {
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index 567c8b2..eb92e2b 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -412,16 +412,6 @@
     _expectedUnits = 0;
     _extraUnits = 0;
 
-    int scanOneByteCharacters(List<int> units, int from) {
-      final to = endIndex;
-      final mask = _ONE_BYTE_LIMIT;
-      for (var i = from; i < to; i++) {
-        final unit = units[i];
-        if ((unit & mask) != unit) return i - from;
-      }
-      return to - from;
-    }
-
     void addSingleBytes(int from, int to) {
       assert(from >= startIndex && from <= endIndex);
       assert(to >= startIndex && to <= endIndex);
@@ -484,7 +474,7 @@
       }
 
       while (i < endIndex) {
-        var oneBytes = scanOneByteCharacters(codeUnits, i);
+        var oneBytes = _scanOneByteCharacters(codeUnits, i, endIndex);
         if (oneBytes > 0) {
           _isFirstCharacter = false;
           addSingleBytes(i, i + oneBytes);
@@ -545,3 +535,10 @@
     }
   }
 }
+
+// Returns the number of bytes in [units] starting at offset [from] which have
+// the leftmost bit set to 0.
+//
+// To increase performance of this critical method we have a special variant of
+// it implemented in the VM's patch files, which is why we make it external.
+external int _scanOneByteCharacters(List<int> units, int from, int endIndex);
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index 7e192c2..52bfc29 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -211,7 +211,7 @@
   int get inMicroseconds => _duration;
 
   /**
-   * Returns `true` if this [Duration] is the same object as [other].
+   * Returns `true` if this [Duration] has the same value as [other].
    */
   bool operator ==(dynamic other) =>
       other is Duration && _duration == other.inMicroseconds;
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 1325dab..3436b58 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -638,7 +638,7 @@
    * Some iterables may have more a efficient way to find the element.
    */
   E elementAt(int index) {
-    if (index is! int) throw new ArgumentError.notNull("index");
+    ArgumentError.checkNotNull(index, "index");
     RangeError.checkNotNegative(index, "index");
     int elementIndex = 0;
     for (E element in this) {
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index f7cf182..4e78c2a 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -77,30 +77,31 @@
   external factory List([int length]);
 
   /**
-   * Creates a fixed-length list of the given length, and initializes the
-   * value at each position with [fill]:
-   *
-   *     new List<int>.filled(3, 0); // [0, 0, 0]
+   * Creates a list of the given length with [fill] at each position.
    *
    * The [length] must be a non-negative integer.
    *
+   * Example:
+   * ```dart
+   * new List<int>.filled(3, 0, growable: true); // [0, 0, 0]
+   * ```
+   *
+   * The created list is fixed-length if [growable] is false (the default)
+   * and growable if [growable] is true.
    * If the list is growable, changing its length will not initialize new
-   * entries with [fill]. After being created and filled, the list is
-   * no different from any other growable or fixed-length list
-   * created using [List].
+   * entries with [fill].
+   * After being created and filled, the list is no different from any other
+   * growable or fixed-length list created using [List].
    *
-   * All entries in the returned list point to the same provided [fill] value.
-   * That all items in the list are the same object is
-   * observable when the given value is a mutable object.
-   *
+   * All elements of the returned list share the same [fill] value.
    * ```
    * var shared = new List.filled(3, []);
    * shared[0].add(499);
    * print(shared);  // => [[499], [499], [499]]
    * ```
    *
-   * You may use [List.generate] to create a new object for each position in
-   * in the list.
+   * You can use [List.generate] to create a list with a new object at
+   * each position.
    * ```
    * var unique = new List.generate(3, (_) => []);
    * unique[0].add(499);
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index ec316c7..c6f4cce 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.dart
@@ -21,9 +21,7 @@
       : _result = result,
         _errorCode = null,
         _errorDetail = null {
-    if (_result is! String) {
-      throw new ArgumentError.value(_result, "result", "Must be a String");
-    }
+    ArgumentError.checkNotNull(_result, "result");
   }
 
   /// Creates an error response to a service protocol extension RPC.
@@ -37,10 +35,7 @@
         _errorCode = errorCode,
         _errorDetail = errorDetail {
     _validateErrorCode(_errorCode);
-    if (_errorDetail is! String) {
-      throw new ArgumentError.value(
-          _errorDetail, "errorDetail", "Must be a String");
-    }
+    ArgumentError.checkNotNull(_errorDetail, "errorDetail");
   }
 
   /// Invalid method parameter(s) error code.
@@ -80,12 +75,8 @@
   }
 
   static _validateErrorCode(int errorCode) {
-    if (errorCode is! int) {
-      throw new ArgumentError.value(errorCode, "errorCode", "Must be an int");
-    }
-    if (errorCode == invalidParams) {
-      return;
-    }
+    ArgumentError.checkNotNull(errorCode, "errorCode");
+    if (errorCode == invalidParams) return;
     if ((errorCode >= extensionErrorMin) && (errorCode <= extensionErrorMax)) {
       return;
     }
@@ -134,31 +125,22 @@
 /// Because service extensions are isolate specific, clients using extensions
 /// must always include an 'isolateId' parameter with each RPC.
 void registerExtension(String method, ServiceExtensionHandler handler) {
-  if (method is! String) {
-    throw new ArgumentError.value(method, 'method', 'Must be a String');
-  }
+  ArgumentError.checkNotNull(method, 'method');
   if (!method.startsWith('ext.')) {
     throw new ArgumentError.value(method, 'method', 'Must begin with ext.');
   }
   if (_lookupExtension(method) != null) {
     throw new ArgumentError('Extension already registered: $method');
   }
-  if (handler is! ServiceExtensionHandler) {
-    throw new ArgumentError.value(
-        handler, 'handler', 'Must be a ServiceExtensionHandler');
-  }
+  ArgumentError.checkNotNull(handler, 'handler');
   _registerExtension(method, handler);
 }
 
 /// Post an event of [eventKind] with payload of [eventData] to the `Extension`
 /// event stream.
 void postEvent(String eventKind, Map eventData) {
-  if (eventKind is! String) {
-    throw new ArgumentError.value(eventKind, 'eventKind', 'Must be a String');
-  }
-  if (eventData is! Map) {
-    throw new ArgumentError.value(eventData, 'eventData', 'Must be a Map');
-  }
+  ArgumentError.checkNotNull(eventKind, 'eventKind');
+  ArgumentError.checkNotNull(eventData, 'eventData');
   String eventDataAsString = json.encode(eventData);
   _postEvent(eventKind, eventDataAsString);
 }
diff --git a/sdk/lib/developer/profiler.dart b/sdk/lib/developer/profiler.dart
index 665cd27..05a9211 100644
--- a/sdk/lib/developer/profiler.dart
+++ b/sdk/lib/developer/profiler.dart
@@ -64,15 +64,9 @@
 
   Gauge(String name, String description, this.min, this.max)
       : super(name, description) {
-    if (min is! double) {
-      throw new ArgumentError('min must be a double');
-    }
-    if (max is! double) {
-      throw new ArgumentError('max must be a double');
-    }
-    if (!(min < max)) {
-      throw new ArgumentError('min must be less than max');
-    }
+    ArgumentError.checkNotNull(min, 'min');
+    ArgumentError.checkNotNull(max, 'max');
+    if (!(min < max)) throw new ArgumentError('min must be less than max');
     _value = min;
   }
 
@@ -117,9 +111,7 @@
 
   /// Register [Metric]s to make them visible to Observatory.
   static void register(Metric metric) {
-    if (metric is! Metric) {
-      throw new ArgumentError('metric must be a Metric');
-    }
+    ArgumentError.checkNotNull(metric, 'metric');
     if (_metrics[metric.name] != null) {
       throw new ArgumentError('Registered metrics have unique names');
     }
@@ -128,9 +120,7 @@
 
   /// Deregister [Metric]s to make them not visible to Observatory.
   static void deregister(Metric metric) {
-    if (metric is! Metric) {
-      throw new ArgumentError('metric must be a Metric');
-    }
+    ArgumentError.checkNotNull(metric, 'metric');
     _metrics.remove(metric.name);
   }
 
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index 9616963..a4d92b9 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.dart
@@ -58,9 +58,7 @@
   /// enable (true) or disable (false) the web server servicing requests.
   static Future<ServiceProtocolInfo> controlWebServer(
       {bool enable: false}) async {
-    if (enable is! bool) {
-      throw new ArgumentError.value(enable, 'enable', 'Must be a bool');
-    }
+    ArgumentError.checkNotNull(enable, 'enable');
     // Port to receive response from service isolate.
     final RawReceivePort receivePort = new RawReceivePort();
     final Completer<Uri> uriCompleter = new Completer<Uri>();
@@ -79,9 +77,7 @@
   /// Returns null if the running Dart environment does not support the service
   /// protocol.
   static String getIsolateID(Isolate isolate) {
-    if (isolate is! Isolate) {
-      throw new ArgumentError.value(isolate, 'isolate', 'Must be an Isolate');
-    }
+    ArgumentError.checkNotNull(isolate, 'isolate');
     return _getIsolateIDFromSendPort(isolate.controlPort);
   }
 }
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index e838a1f..37ae997 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -100,22 +100,18 @@
   /// a [Flow] event. This operation must be finished before
   /// returning to the event queue.
   static void startSync(String name, {Map arguments, Flow flow}) {
-    if (_isProduct) {
-      return;
-    }
-    if (name is! String) {
-      throw new ArgumentError.value(name, 'name', 'Must be a String');
-    }
+    if (_isProduct) return;
+    ArgumentError.checkNotNull(name, 'name');
     if (!_isDartStreamEnabled()) {
       // Push a null onto the stack and return.
       _stack.add(null);
       return;
     }
     var block = new _SyncBlock._(name, _getTraceClock(), _getThreadCpuClock());
-    if (arguments is Map) {
+    if (arguments != null) {
       block._arguments = arguments;
     }
-    if (flow is Flow) {
+    if (flow != null) {
       block.flow = flow;
     }
     _stack.add(block);
@@ -141,18 +137,14 @@
 
   /// Emit an instant event.
   static void instantSync(String name, {Map arguments}) {
-    if (_isProduct) {
-      return;
-    }
-    if (name is! String) {
-      throw new ArgumentError.value(name, 'name', 'Must be a String');
-    }
+    if (_isProduct) return;
+    ArgumentError.checkNotNull(name, 'name');
     if (!_isDartStreamEnabled()) {
       // Stream is disabled.
       return;
     }
     Map instantArguments;
-    if (arguments is Map) {
+    if (arguments != null) {
       instantArguments = new Map.from(arguments);
     }
     _reportInstantEvent(
@@ -189,22 +181,16 @@
   /// Create a task with an explicit [taskId]. This is useful if you are
   /// passing a task from one isolate to another.
   TimelineTask.withTaskId(int taskId) : _taskId = taskId {
-    if (taskId is! int) {
-      throw new ArgumentError.value(taskId, 'taskId', 'Must be an int');
-    }
+    ArgumentError.checkNotNull(taskId, 'taskId');
   }
 
   /// Start a synchronous operation within this task named [name].
   /// Optionally takes a [Map] of [arguments].
   void start(String name, {Map arguments}) {
-    if (_isProduct) {
-      return;
-    }
-    if (name is! String) {
-      throw new ArgumentError.value(name, 'name', 'Must be a String');
-    }
+    if (_isProduct) return;
+    ArgumentError.checkNotNull(name, 'name');
     var block = new _AsyncBlock._(name, _taskId);
-    if (arguments is Map) {
+    if (arguments != null) {
       block._arguments = arguments;
     }
     _stack.add(block);
@@ -213,14 +199,10 @@
 
   /// Emit an instant event for this task.
   void instant(String name, {Map arguments}) {
-    if (_isProduct) {
-      return;
-    }
-    if (name is! String) {
-      throw new ArgumentError.value(name, 'name', 'Must be a String');
-    }
+    if (_isProduct) return;
+    ArgumentError.checkNotNull(name, 'name');
     Map instantArguments;
-    if (arguments is Map) {
+    if (arguments != null) {
       instantArguments = new Map.from(arguments);
     }
     _reportTaskEvent(_getTraceClock(), _taskId, 'n', 'Dart', name,
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index de62e02..10f0898 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -493,9 +493,8 @@
   final int _takeCount;
 
   factory TakeIterable(Iterable<E> iterable, int takeCount) {
-    if (takeCount is! int || takeCount < 0) {
-      throw new ArgumentError(takeCount);
-    }
+    ArgumentError.checkNotNull(takeCount, "takeCount");
+    RangeError.checkNotNegative(takeCount, "takeCount");
     if (iterable is EfficientLengthIterable) {
       return new EfficientLengthTakeIterable<E>(iterable, takeCount);
     }
@@ -621,9 +620,7 @@
 }
 
 int _checkCount(int count) {
-  if (count is! int) {
-    throw new ArgumentError.value(count, "count", "is not an integer");
-  }
+  ArgumentError.checkNotNull(count, "count");
   RangeError.checkNotNegative(count, "count");
   return count;
 }
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 01476ea..77b7587 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -105,9 +105,7 @@
   int j = start;
   for (int i = 0; i < length; i++) {
     int value = buffer[j];
-    if (value is! int) {
-      throw new ArgumentError("List element is not an integer at index $j");
-    }
+    if (value == null) throw ArgumentError("List element is null at index $j");
     newBuffer[i] = value;
     j++;
   }
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 42d6865..faed892 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -9,9 +9,7 @@
   Uint8List _rawPath;
 
   _Directory(String path) {
-    if (path is! String) {
-      throw new ArgumentError('${Error.safeToString(path)} is not a String');
-    }
+    ArgumentError.checkNotNull(path, 'path');
     _path = path;
     _rawPath = FileSystemEntity._toUtf8Array(_path);
   }
@@ -192,8 +190,9 @@
   }
 
   Future<Directory> _delete({bool recursive: false}) {
-    return _File._dispatchWithNamespace(_IOService.directoryDelete,
-        [null, _rawPath, recursive]).then((response) {
+    return _File._dispatchWithNamespace(
+            _IOService.directoryDelete, [null, _rawPath, recursive])
+        .then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionOrErrorFromResponse(response, "Deletion failed");
       }
@@ -252,8 +251,8 @@
         result,
         // FIXME(bkonyi): here we're using `path` directly, which might cause issues
         // if it is not UTF-8 encoded.
-        FileSystemEntity
-            ._toUtf8Array(FileSystemEntity._ensureTrailingPathSeparators(path)),
+        FileSystemEntity._toUtf8Array(
+            FileSystemEntity._ensureTrailingPathSeparators(path)),
         recursive,
         followLinks);
     return result;
@@ -369,8 +368,8 @@
       return;
     }
     nextRunning = true;
-    _IOService
-        ._dispatch(_IOService.directoryListNext, [pointer]).then((result) {
+    _IOService._dispatch(_IOService.directoryListNext, [pointer])
+        .then((result) {
       nextRunning = false;
       if (result is List) {
         next();
@@ -420,8 +419,8 @@
     if (pointer == null) {
       _cleanup();
     } else {
-      _IOService._dispatch(
-          _IOService.directoryListStop, [pointer]).whenComplete(_cleanup);
+      _IOService._dispatch(_IOService.directoryListStop, [pointer])
+          .whenComplete(_cleanup);
     }
   }
 
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 05508cc..33c1352 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -207,17 +207,13 @@
   Uint8List _rawPath;
 
   _File(String path) {
-    if (path is! String) {
-      throw new ArgumentError('${Error.safeToString(path)} is not a String');
-    }
+    ArgumentError.checkNotNull(path, 'path');
     _path = path;
     _rawPath = FileSystemEntity._toUtf8Array(path);
   }
 
   _File.fromRawPath(Uint8List rawPath) {
-    if (rawPath == null) {
-      throw new ArgumentError('rawPath cannot be null');
-    }
+    ArgumentError.checkNotNull(rawPath, 'rawPath');
     _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath);
     _path = FileSystemEntity._toStringFromUtf8Array(rawPath);
   }
@@ -746,9 +742,7 @@
   }
 
   Future<List<int>> read(int bytes) {
-    if (bytes is! int) {
-      throw new ArgumentError(bytes);
-    }
+    ArgumentError.checkNotNull(bytes, 'bytes');
     return _dispatch(_IOService.fileRead, [null, bytes]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "read failed", path);
@@ -761,9 +755,7 @@
 
   List<int> readSync(int bytes) {
     _checkAvailable();
-    if (bytes is! int) {
-      throw new ArgumentError(bytes);
-    }
+    ArgumentError.checkNotNull(bytes, 'bytes');
     var result = _ops.read(bytes);
     if (result is OSError) {
       throw new FileSystemException("readSync failed", path, result);
@@ -815,9 +807,7 @@
   }
 
   Future<RandomAccessFile> writeByte(int value) {
-    if (value is! int) {
-      throw new ArgumentError(value);
-    }
+    ArgumentError.checkNotNull(value, 'value');
     return _dispatch(_IOService.fileWriteByte, [null, value]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "writeByte failed", path);
@@ -829,9 +819,7 @@
 
   int writeByteSync(int value) {
     _checkAvailable();
-    if (value is! int) {
-      throw new ArgumentError(value);
-    }
+    ArgumentError.checkNotNull(value, 'value');
     var result = _ops.writeByte(value);
     if (result is OSError) {
       throw new FileSystemException("writeByte failed", path, result);
@@ -895,17 +883,13 @@
 
   Future<RandomAccessFile> writeString(String string,
       {Encoding encoding: utf8}) {
-    if (encoding is! Encoding) {
-      throw new ArgumentError(encoding);
-    }
+    ArgumentError.checkNotNull(encoding, 'encoding');
     var data = encoding.encode(string);
     return writeFrom(data, 0, data.length);
   }
 
   void writeStringSync(String string, {Encoding encoding: utf8}) {
-    if (encoding is! Encoding) {
-      throw new ArgumentError(encoding);
-    }
+    ArgumentError.checkNotNull(encoding, 'encoding');
     var data = encoding.encode(string);
     writeFromSync(data, 0, data.length);
   }
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 2c995d0..17b05ce 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -165,8 +165,8 @@
     if (Platform.isWindows) {
       path = FileSystemEntity._trimTrailingPathSeparators(path);
     }
-    return _File._dispatchWithNamespace(_IOService.fileStat, [null, path]).then(
-        (response) {
+    return _File._dispatchWithNamespace(_IOService.fileStat, [null, path])
+        .then((response) {
       if (_isErrorResponse(response)) {
         return FileStat._notFound;
       }
@@ -846,7 +846,7 @@
   // TODO(bkonyi): find a way to do this with raw paths.
   static String _trimTrailingPathSeparators(String path) {
     // Don't handle argument errors here.
-    if (path is! String) return path;
+    if (path == null) return path;
     if (Platform.isWindows) {
       while (path.length > 1 &&
           (path.endsWith(Platform.pathSeparator) || path.endsWith('/'))) {
@@ -863,7 +863,7 @@
   // TODO(bkonyi): find a way to do this with raw paths.
   static String _ensureTrailingPathSeparators(String path) {
     // Don't handle argument errors here.
-    if (path is! String) return path;
+    if (path == null) return path;
     if (path.isEmpty) path = '.';
     if (Platform.isWindows) {
       while (!path.endsWith(Platform.pathSeparator) && !path.endsWith('/')) {
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 8b39682..b43c13a 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -162,10 +162,7 @@
   Uint8List _rawPath;
 
   _Link(String path) {
-    if (path is! String) {
-      throw new ArgumentError('${Error.safeToString(path)} '
-          'is not a String');
-    }
+    ArgumentError.checkNotNull(path, 'path');
     _path = path;
     _rawPath = FileSystemEntity._toUtf8Array(path);
   }
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 769eae4..a293b48 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -43,9 +43,7 @@
  * cross-platform issues.
  */
 void exit(int code) {
-  if (code is! int) {
-    throw new ArgumentError("Integer value for exit code expected");
-  }
+  ArgumentError.checkNotNull(code, "code");
   if (!_EmbedderConfig._mayExit) {
     throw new UnsupportedError(
         "This embedder disallows calling dart:io's exit()");
@@ -66,9 +64,7 @@
  * exit code.
  */
 void set exitCode(int code) {
-  if (code is! int) {
-    throw new ArgumentError("Integer value for exit code expected");
-  }
+  ArgumentError.checkNotNull(code, "code");
   _ProcessUtils._setExitCode(code);
 }
 
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 101ea7b..b4c0132 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -581,21 +581,14 @@
     if (host is! String && host is! InternetAddress) {
       throw new ArgumentError("host is not a String or an InternetAddress");
     }
-    if (requestedPort is! int) {
-      throw new ArgumentError("requestedPort is not an int");
-    }
+    ArgumentError.checkNotNull(requestedPort, "requestedPort");
     if (requestedPort < 0 || requestedPort > 65535) {
-      throw new ArgumentError("requestedPort is not in the range 0..65535");
+      throw ArgumentError("requestedPort is not in the range 0..65535");
     }
-    if (requestClientCertificate is! bool) {
-      throw new ArgumentError("requestClientCertificate is not a bool");
-    }
-    if (requireClientCertificate is! bool) {
-      throw new ArgumentError("requireClientCertificate is not a bool");
-    }
-    if (onBadCertificate != null && onBadCertificate is! Function) {
-      throw new ArgumentError("onBadCertificate is not null or a Function");
-    }
+    ArgumentError.checkNotNull(
+        requestClientCertificate, "requestClientCertificate");
+    ArgumentError.checkNotNull(
+        requireClientCertificate, "requireClientCertificate");
   }
 
   int get port => _socket.port;
diff --git a/tests/co19_2/co19_2-analyzer.status b/tests/co19_2/co19_2-analyzer.status
index 5cb30f7..a13758c 100644
--- a/tests/co19_2/co19_2-analyzer.status
+++ b/tests/co19_2/co19_2-analyzer.status
@@ -8,42 +8,12 @@
 Language/Classes/Abstract_Instance_Members/override_default_value_t03: MissingCompileTimeError # Issue 33995
 Language/Classes/Abstract_Instance_Members/override_default_value_t04: MissingCompileTimeError # Issue 33995
 Language/Classes/Abstract_Instance_Members/override_default_value_t05: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t01: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t02: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t04: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t05: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t06: MissingCompileTimeError # Issue 33995
-Language/Classes/Constructors/name_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Constructors/name_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Constructors/name_t03: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t03: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t04: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t05: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t06: MissingCompileTimeError # Legal, see #33235
 Language/Classes/Getters/type_object_t01: CompileTimeError # Issue 33995
 Language/Classes/Getters/type_object_t02: CompileTimeError # Issue 33995
 Language/Classes/Instance_Methods/override_different_default_values_t01: MissingCompileTimeError # Issue 33995
 Language/Classes/Instance_Methods/override_different_default_values_t02: MissingCompileTimeError # Issue 33995
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t01: MissingCompileTimeError # Issue 33995
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t02: MissingCompileTimeError # Issue 27476
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t04: MissingCompileTimeError # Issue 27476
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t05: MissingCompileTimeError # Issue 27476
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t06: MissingCompileTimeError # Issue 27476
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t07: MissingCompileTimeError # Issue 27476
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t09: MissingCompileTimeError # Issue 27476
-Language/Classes/Setters/instance_setter_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t03: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t04: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t05: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t06: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/name_t06: CompileTimeError
-Language/Classes/Setters/name_t07: CompileTimeError
 Language/Classes/Static_Methods/same_name_method_and_setter_t01: CompileTimeError # Invalid test, see #33237
 Language/Classes/method_definition_t06: MissingCompileTimeError # Please triage this failure
-Language/Classes/mixins_t02: MissingCompileTimeError # This syntax is now allowed
 Language/Enums/syntax_t08: CompileTimeError # Issue 33995
 Language/Enums/syntax_t09: CompileTimeError # Issue 33995
 Language/Errors_and_Warnings/static_warning_t01: CompileTimeError # issue #34319
@@ -117,6 +87,33 @@
 Language/Statements/Return/no_expression_function_t16: CompileTimeError # issue #34319
 Language/Statements/Return/no_expression_not_function_t01: CompileTimeError # issue #34319
 Language/Types/Interface_Types/subtype_t30: CompileTimeError # Please triage this failure
+LanguageFeatures/Constant_update2018/CastOperator_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A03_t01/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A03_t02/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t04: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t05: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t07: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t08: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A04_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t03/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/none: CompileTimeError # This feature is not implemented yet
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t04: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t04: CompileTimeError # Please triage this failure
@@ -134,11 +131,12 @@
 LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t04/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t03/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t04/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t05/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t07/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t08/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l3_t02/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/none: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_FutureOr_l1_t02/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t02/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/01: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/02: MissingCompileTimeError # Please triage this failure
@@ -147,8 +145,6 @@
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/05: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/06: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/07: MissingCompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05: MissingCompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t07/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/01: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/02: MissingCompileTimeError # Please triage this failure
@@ -158,10 +154,52 @@
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/06: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/07: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t01/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t02/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t03/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t04/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t05/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t06/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t07: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t08: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t09: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t10: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t13: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t14: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t15: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t21: CompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/constant_set_literals_A03_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/constant_set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A05_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Simple-bounds/dynamic/class_typedef_l1_t02: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t01/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t02/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t03/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t05: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t06: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t07: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_FutureOr_l1_t02: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_l1_t07: CompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_l2_t02/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t06/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t07/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t08/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t09: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t10: MissingCompileTimeError
 LanguageFeatures/Super-bounded-types/static_analysis_A01_t02: CompileTimeError # Issue 32903
 LanguageFeatures/Super-bounded-types/static_analysis_A01_t05: CompileTimeError # Issue 32903
 LanguageFeatures/Super-bounded-types/static_analysis_A01_t08: CompileTimeError # Issue 32903
+LanguageFeatures/Super-mixins/covariance_t03: MissingCompileTimeError # Issue 35111
+LanguageFeatures/Super-mixins/covariance_t06: MissingCompileTimeError # Issue 35111
+LanguageFeatures/Super-mixins/covariance_t07: MissingCompileTimeError # Issue 35111
+LanguageFeatures/Super-mixins/super_invocation_t19: CompileTimeError # Issue 35090
 LanguageFeatures/regression/33585_t01: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/regression/33585_t02: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/regression/33597_t01: MissingCompileTimeError # Please triage this failure
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index 9b8e576..6843d27 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -4,7 +4,6 @@
 
 [ $compiler == dart2js ]
 Language/Classes/Constructors/Generative_Constructors/execution_of_a_superinitializer_t01: RuntimeError
-Language/Classes/mixins_t02: MissingCompileTimeError # co19 issue 163
 Language/Expressions/Assignment/null_aware_assignment_static_type_t01: RuntimeError
 Language/Expressions/Await_Expressions/evaluation_throws_t03: RuntimeError
 Language/Expressions/Booleans/Boolean_Conversion/definition_t01: RuntimeError
@@ -66,6 +65,35 @@
 Language/Types/Interface_Types/subtype_t27: Pass, Crash # Issue 34389
 Language/Types/Type_Declarations/Typedef/dynamic_param_type_t02: RuntimeError
 Language/Variables/constant_initialization_t03: RuntimeError
+LanguageFeatures/Constant_update2018/CastOperator_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A03_t01/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A03_t02/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t04: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t05: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t07: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A02_t08: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A04_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t03/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/none: CompileTimeError # This feature is not implemented yet
 LanguageFeatures/Instantiate-to-bound/FutureOr/dynamic/FutureOr_l1_t01: RuntimeError
 LanguageFeatures/Instantiate-to-bound/FutureOr/dynamic/FutureOr_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
@@ -74,6 +102,7 @@
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t07: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t08: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l3_t02: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/01: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/02: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/none: Crash
@@ -83,18 +112,50 @@
 LanguageFeatures/Instantiate-to-bound/class/static/class_l3_t02/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t04/none: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_FutureOr_l1_t02: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_FutureOr_l1_t05: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t05: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t07: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t01: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t06: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t07: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t08: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t09: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t10: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t11: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t12: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t13: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t14: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t15: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t16: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t20: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t21: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t07/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t01/none: CompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/constant_set_literals_A03_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/constant_set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A05_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
 LanguageFeatures/Simple-bounds/dynamic/FutureOr_l1_t01: RuntimeError, Pass
 LanguageFeatures/Simple-bounds/dynamic/class_FutureOr_l1_t02: CompileTimeError
+LanguageFeatures/Simple-bounds/dynamic/class_typedef_l1_t02: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_FutureOr_l1_t02: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t07: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l2_t01: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t01: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t02: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t03: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t07: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t08: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t10: RuntimeError
 LanguageFeatures/Simple-bounds/static/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t03: CompileTimeError, Pass
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A51_t03: RuntimeError
@@ -117,6 +178,7 @@
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_global_variable_fail_A31_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_global_variable_fail_A32_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_return_value_fail_A31_t01: RuntimeError
+LanguageFeatures/Super-mixins/mixin_member_t06: RuntimeError
 LanguageFeatures/regression/33585_t01: MissingCompileTimeError
 LanguageFeatures/regression/33585_t02: MissingCompileTimeError
 LanguageFeatures/regression/33597_t01: MissingCompileTimeError
@@ -1319,7 +1381,6 @@
 LanguageFeatures/Instantiate-to-bound/check_types/typedef_param_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t10: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_FutureOr_l1_t05: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t05: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t10: RuntimeError
@@ -3598,7 +3659,6 @@
 LanguageFeatures/Instantiate-to-bound/function/function_ret_extends_Future_neg_assign_l1_t07: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t10: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t02/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/01: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/02: MissingCompileTimeError
@@ -3607,7 +3667,6 @@
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/05: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/06: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/07: MissingCompileTimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/01: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/02: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/03: MissingCompileTimeError
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 7abc59e..d739194 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -2,8 +2,11 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-LibTest/io/FileSystemCreateEvent/isDirectory_A01_t06: Pass, Fail # https://github.com/dart-lang/co19/issues/186
 LibTest/io/Stdin/readLineSync_A03_t02: Pass, Fail # https://github.com/dart-lang/co19/issues/184
+LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Slow  # Does many calls
+LibTest/collection/ListMixin/ListMixin_class_A01_t02: Pass, Slow  # Does many calls
+LibTest/core/List/List_class_A01_t02: Pass, Slow  # Does many calls
+LibTest/io/RawDatagramSocket/close_A01_t01: Pass, RuntimeError # https://github.com/dart-lang/co19/issues/195
 
 [ $compiler == dartkp ]
 Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError
@@ -31,8 +34,6 @@
 LibTest/core/Uri/Uri.dataFromString_A01_t01: RuntimeError
 LibTest/core/double/round_A01_t03: RuntimeError
 LibTest/io/Cookie/Cookie_A01_t02: RuntimeError
-LibTest/io/Directory/renameSync_A02_t01: RuntimeError
-LibTest/io/Directory/rename_A02_t01: RuntimeError
 LibTest/io/File/openRead_A01_t04: RuntimeError
 LibTest/io/HttpClientRequest/addStream_A02_t02: RuntimeError
 LibTest/io/HttpClientRequest/add_A03_t01: RuntimeError
@@ -76,14 +77,14 @@
 Language/Statements/For/syntax_t20 tatements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
 
 [ $runtime == vm ]
-LibTest/io/FileSystemEntity/*: Skip # Temporary skip these tests
-LibTest/io/Link/rename_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/174
 LibTest/io/RawDatagramSocket/any_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/any_A01_t03: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/asBroadcastStream_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/distinct_A01_t05: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/lastWhere_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/listen_A02_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/receive_A01_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/where_A01_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/timeout_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
 LibTest/io/RawDatagramSocket/timeout_A06_t01: Pass, Fail # Next roll might fix it (see https://github.com/dart-lang/co19/commit/8b2e2be5bc3bb9fec41efec8ac6fc777e231d915)
 LibTest/io/Stdin/first_A04_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/193
@@ -95,41 +96,12 @@
 Language/Classes/Abstract_Instance_Members/override_default_value_t03: MissingCompileTimeError # Issue 34190
 Language/Classes/Abstract_Instance_Members/override_default_value_t04: MissingCompileTimeError # Issue 34190
 Language/Classes/Abstract_Instance_Members/override_default_value_t05: MissingCompileTimeError # Issue 34190
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t04: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t05: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t06: MissingCompileTimeError # Legal, see #33235
 Language/Classes/Constructors/Generative_Constructors/initializers_t15: CompileTimeError
-Language/Classes/Constructors/name_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Constructors/name_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Constructors/name_t03: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t03: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t04: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t05: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Getters/instance_getter_t06: MissingCompileTimeError # Legal, see #33235
 Language/Classes/Getters/type_object_t01: CompileTimeError
 Language/Classes/Getters/type_object_t02: CompileTimeError
 Language/Classes/Instance_Methods/Operators/return_type_t01: MissingCompileTimeError
 Language/Classes/Instance_Methods/override_different_default_values_t01: MissingCompileTimeError # Issue 34190
 Language/Classes/Instance_Methods/override_different_default_values_t02: MissingCompileTimeError # Issue 34190
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t04: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t05: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t06: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t07: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t09: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t01: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t02: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t03: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t04: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t05: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/instance_setter_t06: MissingCompileTimeError # Legal, see #33235
-Language/Classes/Setters/name_t06: CompileTimeError
-Language/Classes/Setters/name_t07: CompileTimeError
 Language/Classes/Setters/return_type_not_void_t01: MissingCompileTimeError
 Language/Classes/Setters/same_name_getter_different_type_t01: MissingCompileTimeError
 Language/Classes/Setters/syntax_t04: MissingCompileTimeError
@@ -138,7 +110,6 @@
 Language/Classes/Superclasses/wrong_superclass_t08: MissingCompileTimeError # Issue 30273
 Language/Classes/Superinterfaces/wrong_type_t05: MissingCompileTimeError # Issue 30273
 Language/Classes/method_definition_t06: MissingCompileTimeError # Legal
-Language/Classes/mixins_t02: MissingCompileTimeError # co19 issue 163
 Language/Enums/syntax_t08: CompileTimeError
 Language/Enums/syntax_t09: CompileTimeError
 Language/Expressions/Assignable_Expressions/syntax_t01: CompileTimeError
@@ -217,6 +188,29 @@
 Language/Statements/Continue/label_t07: MissingCompileTimeError # Issue 34206
 Language/Statements/Try/catch_scope_t01: CompileTimeError
 Language/Types/Interface_Types/subtype_t30: CompileTimeError
+LanguageFeatures/Constant_update2018/CastOperator_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A03_t01/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/CastOperator_A03_t02/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/NewOperators_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A04_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t02: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t03/none: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/none: CompileTimeError # This feature is not implemented yet
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t01: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t03: Crash
@@ -227,6 +221,7 @@
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t07: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t08: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l3_t02: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/01: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/02: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/03: Crash
@@ -250,7 +245,11 @@
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t04/01: Crash, Pass
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t04/none: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t08/01: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t08/02: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t08/none: Crash, Pass
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t07: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_FutureOr_l1_t02/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t02/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/01: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/02: MissingCompileTimeError
@@ -259,8 +258,6 @@
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/05: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/06: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/07: MissingCompileTimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05: MissingCompileTimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t07/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/01: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/02: MissingCompileTimeError
@@ -270,9 +267,38 @@
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/06: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/07: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t01/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t06/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t15: CompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/constant_set_literals_A03_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/constant_set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A04_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A05_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
+LanguageFeatures/Set-literals/set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
 LanguageFeatures/Simple-bounds/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Simple-bounds/static/class_FutureOr_l1_t02: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t01/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t02/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t03/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t05: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t06: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/class_typedef_l1_t07: MissingCompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_FutureOr_l1_t02: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_l1_t07: CompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_l2_t02/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t06/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t07/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t08/none: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_typedef_l1_t09: MissingCompileTimeError
+LanguageFeatures/Super-mixins/covariance_t03: MissingCompileTimeError # Issue 35111
+LanguageFeatures/Super-mixins/covariance_t06: MissingCompileTimeError # Issue 35111
+LanguageFeatures/Super-mixins/covariance_t07: MissingCompileTimeError # Issue 35111
 LanguageFeatures/regression/33585_t01: MissingCompileTimeError
 LanguageFeatures/regression/33585_t02: MissingCompileTimeError
 LanguageFeatures/regression/33597_t01: MissingCompileTimeError
@@ -284,6 +310,11 @@
 LanguageFeatures/regression/34803_t02: Crash
 LibTest/async/Future/Future_A01_t01: CompileTimeError
 
+[ $arch == simdbc64 && $compiler == dartk ]
+LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Issue http://dartbug.com/35242
+LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Issue http://dartbug.com/35242
+LibTest/core/List/List_class_A01_t02: Crash # Issue http://dartbug.com/35242
+
 [ $arch == simdbc64 && $system == macos && ($compiler == dartk || $compiler == dartkb) ]
 LanguageFeatures/Subtyping/static/generated/function_type_function_arguments_binding_A04_t02: Crash, Pass
 LibTest/io/Directory/watch_A01_t02: RuntimeError, Pass
@@ -296,7 +327,6 @@
 LibTest/io/Stdout/writeCharCode_A01_t03: Timeout, Pass
 
 [ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError
 LibTest/collection/ListBase/ListBase_class_A01_t02: Timeout, Pass
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Timeout, Pass
 LibTest/io/Link/renameSync_A02_t01: RuntimeError, Pass
@@ -388,6 +418,9 @@
 LibTest/isolate/Isolate/spawn_A06_t03: Crash, Pass
 
 [ $runtime == vm && $system == macos && ($compiler == dartk || $compiler == dartkb) ]
+LibTest/collection/ListBase/ListBase_class_A01_t02: Timeout, Pass, Slow  # https://github.com/dart-lang/co19/issues/198
+LibTest/collection/ListMixin/ListMixin_class_A01_t02: Timeout, Pass, Slow  # https://github.com/dart-lang/co19/issues/198
+LibTest/core/List/List_class_A01_t02: Timeout, Pass, Slow  # https://github.com/dart-lang/co19/issues/198
 LibTest/io/Directory/watch_A01_t02: RuntimeError, Pass
 LibTest/io/Directory/watch_A02_t01: RuntimeError, Pass
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t03: RuntimeError, Pass
@@ -397,11 +430,10 @@
 LibTest/io/FileSystemCreateEvent/type_A01_t01: RuntimeError, Pass
 LibTest/io/FileSystemCreateEvent/type_A01_t02: RuntimeError, Pass
 LibTest/io/FileSystemCreateEvent/type_A01_t03: RuntimeError, Pass, Timeout
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t01: RuntimeError, Timeout
+LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t07: RuntimeError
 LibTest/io/FileSystemDeleteEvent/path_A01_t02: RuntimeError, Pass
 LibTest/io/FileSystemDeleteEvent/path_A01_t03: RuntimeError, Pass
 LibTest/io/FileSystemDeleteEvent/type_A01_t03: RuntimeError, Pass
-LibTest/io/FileSystemEntity/isWatchSupported_A01_t01: RuntimeError
 LibTest/io/FileSystemModifyEvent/contentChanged_A01_t01: Fail, Timeout
 LibTest/io/FileSystemModifyEvent/contentChanged_A01_t02: Timeout, Pass
 LibTest/io/FileSystemModifyEvent/isDirectory_A01_t01: Timeout, Pass
@@ -538,16 +570,7 @@
 LibTest/math/atan_A01_t01: RuntimeError
 LibTest/math/cos_A01_t01: RuntimeError
 
-[ $runtime == vm && $system != macos ]
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t07: Fail # Issue 35032
-
 [ $runtime == vm && $system != macos && ($compiler == dartk || $compiler == dartkb) ]
-LibTest/io/Directory/listSync_A01_t02: RuntimeError
-LibTest/io/Directory/listSync_A01_t03: RuntimeError
-LibTest/io/Directory/listSync_A01_t04: RuntimeError
-LibTest/io/Directory/list_A01_t02: RuntimeError
-LibTest/io/Directory/list_A01_t03: RuntimeError
-LibTest/io/Directory/list_A01_t04: RuntimeError
 LibTest/io/InternetAddress/lookup_A02_t01: RuntimeError
 LibTest/io/InternetAddress/lookup_A03_t01: RuntimeError
 LibTest/io/InternetAddress/lookup_A03_t02: RuntimeError
@@ -561,12 +584,24 @@
 Language/Mixins/Mixin_Application/syntax_t16: CompileTimeError
 Language/Statements/Assert/execution_t08: RuntimeError
 Language/Types/Function_Types/call_t01: RuntimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t04/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t08/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: DartkCrash
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t02: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_FutureOr_l1_t02: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t06: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t11: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t12: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t13: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t14: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t15: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t16: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/class_typedef_l1_t02: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_FutureOr_l1_t02: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t07: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l2_t02: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t07: RuntimeError
 LanguageFeatures/regression/33701_t01: MissingCompileTimeError
 LanguageFeatures/regression/34803_t01: DartkCrash
 LanguageFeatures/regression/34803_t02: DartkCrash
@@ -611,11 +646,11 @@
 LibTest/core/int/isOdd_A01_t01: RuntimeError
 LibTest/io/Cookie/Cookie_A01_t04: RuntimeError
 LibTest/io/Directory/watch_A01_t01: Fail, Pass
-LibTest/io/Directory/watch_A02_t01: Timeout
+LibTest/io/Directory/watch_A02_t01: Fail
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t01: Fail, Pass
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t02: Fail, Pass
 LibTest/io/FileSystemCreateEvent/path_A01_t01: Fail, Pass
-LibTest/io/FileSystemEntity/identical_A01_t06: Pass, RuntimeError # Issue 183 (co19)
+LibTest/io/FileSystemEntity/identical_A01_t06: Fail
 LibTest/io/FileSystemModifyEvent/isDirectory_A01_t02: Fail
 LibTest/io/FileSystemModifyEvent/path_A01_t01: Fail
 LibTest/io/FileSystemModifyEvent/type_A01_t02: Fail
@@ -669,6 +704,7 @@
 LibTest/io/WebSocket/connect_A01_t02: RuntimeError
 LibTest/isolate/Isolate/pause_A01_t01: Timeout, Pass
 LibTest/isolate/Isolate/pause_A01_t02: Timeout, Pass
+LibTest/isolate/Isolate/ping_A02_t01: Timeout, Pass
 LibTest/isolate/Isolate/ping_A03_t01: RuntimeError, Pass
 LibTest/isolate/Isolate/ping_A03_t02: RuntimeError, Pass
 LibTest/isolate/ReceivePort/firstWhere_A01_t01: RuntimeError
@@ -885,8 +921,6 @@
 Language/Types/Type_Declarations/Typedef/dynamic_param_type_t02: RuntimeError
 Language/Variables/constant_initialization_t03: RuntimeError
 Language/Variables/constant_variable_t09: RuntimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t05: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t05/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t01: RuntimeError
 LibTest/async/Future/asStream_A01_t02: RuntimeError
@@ -1020,8 +1054,6 @@
 LibTest/io/Directory/delete_A02_t05: RuntimeError
 LibTest/io/Directory/existsSync_A02_t02: RuntimeError
 LibTest/io/Directory/exists_A02_t02: RuntimeError
-LibTest/io/Directory/renameSync_A02_t01: RuntimeError
-LibTest/io/Directory/rename_A02_t01: RuntimeError
 LibTest/io/Directory/statSync_A01_t05: RuntimeError
 LibTest/io/Directory/stat_A01_t05: RuntimeError
 LibTest/io/File/openRead_A01_t04: RuntimeError
@@ -1040,7 +1072,6 @@
 LibTest/io/FileSystemEntity/isDirectorySync_A01_t03: RuntimeError
 LibTest/io/FileSystemEntity/isDirectory_A01_t03: RuntimeError
 LibTest/io/FileSystemEntity/isFileSync_A01_t03: RuntimeError
-LibTest/io/FileSystemEntity/isFile_A01_t01: RuntimeError
 LibTest/io/FileSystemEntity/isFile_A01_t03: RuntimeError
 LibTest/io/FileSystemModifyEvent/path_A01_t01: RuntimeError
 LibTest/io/HttpClient/addCredentials_A03_t01: RuntimeError
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index cbfbbb8b..c5f2dd0 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -11,9 +11,9 @@
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/diagnostics/source_span.dart';
-import 'package:compiler/src/library_loader.dart';
 import 'package:compiler/src/ir/static_type.dart';
 import 'package:compiler/src/ir/util.dart';
+import 'package:compiler/src/kernel/loader.dart';
 import 'package:compiler/src/util/uri_extras.dart';
 import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart' as ir;
@@ -57,10 +57,9 @@
         librariesSpecificationUri: librariesSpecificationUri,
         packageConfig: packageConfig,
         options: options);
-    LoadedLibraries loadedLibraries =
-        await compiler.libraryLoader.loadLibraries(entryPoint);
-    new DynamicVisitor(compiler.reporter, loadedLibraries.component,
-            allowedListPath, analyzedUrisFilter)
+    KernelResult result = await compiler.kernelLoader.load(entryPoint);
+    new DynamicVisitor(compiler.reporter, result.component, allowedListPath,
+            analyzedUrisFilter)
         .run(verbose: verbose, generate: generate);
   });
 }
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index ea21856..920dc49 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -195,9 +195,6 @@
     "Dynamic access of 'names'.": 1,
     "Dynamic access of 'isNonLeaf'.": 1
   },
-  "pkg/compiler/lib/src/universe/world_builder.dart": {
-    "Dynamic access of 'cls'.": 1
-  },
   "pkg/compiler/lib/src/elements/names.dart": {
     "Dynamic access of 'library'.": 1
   },
diff --git a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
index 09d8882..00403a7 100644
--- a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
+++ b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
@@ -5,7 +5,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/ir/static_type.dart';
-import 'package:compiler/src/library_loader.dart';
+import 'package:compiler/src/kernel/loader.dart';
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
@@ -21,9 +21,9 @@
   asyncTest(() async {
     Compiler compiler =
         await compilerFor(memorySourceFiles: {'main.dart': source});
-    LoadedLibraries loadedLibraries = await compiler.libraryLoader
-        .loadLibraries(Uri.parse('memory:main.dart'));
-    ir.Component component = loadedLibraries.component;
+    KernelResult result =
+        await compiler.kernelLoader.load(Uri.parse('memory:main.dart'));
+    ir.Component component = result.component;
     StaticTypeVisitor visitor = new Visitor(component);
     component.accept(visitor);
   });
diff --git a/tests/compiler/dart2js/deferred/load_mapping_test.dart b/tests/compiler/dart2js/deferred/load_mapping_test.dart
index 6736599..74c0c43 100644
--- a/tests/compiler/dart2js/deferred/load_mapping_test.dart
+++ b/tests/compiler/dart2js/deferred/load_mapping_test.dart
@@ -19,7 +19,8 @@
     CompilerImpl compiler = result.compiler;
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     // Ensure a mapping file is output.
-    Expect.isNotNull(collector.getOutput("deferred_map.json", OutputType.info));
+    Expect.isNotNull(
+        collector.getOutput("deferred_map.json", OutputType.deferredMap));
 
     Map mapping = closedWorld.outputUnitData
         .computeDeferredMap(compiler.options, closedWorld.elementEnvironment);
diff --git a/tests/compiler/dart2js/end_to_end/dill_loader_test.dart b/tests/compiler/dart2js/end_to_end/dill_loader_test.dart
index 3b3c0e6..56bf3e6 100644
--- a/tests/compiler/dart2js/end_to_end/dill_loader_test.dart
+++ b/tests/compiler/dart2js/end_to_end/dill_loader_test.dart
@@ -9,7 +9,7 @@
 import 'package:compiler/src/elements/entities.dart'
     show LibraryEntity, ClassEntity;
 import 'package:compiler/src/kernel/dart2js_target.dart';
-import 'package:compiler/src/library_loader.dart';
+import 'package:compiler/src/kernel/loader.dart';
 import 'package:expect/expect.dart';
 import 'package:front_end/src/api_prototype/front_end.dart';
 import 'package:front_end/src/compute_platform_binaries_location.dart'
@@ -44,9 +44,8 @@
         diagnosticHandler: diagnostics,
         outputProvider: output);
     await compiler.setupSdk();
-    LoadedLibraries loadedLibraries =
-        await compiler.libraryLoader.loadLibraries(entryPoint);
-    compiler.frontendStrategy.registerLoadedLibraries(loadedLibraries);
+    KernelResult result = await compiler.kernelLoader.load(entryPoint);
+    compiler.frontendStrategy.registerLoadedLibraries(result);
 
     Expect.equals(0, diagnostics.errors.length);
     Expect.equals(0, diagnostics.warnings.length);
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 8c7624f..52657e0 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -21,7 +21,6 @@
 import 'package:compiler/src/apiimpl.dart' as apiimpl;
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/js_backend.dart';
-import 'package:compiler/src/library_loader.dart';
 import 'package:compiler/src/null_compiler_output.dart';
 import 'package:compiler/src/options.dart' show CompilerOptions;
 import 'package:compiler/src/types/types.dart';
@@ -60,11 +59,6 @@
     return super.run(uri);
   }
 
-  void processLoadedLibraries(LoadedLibraries loadedLibraries) {
-    test('Compiler.processLoadedLibraries');
-    super.processLoadedLibraries(loadedLibraries);
-  }
-
   test(String marker) {
     if (marker == testMarker) {
       switch (testType) {
@@ -239,7 +233,6 @@
   final tests = {
     'Compiler': beforeRun,
     'Compiler.run': beforeRun,
-    'Compiler.processLoadedLibraries': beforeRun,
     'Compiler.withCurrentElement': duringRun,
     'Compiler.codegen': duringRun,
   };
diff --git a/tests/compiler/dart2js/helpers/memory_compiler.dart b/tests/compiler/dart2js/helpers/memory_compiler.dart
index 079ac0b..6062660 100644
--- a/tests/compiler/dart2js/helpers/memory_compiler.dart
+++ b/tests/compiler/dart2js/helpers/memory_compiler.dart
@@ -94,7 +94,7 @@
   }
   bool isSuccess = await compiler.run(entryPoint);
   fe.InitializedCompilerState compilerState = kernelInitializedCompilerState =
-      compiler.libraryLoader.initializedCompilerState;
+      compiler.kernelLoader.initializedCompilerState;
   return new CompilationResult(compiler,
       isSuccess: isSuccess, kernelInitializedCompilerState: compilerState);
 }
diff --git a/tests/compiler/dart2js/helpers/text_helpers.dart b/tests/compiler/dart2js/helpers/text_helpers.dart
index ce1254c..e9723d2 100644
--- a/tests/compiler/dart2js/helpers/text_helpers.dart
+++ b/tests/compiler/dart2js/helpers/text_helpers.dart
@@ -6,40 +6,68 @@
 /// of the [windowSize] lines before and after are printed and the mismatch line
 /// number is returned. If identical, nothing is printed and `null` is returned.
 int checkEqualContentAndShowDiff(String text1, String text2,
-    {int windowSize: 20}) {
+    {int windowSize: 20,
+    bool Function(int, List<String>, List<String>) filter}) {
   List<String> lines1 = text1.split('\n');
   List<String> lines2 = text2.split('\n');
   for (int i = 0; i < lines1.length && i < lines2.length; i++) {
     if (i >= lines1.length || i >= lines2.length || lines1[i] != lines2[i]) {
-      for (int j = i - windowSize; j < i + windowSize; j++) {
-        if (j < 0) continue;
-        String line1 = 0 <= j && j < lines1.length ? lines1[j] : null;
-        String line2 = 0 <= j && j < lines2.length ? lines2[j] : null;
-        if (line1 == line2) {
-          print('  $j $line1');
-        } else {
-          String text = line1 == null ? '<eof>' : line1;
-          String newText = line2 == null ? '<eof>' : line2;
-          print('- $j ${text}');
-          print('+ $j ${newText}');
-          if (text.length > 80 && newText.length > 80) {
-            assert(text != newText);
-            StringBuffer diff = new StringBuffer();
-            diff.write('  $j ');
-            for (int k = 0; k < text.length && k < newText.length; k++) {
-              int char1 = k < text.length ? text.codeUnitAt(k) : null;
-              int char2 = k < newText.length ? newText.codeUnitAt(k) : null;
-              if (char1 != char2) {
-                diff.write('^');
-              } else {
-                diff.write(' ');
-              }
-            }
-            print(diff);
+      if (filter != null && filter(i, lines1, lines2)) {
+        String line1 = 0 <= i && i < lines1.length ? lines1[i] : null;
+        String line2 = 0 <= i && i < lines2.length ? lines2[i] : null;
+        String text = line1 == null ? '<eof>' : line1;
+        String newText = line2 == null ? '<eof>' : line2;
+        print('(skipped) - $i ${text}');
+        print('(skipped) + $i ${newText}');
+      } else {
+        List<String> pendingLines = <String>[];
+
+        void flushPendingLines() {
+          if (pendingLines.isNotEmpty) {
+            print(pendingLines.join('\n'));
+            pendingLines.clear();
           }
         }
+
+        for (int j = i - windowSize; j < i + windowSize; j++) {
+          if (j < 0) continue;
+          String line1 = 0 <= j && j < lines1.length ? lines1[j] : null;
+          String line2 = 0 <= j && j < lines2.length ? lines2[j] : null;
+          if (line1 == line2) {
+            flushPendingLines();
+            if (line1 != null) {
+              print('  $j $line1');
+            }
+          } else {
+            String text = line1 == null ? '<eof>' : line1;
+            String newText = line2 == null ? '<eof>' : line2;
+
+            if (text.length > 80 && newText.length > 80) {
+              flushPendingLines();
+              print('- $j ${text}');
+              print('+ $j ${newText}');
+              assert(text != newText);
+              StringBuffer diff = new StringBuffer();
+              diff.write('  $j ');
+              for (int k = 0; k < text.length && k < newText.length; k++) {
+                int char1 = k < text.length ? text.codeUnitAt(k) : null;
+                int char2 = k < newText.length ? newText.codeUnitAt(k) : null;
+                if (char1 != char2) {
+                  diff.write('^');
+                } else {
+                  diff.write(' ');
+                }
+              }
+              print(diff);
+            } else {
+              print('- $j ${text}');
+              pendingLines.add('+ $j ${newText}');
+            }
+          }
+        }
+        flushPendingLines();
+        return i;
       }
-      return i;
     }
   }
   return null;
diff --git a/tests/compiler/dart2js/impact/data/effectively_final.dart b/tests/compiler/dart2js/impact/data/effectively_final.dart
new file mode 100644
index 0000000..305ca2b
--- /dev/null
+++ b/tests/compiler/dart2js/impact/data/effectively_final.dart
@@ -0,0 +1,114 @@
+// 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.
+
+/*element: main:
+ static=[
+  effectivelyFinalList(0),
+  effectivelyFinalPromoted(0),
+  effectivelyFinalPromotedInvalid(0),
+  notEffectivelyFinalList(0)]
+*/
+main() {
+  effectivelyFinalList();
+  notEffectivelyFinalList();
+  effectivelyFinalPromoted();
+  effectivelyFinalPromotedInvalid();
+}
+
+/*element: effectivelyFinalList:
+ dynamic=[
+  List.add(1),
+  List.length,
+  List.length=,
+  int.+],
+ type=[
+  inst:JSDouble,
+  inst:JSInt,
+  inst:JSNull,
+  inst:JSNumber,
+  inst:JSPositiveInt,
+  inst:JSUInt31,
+  inst:JSUInt32,
+  inst:List<dynamic>]
+*/
+effectivelyFinalList() {
+  dynamic c = [];
+  c.add(null);
+  c.length + 1;
+  c.length = 1;
+}
+
+/*element: notEffectivelyFinalList:
+ dynamic=[
+  +,
+  add(1),
+  call(1),
+  length,
+  length=],
+ type=[
+  inst:JSDouble,
+  inst:JSInt,
+  inst:JSNull,
+  inst:JSNumber,
+  inst:JSPositiveInt,
+  inst:JSUInt31,
+  inst:JSUInt32,
+  inst:List<dynamic>]
+*/
+notEffectivelyFinalList() {
+  dynamic c = [];
+  c.add(null);
+  c.length + 1;
+  c.length = 1;
+  c = null;
+}
+
+/*element: _method1:type=[inst:JSNull]*/
+num _method1() => null;
+
+/*element: effectivelyFinalPromoted:
+ dynamic=[int.+,num.+],
+ static=[_method1(0)],
+ type=[
+  inst:JSBool,
+  inst:JSDouble,
+  inst:JSInt,
+  inst:JSNumber,
+  inst:JSPositiveInt,
+  inst:JSUInt31,
+  inst:JSUInt32,
+  is:int]
+*/
+effectivelyFinalPromoted() {
+  dynamic c = _method1();
+  c + 0;
+  if (c is int) {
+    c + 1;
+  }
+}
+
+/*element: _method2:type=[inst:JSNull]*/
+String _method2() => null;
+
+/*element: effectivelyFinalPromotedInvalid:
+ dynamic=[String.+,int.+],
+ static=[_method2(0)],
+ type=[
+  inst:JSBool,
+  inst:JSDouble,
+  inst:JSInt,
+  inst:JSNumber,
+  inst:JSPositiveInt,
+  inst:JSString,
+  inst:JSUInt31,
+  inst:JSUInt32,
+  is:int]
+*/
+effectivelyFinalPromotedInvalid() {
+  dynamic c = _method2();
+  c + '';
+  if (c is int) {
+    c + 1;
+  }
+}
diff --git a/tests/compiler/dart2js/impact/data/runtime_type_strong.dart b/tests/compiler/dart2js/impact/data/runtime_type_strong.dart
index 63d2dea..32fa0a7 100644
--- a/tests/compiler/dart2js/impact/data/runtime_type_strong.dart
+++ b/tests/compiler/dart2js/impact/data/runtime_type_strong.dart
@@ -5,7 +5,7 @@
 /*element: Class1a.:static=[Object.(0)]*/
 class Class1a<T> {
   /*element: Class1a.==:
-   dynamic=[Class1a.runtimeType,Object.runtimeType,Type.==],
+   dynamic=[<Class1a.runtimeType,Object.runtimeType,Type.==],
    runtimeType=[equals:Class1a<Class1a.T>/dynamic]
   */
   bool operator ==(other) {
@@ -16,7 +16,7 @@
 /*element: Class1b.:static=[Class1a.(0)]*/
 class Class1b<T> extends Class1a<T> {
   /*element: Class1b.==:
-   dynamic=[Class1b.runtimeType,Object.runtimeType,Type.==],
+   dynamic=[<Class1b.runtimeType,Object.runtimeType,Type.==],
    runtimeType=[equals:dynamic/Class1b<Class1b.T>]
   */
   bool operator ==(other) {
@@ -27,7 +27,7 @@
 /*element: Class1c.:static=[Object.(0)]*/
 class Class1c<T> implements Class1a<T> {
   /*element: Class1c.==:
-   dynamic=[Class1c.runtimeType,Object.==,Object.runtimeType,Type.==],
+   dynamic=[<Class1c.runtimeType,Object.==,Object.runtimeType,Type.==],
    runtimeType=[equals:Class1c<Class1c.T>/dynamic],
    type=[inst:JSNull]
   */
@@ -39,7 +39,7 @@
 /*element: Class1d.:static=[Object.(0)]*/
 class Class1d<T> implements Class1a<T> {
   /*element: Class1d.==:
-   dynamic=[Class1d.runtimeType,Object.==,Object.runtimeType,Type.==],
+   dynamic=[<Class1d.runtimeType,Object.==,Object.runtimeType,Type.==],
    runtimeType=[equals:dynamic/Class1d<Class1d.T>],
    type=[inst:JSNull]
   */
diff --git a/tests/compiler/dart2js/impact/data/this.dart b/tests/compiler/dart2js/impact/data/this.dart
new file mode 100644
index 0000000..2579dda
--- /dev/null
+++ b/tests/compiler/dart2js/impact/data/this.dart
@@ -0,0 +1,69 @@
+// 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.
+
+/*element: Class.:static=[Object.(0)]*/
+class Class {
+  /*element: Class.field1:type=[inst:JSNull]*/
+  var field1;
+
+  /*element: Class.field2:type=[inst:JSNull]*/
+  var field2;
+
+  /*element: Class.method1:dynamic=[<Class.method2(0)]*/
+  method1() {
+    method2();
+  }
+
+  /*element: Class.method2:dynamic=[<Class.field1=,<Class.field2]*/
+  method2() {
+    field1 = field2;
+  }
+}
+
+/*element: Subclass.:static=[Class.(0)]*/
+class Subclass extends Class {
+  /*element: Subclass.field1:type=[inst:JSNull]*/
+  var field1;
+  /*element: Subclass.field2:type=[inst:JSNull]*/
+  var field2;
+
+  /*element: Subclass.method1:*/
+  method1() {}
+
+  /*element: Subclass.method2:dynamic=[<Subclass.method3(0)]*/
+  method2() {
+    method3();
+  }
+
+  method3() {}
+}
+
+/*element: Subtype.:static=[Object.(0)]*/
+class Subtype implements Class {
+  /*element: Subtype.field1:type=[inst:JSNull]*/
+  var field1;
+  /*element: Subtype.field2:type=[inst:JSNull]*/
+  var field2;
+
+  method1() {}
+
+  method2() {
+    method4();
+  }
+
+  method4() {
+    method2();
+  }
+}
+
+/*element: main:
+ dynamic=[Class.method1(0)],
+ static=[Class.(0),Subclass.(0),Subtype.(0)]
+*/
+main() {
+  var c = new Class();
+  c = new Subclass();
+  c = new Subtype();
+  c.method1();
+}
diff --git a/tests/compiler/dart2js/inference/data/locals_notrust.dart b/tests/compiler/dart2js/inference/data/locals_notrust.dart
index 35f518a..fbd9b464 100644
--- a/tests/compiler/dart2js/inference/data/locals_notrust.dart
+++ b/tests/compiler/dart2js/inference/data/locals_notrust.dart
@@ -35,6 +35,7 @@
 /*element: _dontTrustFunctions:[exact=JSBool]*/
 _dontTrustFunctions(int Function(int) /*[null|subclass=Closure]*/ f) {
   dynamic c = f(0);
+  c = f(0);
   return c == 0;
 }
 
diff --git a/tests/compiler/dart2js/inference/data/locals_trust.dart b/tests/compiler/dart2js/inference/data/locals_trust.dart
index c179e96..b937783 100644
--- a/tests/compiler/dart2js/inference/data/locals_trust.dart
+++ b/tests/compiler/dart2js/inference/data/locals_trust.dart
@@ -34,6 +34,7 @@
 /*element: _dontTrustFunctions:[exact=JSBool]*/
 _dontTrustFunctions(int Function(int) /*[null|subclass=Closure]*/ f) {
   dynamic c = f(0);
+  c = f(0);
   return c == 0;
 }
 
diff --git a/tests/compiler/dart2js/inference/data/null.dart b/tests/compiler/dart2js/inference/data/null.dart
new file mode 100644
index 0000000..b91c581
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/null.dart
@@ -0,0 +1,97 @@
+// 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.
+
+/*element: main:[null]*/
+main() {
+  ifThenNullCheck(0);
+  ifThenNullCheck(null);
+  ifThenElseNullCheck(0);
+  ifThenElseNullCheck(null);
+  ifNotThenNullCheck(0);
+  ifNotThenNullCheck(null);
+  ifNotThenElseNullCheck(0);
+  ifNotThenElseNullCheck(null);
+  ifThenNotNullComplexCheck(0, 0);
+  ifThenNotNullComplexCheck(null, null);
+  ifThenElseNotNullComplexCheck(0, 0);
+  ifThenElseNotNullComplexCheck(null, null);
+  ifThenNotNullGradualCheck1(0, 0);
+  ifThenNotNullGradualCheck1(null, 0);
+  ifThenNotNullGradualCheck2(0, 0);
+  ifThenNotNullGradualCheck2(null, 0);
+}
+
+/*element: ifThenNullCheck:[exact=JSUInt31]*/
+ifThenNullCheck(int /*[null|exact=JSUInt31]*/ value) {
+  if (value == null) {
+    return 0;
+  }
+  return value;
+}
+
+/*element: ifThenElseNullCheck:[exact=JSUInt31]*/
+ifThenElseNullCheck(int /*[null|exact=JSUInt31]*/ value) {
+  if (value == null) {
+    return 0;
+  } else {
+    return value;
+  }
+}
+
+/*element: ifNotThenNullCheck:[exact=JSUInt31]*/
+ifNotThenNullCheck(int /*[null|exact=JSUInt31]*/ value) {
+  if (value != null) {
+    return value;
+  }
+  return 0;
+}
+
+/*element: ifNotThenElseNullCheck:[exact=JSUInt31]*/
+ifNotThenElseNullCheck(int /*[null|exact=JSUInt31]*/ value) {
+  if (value != null) {
+    return value;
+  } else {
+    return 0;
+  }
+}
+
+/*element: ifThenNotNullComplexCheck:[null|exact=JSUInt31]*/
+ifThenNotNullComplexCheck(
+    int /*[null|exact=JSUInt31]*/ a, int /*[null|exact=JSUInt31]*/ b) {
+  if (a != null && a /*invoke: [exact=JSUInt31]*/ != b) {
+    return a;
+  }
+  return 0;
+}
+
+/*element: ifThenElseNotNullComplexCheck:[null|exact=JSUInt31]*/
+ifThenElseNotNullComplexCheck(
+    int /*[null|exact=JSUInt31]*/ a, int /*[null|exact=JSUInt31]*/ b) {
+  if (a != null && a /*invoke: [exact=JSUInt31]*/ != b) {
+    return a;
+  }
+  return a;
+}
+
+/*element: ifThenNotNullGradualCheck1:[exact=JSUInt31]*/
+ifThenNotNullGradualCheck1(
+    int /*[null|exact=JSUInt31]*/ a, int /*[exact=JSUInt31]*/ b) {
+  if (a /*invoke: [null|exact=JSUInt31]*/ != b) {
+    if (a != null) {
+      return a;
+    }
+  }
+  return 0;
+}
+
+/*element: ifThenNotNullGradualCheck2:[exact=JSUInt31]*/
+ifThenNotNullGradualCheck2(
+    int /*[null|exact=JSUInt31]*/ a, int /*[exact=JSUInt31]*/ b) {
+  if (a != null) {
+    if (a /*invoke: [exact=JSUInt31]*/ != b) {
+      return a;
+    }
+  }
+  return 0;
+}
diff --git a/tests/compiler/dart2js/js/js_spec_string_test.dart b/tests/compiler/dart2js/js/js_spec_string_test.dart
index 4f301af..1e7080d 100644
--- a/tests/compiler/dart2js/js/js_spec_string_test.dart
+++ b/tests/compiler/dart2js/js/js_spec_string_test.dart
@@ -5,7 +5,7 @@
 // Unit test of the [NativeBehavior.processSpecString] method.
 
 import 'package:expect/expect.dart';
-import 'package:compiler/src/native/native.dart';
+import 'package:compiler/src/native/behavior.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/universe/side_effects.dart' show SideEffects;
diff --git a/tests/compiler/dart2js/js/js_throw_behavior_test.dart b/tests/compiler/dart2js/js/js_throw_behavior_test.dart
index e0b75b9..22fb733 100644
--- a/tests/compiler/dart2js/js/js_throw_behavior_test.dart
+++ b/tests/compiler/dart2js/js/js_throw_behavior_test.dart
@@ -3,7 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:expect/expect.dart';
-import 'package:compiler/src/native/native.dart';
+import 'package:compiler/src/native/behavior.dart';
+import 'package:compiler/src/native/js.dart';
 import 'package:compiler/src/js/js.dart' as js;
 
 void test(String source, NativeThrowBehavior expectedThrowBehavior) {
diff --git a/tests/compiler/dart2js/model/open_world_test.dart b/tests/compiler/dart2js/model/open_world_test.dart
new file mode 100644
index 0000000..b315b5c
--- /dev/null
+++ b/tests/compiler/dart2js/model/open_world_test.dart
@@ -0,0 +1,434 @@
+// 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';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/common_elements.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/ir/static_type.dart';
+import 'package:compiler/src/js_backend/native_data.dart';
+import 'package:compiler/src/universe/resolution_world_builder.dart';
+import 'package:compiler/src/universe/world_builder.dart';
+import '../helpers/memory_compiler.dart';
+
+main() {
+  asyncTest(() async {
+    await runTest();
+  });
+}
+
+runTest() async {
+  String classes = '''
+@JS()
+library lib;
+
+import 'package:js/js.dart';
+
+class A {}
+class A1 extends A {}
+class A2 extends A1 {}
+
+class B implements A {}
+class B1 extends B {}
+
+class C {}
+class C0 {}
+class C1 = C with A;
+class C2 extends C1 {}
+class C3 = C with C0, A;
+class C4 = C with A, C0;
+
+@JS()
+class D {}
+
+@JS()
+class D1 extends D {}
+
+''';
+
+  CommonElements commonElements;
+  NativeBasicData nativeBasicData;
+  ResolutionWorldBuilderImpl world;
+
+  List<ClassEntity> allClasses;
+
+  ClassEntity A;
+  ClassEntity A1;
+  ClassEntity A2;
+  ClassEntity B;
+  ClassEntity B1;
+  ClassEntity C;
+  ClassEntity C0;
+  ClassEntity C1;
+  ClassEntity C2;
+  ClassEntity C3;
+  ClassEntity C4;
+  ClassEntity D;
+  ClassEntity D1;
+
+  List<ClassRelation> allRelations = ClassRelation.values;
+  List<ClassRelation> notExact = [
+    ClassRelation.thisExpression,
+    ClassRelation.subtype
+  ];
+  List<ClassRelation> subtype = [ClassRelation.subtype];
+
+  run(List<String> liveClasses) async {
+    String source = '''
+$classes
+main() {
+${liveClasses.map((c) => '  new $c();').join('\n')}
+}
+''';
+    print('------------------------------------------------------------------');
+    print(source);
+    CompilationResult result =
+        await runCompiler(memorySourceFiles: {'main.dart': source});
+    Expect.isTrue(result.isSuccess);
+    Compiler compiler = result.compiler;
+    commonElements = compiler.frontendStrategy.commonElements;
+    ElementEnvironment elementEnvironment =
+        compiler.frontendStrategy.elementEnvironment;
+    nativeBasicData = compiler.frontendStrategy.nativeBasicData;
+    world = compiler.resolutionWorldBuilder;
+
+    ClassEntity findClass(String name) {
+      ClassEntity cls =
+          elementEnvironment.lookupClass(elementEnvironment.mainLibrary, name);
+      Expect.isNotNull(cls, 'Class $name not found.');
+      return cls;
+    }
+
+    allClasses = [
+      A = findClass('A'),
+      A1 = findClass('A1'),
+      A2 = findClass('A2'),
+      B = findClass('B'),
+      B1 = findClass('B1'),
+      C = findClass('C'),
+      C0 = findClass('C0'),
+      C1 = findClass('C1'),
+      C2 = findClass('C2'),
+      C3 = findClass('C3'),
+      C4 = findClass('C4'),
+      D = findClass('D'),
+      D1 = findClass('D1'),
+    ];
+  }
+
+  void check(
+      Map<ClassEntity, Map<ClassEntity, List<ClassRelation>>> expectedResults) {
+    for (ClassEntity cls in allClasses) {
+      for (ClassEntity memberHoldingClass in allClasses) {
+        Map<ClassEntity, List<ClassRelation>> memberResults =
+            expectedResults[memberHoldingClass] ?? {};
+        for (ClassRelation relation in allRelations) {
+          List<ClassRelation> expectRelations = memberResults[cls];
+          bool expectedResult =
+              expectRelations != null && expectRelations.contains(relation);
+          StrongModeConstraint constraint = new StrongModeConstraint(
+              commonElements, nativeBasicData, cls, relation);
+          Expect.equals(
+              expectedResult,
+              world.isInheritedInClass(
+                  memberHoldingClass, constraint.cls, constraint.relation),
+              "Unexpected results for member of $memberHoldingClass on a "
+              "receiver $constraint (cls=$cls, relation=$relation)");
+        }
+      }
+    }
+  }
+
+  await run([]);
+  check({});
+
+  await run(['A']);
+  check({
+    A: {A: allRelations},
+  });
+
+  await run(['A1']);
+  check({
+    A: {
+      A: notExact,
+      A1: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: allRelations,
+    },
+  });
+
+  await run(['A', 'A1']);
+  check({
+    A: {
+      A: allRelations,
+      A1: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: allRelations,
+    },
+  });
+
+  await run(['A2']);
+  check({
+    A: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A2: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+  });
+
+  await run(['A', 'A2']);
+  check({
+    A: {
+      A: allRelations,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A2: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+  });
+
+  await run(['A1', 'A2']);
+  check({
+    A: {
+      A: notExact,
+      A1: allRelations,
+      A2: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: allRelations,
+      A2: allRelations,
+    },
+    A2: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+  });
+
+  await run(['B']);
+  check({
+    B: {
+      A: subtype,
+      B: allRelations,
+    },
+  });
+
+  await run(['B1']);
+  check({
+    B: {
+      A: subtype,
+      B: notExact,
+      B1: allRelations,
+    },
+    B1: {
+      A: subtype,
+      B: notExact,
+      B1: allRelations,
+    },
+  });
+
+  await run(['A', 'A2', 'B']);
+  check({
+    A: {
+      A: allRelations,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A2: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    B: {A: subtype, B: allRelations},
+  });
+
+  await run(['C']);
+  check({
+    C: {
+      C: allRelations,
+    },
+  });
+
+  await run(['C1']);
+  check({
+    A: {
+      A: notExact,
+      C: notExact,
+      C1: allRelations,
+    },
+    C: {
+      A: notExact,
+      C: notExact,
+      C1: allRelations,
+    },
+    C1: {
+      A: notExact,
+      C: notExact,
+      C1: allRelations,
+    },
+  });
+
+  await run(['C2']);
+  check({
+    A: {
+      A: notExact,
+      C: notExact,
+      C1: notExact,
+      C2: allRelations,
+    },
+    C: {
+      A: notExact,
+      C: notExact,
+      C1: notExact,
+      C2: allRelations,
+    },
+    C1: {
+      A: notExact,
+      C: notExact,
+      C1: notExact,
+      C2: allRelations,
+    },
+    C2: {
+      A: notExact,
+      C: notExact,
+      C1: notExact,
+      C2: allRelations,
+    },
+  });
+
+  await run(['C3']);
+  check({
+    A: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C3: allRelations,
+    },
+    C: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C3: allRelations,
+    },
+    C0: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C3: allRelations,
+    },
+    C3: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C3: allRelations,
+    },
+  });
+
+  await run(['C4']);
+  check({
+    A: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C4: allRelations,
+    },
+    C: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C4: allRelations,
+    },
+    C0: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C4: allRelations,
+    },
+    C4: {
+      A: notExact,
+      C: notExact,
+      C0: notExact,
+      C4: allRelations,
+    },
+  });
+
+  await run(['A2', 'C1']);
+  check({
+    A: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+      C: notExact,
+      C1: allRelations,
+    },
+    A1: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    A2: {
+      A: notExact,
+      A1: notExact,
+      A2: allRelations,
+    },
+    C: {
+      A: notExact,
+      C: notExact,
+      C1: allRelations,
+    },
+    C1: {
+      A: notExact,
+      C: notExact,
+      C1: allRelations,
+    },
+  });
+
+  await run(['D']);
+  check({
+    D: {
+      D: allRelations,
+      D1: allRelations,
+    },
+  });
+  await run(['D1']);
+  check({
+    D: {
+      D: allRelations,
+      D1: allRelations,
+    },
+    D1: {
+      D: allRelations,
+      D1: allRelations,
+    },
+  });
+}
diff --git a/tests/compiler/dart2js/rti/data/runtime_type_to_string6.dart b/tests/compiler/dart2js/rti/data/runtime_type_to_string6.dart
index fb64484..eeb633c 100644
--- a/tests/compiler/dart2js/rti/data/runtime_type_to_string6.dart
+++ b/tests/compiler/dart2js/rti/data/runtime_type_to_string6.dart
@@ -24,4 +24,5 @@
   dynamic cls1 = new Class1<int>();
   print('${cls1.runtimeType}');
   new Class2<int>();
+  cls1 = null;
 }
diff --git a/tests/compiler/dart2js/serialization/serialization_test.dart b/tests/compiler/dart2js/serialization/serialization_test.dart
index 72af9ba..6c5a1cb 100644
--- a/tests/compiler/dart2js/serialization/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization/serialization_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:io';
 import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/serialization/strategies.dart';
 import 'package:expect/expect.dart';
 import 'serialization_test_helper.dart';
@@ -49,6 +50,8 @@
     if (shouldContinue) continued = true;
     testCount++;
     List<String> testOptions = options.toList();
+    testOptions.add(Flags.dumpInfo);
+    testOptions.add('--out=out.js');
     if (onTest != null) {
       onTest(entity.uri);
     }
diff --git a/tests/compiler/dart2js/serialization/serialization_test_helper.dart b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
index 12be8dc..ad0ddfd 100644
--- a/tests/compiler/dart2js/serialization/serialization_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
@@ -11,6 +11,13 @@
 import '../helpers/memory_compiler.dart';
 import '../helpers/text_helpers.dart';
 
+/// Entries in dump info that naturally differ between compilations.
+const List<String> dumpInfoExceptions = [
+  '"compilationMoment":',
+  '"compilationDuration":',
+  '"toJsonDuration":'
+];
+
 runTest(
     {Uri entryPoint,
     Map<String, String> memorySourceFiles: const <String, String>{},
@@ -28,7 +35,7 @@
       options: options,
       outputProvider: collector1,
       beforeRun: (Compiler compiler) {
-        compiler.libraryLoader.forceSerialization = true;
+        compiler.kernelLoader.forceSerialization = true;
       });
   Expect.isTrue(result1.isSuccess);
 
@@ -41,7 +48,7 @@
       options: options,
       outputProvider: collector2,
       beforeRun: (Compiler compiler) {
-        compiler.libraryLoader.forceSerialization = true;
+        compiler.kernelLoader.forceSerialization = true;
         compiler.stopAfterTypeInference = true;
       });
   Expect.isTrue(result.isSuccess);
@@ -62,10 +69,26 @@
     Map<String, String> newFileMap = newOutput[outputType];
     Expect.setEquals(fileMap.keys, newFileMap.keys,
         "File mismatch for output type $outputType.");
-
     fileMap.forEach((String fileName, String code) {
       String newCode = newFileMap[fileName];
-      int failureLine = checkEqualContentAndShowDiff(code, newCode);
+      bool Function(int, List<String>, List<String>) filter;
+      if (outputType == OutputType.dumpInfo) {
+        filter = (int index, List<String> lines1, List<String> lines2) {
+          if (index <= lines1.length && index <= lines2.length) {
+            String line1 = lines1[index];
+            String line2 = lines2[index];
+            for (String exception in dumpInfoExceptions) {
+              if (line1.trim().startsWith(exception) &&
+                  line2.trim().startsWith(exception)) {
+                return true;
+              }
+            }
+          }
+          return false;
+        };
+      }
+      int failureLine =
+          checkEqualContentAndShowDiff(code, newCode, filter: filter);
       Expect.isNull(
           failureLine,
           "Output mismatch at line $failureLine in "
diff --git a/tests/compiler/dart2js/static_type/data/effectively_final.dart b/tests/compiler/dart2js/static_type/data/effectively_final.dart
index 5d13f32..58bd022 100644
--- a/tests/compiler/dart2js/static_type/data/effectively_final.dart
+++ b/tests/compiler/dart2js/static_type/data/effectively_final.dart
@@ -11,12 +11,14 @@
 
 effectivelyFinalList() {
   dynamic c = [];
-  /*dynamic*/ c. /*invoke: dynamic*/ add(null);
+  /*List<dynamic>*/ c. /*invoke: void*/ add(null);
+  /*List<dynamic>*/ c.length /*invoke: int*/ + 1;
 }
 
 notEffectivelyFinalList() {
   dynamic c = [];
   /*dynamic*/ c. /*invoke: dynamic*/ add(null);
+  /*dynamic*/ c.length /*invoke: dynamic*/ + 1;
   c = null;
 }
 
@@ -24,8 +26,8 @@
 
 effectivelyFinalPromoted() {
   dynamic c = _method1();
-  /*dynamic*/ c /*invoke: dynamic*/ + 0;
-  if (/*dynamic*/ c is int) {
+  /*num*/ c /*invoke: num*/ + 0;
+  if (/*num*/ c is int) {
     /*int*/ c /*invoke: int*/ + 1;
   }
 }
@@ -34,8 +36,8 @@
 
 effectivelyFinalPromotedInvalid() {
   dynamic c = _method2();
-  /*dynamic*/ c /*invoke: dynamic*/ + '';
-  if (/*dynamic*/ c is int) {
+  /*String*/ c /*invoke: String*/ + '';
+  if (/*String*/ c is int) {
     /*int*/ c /*invoke: int*/ + 1;
   }
 }
diff --git a/tests/compiler/dart2js/static_type/data/generic_method.dart b/tests/compiler/dart2js/static_type/data/generic_method.dart
index 97f839c..0af8ea4 100644
--- a/tests/compiler/dart2js/static_type/data/generic_method.dart
+++ b/tests/compiler/dart2js/static_type/data/generic_method.dart
@@ -2,22 +2,33 @@
 // 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 Class {
+class Class1 {
   T method<T>(T t) => t;
 }
 
+class Class2<T> {
+  @pragma('dart2js:noInline')
+  S method<S extends T>() => null;
+}
+
 main() {
   genericMethod1(null);
   genericMethod2(null);
+  genericMethod3();
 }
 
 genericMethod1(c) {
-  if (/*dynamic*/ c is Class) {
-    /*Class*/ c. /*invoke: String*/ method('').length;
+  if (/*dynamic*/ c is Class1) {
+    /*Class1*/ c. /*invoke: String*/ method('').length;
   }
 }
 
 genericMethod2(c) {
-  if (/*dynamic*/ c is! Class) return;
+  if (/*dynamic*/ c is! Class1) return;
   /*dynamic*/ c. /*invoke: dynamic*/ method('').length;
 }
+
+genericMethod3() {
+  dynamic c = new Class2<int>();
+  /*Class2<int>*/ c. /*invoke: int*/ method();
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index d705379..e8bc0cb 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -408,14 +408,6 @@
 [ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # Deprecating all Dart1 modes of execution
 
-# Sections for dartk and dartkp.
-#
-# Note: these sections are normalized so we can update them with automated
-# tools. Please add any new status lines affecting those two compilers in the
-# existing sections, if possible keep the alphabetic ordering. If we are missing
-# a section you need, please reach out to sigmund@ to see the best way to add
-# them.
-# ===== Skip dartk and darkp in !$strong mode ====
 [ !$strong && ($compiler == dartk || $compiler == dartkb || $compiler == dartkp) ]
 *: SkipByDesign
 
diff --git a/tests/language_2/cascade_2_test.dart b/tests/language_2/cascade_2_test.dart
index 1742f48..11b2974 100644
--- a/tests/language_2/cascade_2_test.dart
+++ b/tests/language_2/cascade_2_test.dart
@@ -29,6 +29,14 @@
   Expect.equals(b, b.path1[2]);
 
   Expect.equals(2, b.path2.length); // NPE.
+
+  // Regression test for dartdevc comma expressions (js_ast printer did not
+  // generate parentheses around the comma expression).
+  var expectedList = [3, 2, 1];
+  for (var actual in expectedList.toList()..sort()) {
+    Expect.equals(
+        expectedList.removeLast(), actual, "list items should be sorted");
+  }
 }
 
 class Element {
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index cbbe9b5..b514980 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -3,12 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 # Sections in this file should contain "$compiler == dartk" or
 # "$compiler == dartkp".
-#
-# Note: Sections in this file are normalized so we can update them with
-# automated tools. Please add any new status lines affecting those two compilers
-# in the existing sections, if possible keep the alphabetic ordering. If we are
-# missing a section you need, please reach out to sigmund@ to see the best way
-# to add them.
 
 [ $compiler == app_jitk ]
 assertion_initializer_const_error2_test/cc01: MissingCompileTimeError
diff --git a/tests/language_2/set_literals/const_set_literal_test.dart b/tests/language_2/set_literals/const_set_literal_test.dart
index 4dc9eb0..f236d9b 100644
--- a/tests/language_2/set_literals/const_set_literal_test.dart
+++ b/tests/language_2/set_literals/const_set_literal_test.dart
@@ -4,6 +4,8 @@
 
 // SharedOptions=--enable-experiment=set-literals
 
+import 'dart:async';
+
 import "package:expect/expect.dart";
 
 void main() {
diff --git a/tests/language_2/set_literals/invalid_set_literal_test.dart b/tests/language_2/set_literals/invalid_set_literal_test.dart
index f116a42..18b1a67 100644
--- a/tests/language_2/set_literals/invalid_set_literal_test.dart
+++ b/tests/language_2/set_literals/invalid_set_literal_test.dart
@@ -4,7 +4,7 @@
 
 // SharedOptions=--enable-experiment=set-literals
 
-import "dart:collection" show LinkedHashSet;
+import "dart:collection" show HashSet, LinkedHashSet;
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language_2/set_literals/set_literal_test.dart b/tests/language_2/set_literals/set_literal_test.dart
index 03e9b0b..460d1b6 100644
--- a/tests/language_2/set_literals/set_literal_test.dart
+++ b/tests/language_2/set_literals/set_literal_test.dart
@@ -4,6 +4,7 @@
 
 // SharedOptions=--enable-experiment=set-literals
 
+import 'dart:async';
 import "dart:collection" show LinkedHashSet;
 
 import "package:expect/expect.dart";
@@ -22,7 +23,7 @@
   Object setContext<T>(Set<T> object) => object;
   Object iterableContext<T>(Iterable<T> object) => object;
   Object foSetContext<T>(FutureOr<Set<T>> object) => object;
-  cbject foIterableContext<T>(FutureOr<Iterable<T>> object) => object;
+  Object foIterableContext<T>(FutureOr<Iterable<T>> object) => object;
   Object sContext(S object) => object;
   Object iContext(I object) => object;
 
@@ -113,8 +114,8 @@
   Expect.equals(0, set.first.length);
 
   set = {{1}, {}};  // Set<Object>
-  Expect.type<Set<Object>>(x);
-  Expect.notType<Set<Set<Object>>>(x);
+  Expect.type<Set<Object>>(set);
+  Expect.notType<Set<Set<Object>>>(set);
 
   // Trailing comma.
   Iterable<Object> i;
@@ -124,7 +125,8 @@
 
   o = {1, 2, 3,};
   Expect.type<Set<int>>(o);
-  Expect.equals(3, o.length);
+  set = o;
+  Expect.equals(3, set.length);
 }
 
 class Equality {
@@ -132,6 +134,6 @@
   final String name;
   const Equality(this.id, this.name);
   int get hashCode => id;
-  bool operator==(Object other) => other is Equality && id = other.id;
+  bool operator==(Object other) => other is Equality && id == other.id;
   String toString() => "$id:$name";
 }
diff --git a/tests/language_2/static_const_field_reserved_name_test.dart b/tests/language_2/static_const_field_reserved_name_test.dart
index 8c892a1..1de0168 100644
--- a/tests/language_2/static_const_field_reserved_name_test.dart
+++ b/tests/language_2/static_const_field_reserved_name_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Dart test for testing redefinition of reserved names as static const fields.
-// Bug #587.
+// Issue https://github.com/dart-archive/dev_compiler/issues/587
 
 import "package:expect/expect.dart";
 
@@ -17,6 +17,19 @@
   }
 }
 
+class Foo {
+  int get foo => 42;
+  static final baz = new Foo();
+}
+
+class Bar extends Foo {
+  get foo => 123;
+  Bar.baz();
+}
+
 void main() {
   StaticConstFieldReservedNameTest.testMain();
+
+  // Regression test for https://github.com/dart-lang/sdk/issues/33621
+  Expect.equals(Bar.baz().foo, 123);
 }
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 610f4b9..55192e7 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -9,10 +9,6 @@
 
 [ $compiler == dartdevk ]
 async/slow_consumer_test: CompileTimeError
-convert/chunked_conversion_utf82_test: RuntimeError
-convert/chunked_conversion_utf86_test: RuntimeError
-convert/chunked_conversion_utf87_test: RuntimeError
-convert/utf82_test: RuntimeError
 html/debugger_test: CompileTimeError
 
 [ $runtime == chrome && ($compiler == dartdevc || $compiler == dartdevk) ]
@@ -43,8 +39,7 @@
 convert/chunked_conversion_utf88_test: Slow, Pass
 convert/json_utf8_chunk_test: Slow, Pass
 convert/streamed_conversion_json_utf8_encode_test: Pass, Timeout # Issue 29922
-convert/streamed_conversion_utf8_decode_test: Slow, Pass
-convert/streamed_conversion_utf8_encode_test: Pass, Timeout # Issue 29922
+convert/streamed_conversion_utf8_decode_test: Slow, Pass, Timeout # Issue 29922
 convert/utf85_test: Slow, Pass
 html/async_spawnuri_test: RuntimeError # Issue 29922
 html/async_test: RuntimeError # Issue 29922
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 081f26e..b636d47 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -3,12 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 # Sections in this file should contain "$compiler == dartk" or
 # "$compiler == dartkp".
-#
-# Note: Sections in this file are normalized so we can update them with
-# automated tools. Please add any new status lines affecting those two compilers
-# in the existing sections, if possible keep the alphabetic ordering. If we are
-# missing a section you need, please reach out to sigmund@ to see the best way
-# to add them.
 
 convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Uses --verify_before_gc --verify_after_gc --old_gen_growth_rate=1 flags
 
@@ -129,6 +123,7 @@
 mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
 
 [ $mode == debug && $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
+async/timer_regress22626_test: Skip # Timing dependent
 isolate/message3_test/constList_identical: Skip # Timeout
 
 [ $runtime == vm && $checked && $strong && ($compiler == dartk || $compiler == dartkb) ]
diff --git a/tests/standalone_2/fragmentation_test.dart b/tests/standalone_2/fragmentation_test.dart
index 19d1d95..b083ec1 100644
--- a/tests/standalone_2/fragmentation_test.dart
+++ b/tests/standalone_2/fragmentation_test.dart
@@ -13,9 +13,11 @@
 // VMOptions=--no_concurrent_mark --no_concurrent_sweep
 // VMOptions=--no_concurrent_mark --concurrent_sweep
 // VMOptions=--no_concurrent_mark --use_compactor
+// VMOptions=--no_concurrent_mark --use_compactor --force_evacuation
 // VMOptions=--concurrent_mark --no_concurrent_sweep
 // VMOptions=--concurrent_mark --concurrent_sweep
 // VMOptions=--concurrent_mark --use_compactor
+// VMOptions=--concurrent_mark --use_compactor --force_evacuation
 
 main() {
   final List<List> arrays = [];
diff --git a/tests/standalone_2/io/http_loopback_test.dart b/tests/standalone_2/io/http_loopback_test.dart
index f2b9db6..2667091 100644
--- a/tests/standalone_2/io/http_loopback_test.dart
+++ b/tests/standalone_2/io/http_loopback_test.dart
@@ -2,57 +2,64 @@
 // 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";
 
 RawServerSocket server;
 RawSocket client;
 
-serverListen(RawSocket serverSide) {
-  serveData(RawSocketEvent event) {
-    serverSide.shutdown(SocketDirection.send);
-  }
+/// Creates a callback that listens for incomming connections.
+/// If [remotePorts] is not null then callback would add remote port of each
+/// new connection to the given list.
+makeListener([List<int> remotePorts]) {
+  return (RawSocket serverSide) {
+    serveData(RawSocketEvent event) {
+      serverSide.shutdown(SocketDirection.send);
+    }
 
-  serverSide.listen(serveData);
+    remotePorts?.add(serverSide.remotePort);
+    serverSide.listen(serveData);
+  };
 }
 
-IPv4ToIPv6FailureTest() async {
-  server = await RawServerSocket.bind(InternetAddress.loopbackIPv6, 0);
-  server.listen(serverListen);
+/// Verify that you can't connect to loopback via mismatching protocol, e.g.
+/// if the server is listening to IPv4 then you can't connect via IPv6.
+Future<void> failureTest(
+    InternetAddress serverAddr, InternetAddress clientAddr) async {
+  final remotePorts = <int>[];
+  server = await RawServerSocket.bind(serverAddr, 0);
+  server.listen(makeListener(remotePorts));
+
+  bool success = false;
   try {
-    client = await RawSocket.connect(InternetAddress.loopbackIPv4, server.port);
+    client = await RawSocket.connect(clientAddr, server.port);
+    final clientPort = client.port;
+
+    // We might actually succeed in connecting somewhere (e.g. to another test
+    // which by chance started listening to the same port).
+    // To make this test more robust we add a check that verifies that we did
+    // not connect to our server by checking if clientPort is within
+    // the list of remotePorts observed by the server. It should not be there.
+    await Future.delayed(Duration(seconds: 2));
+    success = !remotePorts.contains(clientPort);
     await client.close();
-    Expect.fail('Unexpected connection to IPv6 server!');
   } on SocketException catch (e) {
-    // We shouldn't be able to connect to the IPv6 loopback adapter using the
-    // IPv4 loopback address.
+    // We expect that we fail to connect to IPv4 server via IPv6 client and
+    // vice versa.
+    success = true;
   } catch (e) {
     Expect.fail('Unexpected exception: $e');
   } finally {
+    Expect.isTrue(success,
+        'Unexpected connection to $serverAddr via $clientAddr address!');
     await server.close();
   }
 }
 
-IPv6ToIPv4FailureTest() async {
-  server = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
-  server.listen(serverListen);
-  try {
-    client = await RawSocket.connect(InternetAddress.loopbackIPv6, server.port);
-    await client.close();
-    Expect.fail('Unexpected connection to IPv4 server!');
-  } on SocketException catch (e) {
-    // We shouldn't be able to connect to the IPv4 loopback adapter using the
-    // IPv6 loopback address.
-  } catch (e) {
-    Expect.fail('Unexpected exception: $e');
-  } finally {
-    await server.close();
-  }
-}
-
-loopbackSuccessTest(InternetAddress address) async {
+Future<void> successTest(InternetAddress address) async {
   server = await RawServerSocket.bind(address, 0);
-  server.listen(serverListen);
+  server.listen(makeListener());
   bool testFailure = false;
   try {
     client = await RawSocket.connect(address, server.port);
@@ -66,8 +73,8 @@
 }
 
 main() async {
-  await IPv4ToIPv6FailureTest();
-  await IPv6ToIPv4FailureTest();
-  await loopbackSuccessTest(InternetAddress.loopbackIPv4);
-  await loopbackSuccessTest(InternetAddress.loopbackIPv6);
+  await failureTest(InternetAddress.loopbackIPv4, InternetAddress.loopbackIPv6);
+  await failureTest(InternetAddress.loopbackIPv6, InternetAddress.loopbackIPv4);
+  await successTest(InternetAddress.loopbackIPv4);
+  await successTest(InternetAddress.loopbackIPv6);
 }
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index b1220e5..2935167 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -3,13 +3,8 @@
 # BSD-style license that can be found in the LICENSE file.
 # Sections in this file should contain "$compiler == dartk" or
 # "$compiler == dartkp".
-#
-# Note: Sections in this file are normalized so we can update them with
-# automated tools. Please add any new status lines affecting those two compilers
-# in the existing sections, if possible keep the alphabetic ordering. If we are
-# missing a section you need, please reach out to sigmund@ to see the best way
-# to add them.
 
+fragmentation_test: Pass, Slow # GC heavy
 io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
 
 [ $builder_tag == asan ]
diff --git a/tools/approve_results.dart b/tools/approve_results.dart
index 75d54fb..d8adccd 100755
--- a/tools/approve_results.dart
+++ b/tools/approve_results.dart
@@ -358,10 +358,10 @@
 
   // Stop if this is a dry run.
   if (options["no"]) {
-    if (unapprovedBots.length == 1) {
+    if (unapprovedTests.length == 1) {
       print("1 test has a changed result and needs approval");
     } else {
-      print("${unapprovedBots.length} "
+      print("${unapprovedTests.length} "
           "tests have changed results and need approval");
     }
     return;
diff --git a/tools/bots/flutter/analyze_flutter.sh b/tools/bots/flutter/analyze_flutter.sh
index c54f461..0685c0e 100755
--- a/tools/bots/flutter/analyze_flutter.sh
+++ b/tools/bots/flutter/analyze_flutter.sh
@@ -6,8 +6,9 @@
 # Runs flutter's analyzer related tests with a locally built SDK.
 set -e
 
-dart=$(pwd)/tools/sdks/dart-sdk/bin/dart
-sdk=$(pwd)/out/ReleaseX64/dart-sdk
+checkout=$(pwd)
+dart=$checkout/tools/sdks/dart-sdk/bin/dart
+sdk=$checkout/out/ReleaseX64/dart-sdk
 tmpdir=$(mktemp -d)
 cleanup() {
   rm -rf "$tmpdir"
@@ -20,6 +21,13 @@
 cd flutter
 
 bin/flutter config --no-analytics
+
+pinned_dart_sdk=$(cat bin/cache/dart-sdk/revision)
+patch=$checkout/tools/patches/flutter-engine/${pinned_dart_sdk}.flutter.patch
+if [ -e "$patch" ]; then
+  git apply $patch
+fi
+
 bin/flutter update-packages
 
 $dart dev/bots/analyze.dart --dart-sdk $sdk
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index e2ac1df..b449af1 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
 #
 # 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
@@ -32,11 +32,55 @@
   (cd flutter && git apply ../$patch)
   need_runhooks=true
 fi
+
 patch=src/third_party/dart/tools/patches/flutter-engine/${pinned_dart_sdk}.patch
 if [ -e "$patch" ]; then
   (cd src/flutter && git apply ../../$patch)
   need_runhooks=true
 fi
+
 if [ $need_runhooks = true ]; then
+  # Check if .gclient configuration specifies a cache_dir. Local caches are used
+  # by bots to reduce amount of Git traffic. .gclient configuration file
+  # is a well-formed Python source so use Python load_source to parse it.
+  # If cache_dir is specified then we need to force update the git cache,
+  # otherwise git fetch below might fail to find tags and commits we are
+  # referencing.
+  # Normally gclient sync would update the cache - but we are bypassing
+  # it here.
+  git_cache=$(python -c 'import imp; config = imp.load_source("config", ".gclient"); print getattr(config, "cache_dir", "")')
+
+  # DEPS file might have been patched with new version of packages that
+  # Dart SDK depends on. Get information about dependencies from the
+  # DEPS file and forcefully update checkouts of those dependencies.
+  gclient revinfo | grep 'src/third_party/dart/' | while read -r line; do
+    # revinfo would produce lines in the following format:
+    #     path: git-url@tag-or-hash
+    # Where no spaces occur inside path, git-url or tag-or-hash.
+    # To extract path and tag-or-hash we replace ': ' and '@' with ' '
+    # and then create array from the resulting string which splits it
+    # by whitespace.
+    line="${line/: / }"
+    line="${line/@/ }"
+    line=(${line})
+    dependency_path=${line[0]}
+    dependency_tag_or_hash=${line[2]}
+
+    # Inside dependency compare HEAD to specified tag-or-hash by rev-parse'ing
+    # them and comparing resulting hashes.
+    # Note: tag^0 forces rev-parse to return commit hash rather then the hash of
+    # the tag object itself.
+    pushd ${dependency_path} > /dev/null
+    if [ $(git rev-parse HEAD) != $(git rev-parse ${dependency_tag_or_hash}^0) ]; then
+      echo "${dependency_path} requires update to match DEPS file"
+      if [ "$git_cache" != "" ]; then
+        echo "--- Forcing update of the git_cache ${git_cache}"
+        git cache fetch -c ${git_cache} --all -v
+      fi
+      git fetch origin
+      git checkout ${dependency_tag_or_hash}
+    fi
+    popd > /dev/null
+  done
   gclient runhooks
 fi
diff --git a/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.flutter.patch b/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.flutter.patch
new file mode 100644
index 0000000..e4dcd66
--- /dev/null
+++ b/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.flutter.patch
@@ -0,0 +1,52 @@
+diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml
+index 9dee6de4a12..8063988556d 100644
+--- a/dev/devicelab/pubspec.yaml
++++ b/dev/devicelab/pubspec.yaml
+@@ -5,7 +5,7 @@ homepage: https://github.com/flutter/flutter
+ 
+ environment:
+   # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
+-  sdk: ">=2.0.0-dev.68.0 <3.0.0"
++  sdk: ">=2.1.0-dev.5.0 <3.0.0"
+ 
+ dependencies:
+   args: 1.5.1
+diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml
+index 81564e6a2b4..9f85ed7ab4d 100644
+--- a/packages/flutter/pubspec.yaml
++++ b/packages/flutter/pubspec.yaml
+@@ -5,7 +5,7 @@ homepage: http://flutter.io
+ 
+ environment:
+   # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
+-  sdk: ">=2.0.0-dev.68.0 <3.0.0"
++  sdk: ">=2.1.0-dev.5.0 <3.0.0"
+ 
+ dependencies:
+   # To update these, use "flutter update-packages --force-upgrade".
+diff --git a/packages/flutter_test/pubspec.yaml b/packages/flutter_test/pubspec.yaml
+index aa930cbdf49..531d24b7187 100644
+--- a/packages/flutter_test/pubspec.yaml
++++ b/packages/flutter_test/pubspec.yaml
+@@ -2,7 +2,7 @@ name: flutter_test
+ 
+ environment:
+   # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
+-  sdk: ">=2.0.0-dev.68.0 <3.0.0"
++  sdk: ">=2.1.0-dev.5.0 <3.0.0"
+ 
+ dependencies:
+   # To update these, use "flutter update-packages --force-upgrade".
+diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml
+index 5f89d0f18ea..a869162b0e8 100644
+--- a/packages/flutter_tools/pubspec.yaml
++++ b/packages/flutter_tools/pubspec.yaml
+@@ -5,7 +5,7 @@ author: Flutter Authors <flutter-dev@googlegroups.com>
+ 
+ environment:
+   # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
+-  sdk: ">=2.0.0-dev.68.0 <3.0.0"
++  sdk: ">=2.1.0-dev.5.0 <3.0.0"
+ 
+ dependencies:
+   # To update these, use "flutter update-packages --force-upgrade".
diff --git a/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.patch b/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.patch
index c9a4d7d..0d76138 100644
--- a/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.patch
+++ b/tools/patches/flutter-engine/f9ebf2129732fd2b606286fdf58e500384b8a0bc.patch
@@ -1,3 +1,16 @@
+diff --git a/DEPS b/DEPS
+index bb8bca813..701871f79 100644
+--- a/DEPS
++++ b/DEPS
+@@ -47,7 +47,7 @@ vars = {
+   'dart_convert_tag': '2.0.2',
+   'dart_crypto_tag': '2.0.6',
+   'dart_csslib_tag': '0.14.4+1',
+-  'dart_dart2js_info_tag': '0.5.13',
++  'dart_dart2js_info_tag': '0.5.15',
+   'dart_dart_style_tag': '1.2.0',
+   'dart_dartdoc_tag': 'v0.24.1',
+   'dart_fixnum_tag': '0.10.8',
 diff --git a/lib/snapshot/BUILD.gn b/lib/snapshot/BUILD.gn
 index ef06063a2..fa18ebfbf 100644
 --- a/lib/snapshot/BUILD.gn
diff --git a/tools/testing/dart/android.dart b/tools/testing/dart/android.dart
index 20e5fca..5cb232a 100644
--- a/tools/testing/dart/android.dart
+++ b/tools/testing/dart/android.dart
@@ -393,6 +393,9 @@
  * Helper to list all adb devices available.
  */
 class AdbHelper {
+  // This particular device seems to be flakily going offline / having problems.
+  static const blackListedDeviceIds = const <String>['06ada00c003b6f92'];
+
   static RegExp _deviceLineRegexp =
       new RegExp(r'^([a-zA-Z0-9_-]+)[ \t]+device$', multiLine: true);
 
@@ -405,6 +408,7 @@
       return _deviceLineRegexp
           .allMatches(result.stdout as String)
           .map((Match m) => m.group(1))
+          .where((String deviceId) => !blackListedDeviceIds.contains(deviceId))
           .toList();
     });
   }
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 8fe7756..d1c68fb 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -622,7 +622,7 @@
     commands.add(
         computeDartBootstrapCommand(tempDir, arguments, environmentOverrides));
 
-    if (previewDart2) {
+    if (previewDart2 && !_configuration.keepGeneratedFiles) {
       commands.add(computeRemoveKernelFileCommand(
           tempDir, arguments, environmentOverrides));
     }
@@ -630,8 +630,10 @@
     if (!_configuration.useBlobs) {
       commands.add(
           computeAssembleCommand(tempDir, arguments, environmentOverrides));
-      commands.add(computeRemoveAssemblyCommand(
-          tempDir, arguments, environmentOverrides));
+      if (!_configuration.keepGeneratedFiles) {
+        commands.add(computeRemoveAssemblyCommand(
+            tempDir, arguments, environmentOverrides));
+      }
     }
 
     return new CommandArtifact(
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 3568239..53f95df 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -26,7 +26,6 @@
       this.progress,
       this.selectors,
       this.testList,
-      this.appendLogs,
       this.repeat,
       this.batch,
       this.batchDart2JS,
@@ -34,6 +33,7 @@
       this.isVerbose,
       this.listTests,
       this.listStatusFiles,
+      this.noStatus,
       this.printTiming,
       this.printReport,
       this.reportInJson,
@@ -41,8 +41,6 @@
       this.skipCompilation,
       this.useKernelBytecode,
       this.writeDebugLog,
-      this.writeTestOutcomeLog,
-      this.writeResultLog,
       this.writeResults,
       this.writeLogs,
       this.drtPath,
@@ -78,7 +76,6 @@
 
   // Boolean flags.
 
-  final bool appendLogs;
   final bool batch;
   final bool batchDart2JS;
   final bool copyCoreDumps;
@@ -86,6 +83,7 @@
   final bool isVerbose;
   final bool listTests;
   final bool listStatusFiles;
+  final bool noStatus;
   final bool printTiming;
   final bool printReport;
   final bool reportInJson;
@@ -93,8 +91,6 @@
   final bool skipCompilation;
   final bool useKernelBytecode;
   final bool writeDebugLog;
-  final bool writeTestOutcomeLog;
-  final bool writeResultLog;
   final bool writeResults;
   final bool writeLogs;
   final bool printPassingStdout;
@@ -116,6 +112,7 @@
   bool get useAnalyzerCfe => configuration.useAnalyzerCfe;
   bool get useAnalyzerFastaParser => configuration.useAnalyzerFastaParser;
   bool get useBlobs => configuration.useBlobs;
+  bool get keepGeneratedFiles => configuration.keepGeneratedFiles;
   bool get useSdk => configuration.useSdk;
   bool get useFastStartup => configuration.useFastStartup;
   bool get useEnableAsserts => configuration.enableAsserts;
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 7ebecad..3bea2d7 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -191,6 +191,8 @@
     new _Option.bool(
         'use_blobs', 'Use mmap instead of shared libraries for precompilation.',
         hide: true),
+    new _Option.bool('keep_generated_files', 'Keep any generated files.',
+        abbr: 'k'),
     new _Option.int('timeout', 'Timeout in seconds.', abbr: 't'),
     new _Option(
         'progress',
@@ -223,6 +225,12 @@
     new _Option.bool('list_status_files',
         'List status files for test-suites. Do not run any test suites.',
         hide: true),
+    new _Option.bool(
+        'no_status',
+        'Do not use status files for test expectations. Use Skip '
+        'and Slow from status files. Return exit code 0 if tests '
+        'run and return results.',
+        hide: true),
     new _Option.bool('report_in_json',
         'When listing with --list, output result summary in JSON.',
         hide: true),
@@ -243,20 +251,9 @@
     new _Option.bool('noBatch', 'Do not run tests in batch mode.', hide: true),
     new _Option.bool('dart2js_batch', 'Run dart2js tests in batch mode.',
         hide: true),
-    new _Option.bool(
-        'append_logs', 'Do not delete old logs but rather append to them.',
-        hide: true),
     new _Option.bool('write_debug_log',
         'Don\'t write debug messages to stdout but rather to a logfile.',
         hide: true),
-    new _Option.bool('write_test_outcome_log',
-        'Write test outcomes to a "${TestUtils.testOutcomeFileName}" file.',
-        hide: true),
-    new _Option.bool(
-        'write_result_log',
-        'Write test results to a "${TestUtils.resultLogFileName}" json file '
-        'located at the debug_output_directory.',
-        hide: true),
     new _Option.bool(
         'write_results',
         'Write results to a "${TestUtils.resultsFileName}" json file '
@@ -335,7 +332,6 @@
   /// For printing out reproducing command lines, we don't want to add these
   /// options.
   static final _blacklistedOptions = [
-    'append_logs',
     'build_directory',
     'debug_output_directory',
     'chrome',
@@ -358,8 +354,6 @@
     'verbose',
     'write_logs',
     'write_debug_log',
-    'write_test_outcome_log',
-    'write_result_log',
     'write_results',
   ].toSet();
 
@@ -656,6 +650,7 @@
                     useAnalyzerFastaParser:
                         data["analyzer_use_fasta_parser"] as bool,
                     useBlobs: data["use_blobs"] as bool,
+                    keepGeneratedFiles: data["keep_generated_files"] as bool,
                     useSdk: data["use_sdk"] as bool,
                     useFastStartup: data["fast_startup"] as bool,
                     useDart2JSWithKernel: data["dart2js_with_kernel"] as bool,
@@ -674,7 +669,6 @@
                 progress: Progress.find(data["progress"] as String),
                 selectors: selectors,
                 testList: data["test_list_contents"] as List<String>,
-                appendLogs: data["append_logs"] as bool,
                 repeat: data["repeat"] as int,
                 batch: !(data["noBatch"] as bool),
                 batchDart2JS: data["dart2js_batch"] as bool,
@@ -682,6 +676,7 @@
                 isVerbose: data["verbose"] as bool,
                 listTests: data["list"] as bool,
                 listStatusFiles: data["list_status_files"] as bool,
+                noStatus: data["no_status"] as bool,
                 printTiming: data["time"] as bool,
                 printReport: data["report"] as bool,
                 reportInJson: data["report_in_json"] as bool,
@@ -689,8 +684,6 @@
                 skipCompilation: data["skip_compilation"] as bool,
                 useKernelBytecode: compiler == Compiler.dartkb,
                 writeDebugLog: data["write_debug_log"] as bool,
-                writeTestOutcomeLog: data["write_test_outcome_log"] as bool,
-                writeResultLog: data["write_result_log"] as bool,
                 writeResults: data["write_results"] as bool,
                 writeLogs: data["write_logs"] as bool,
                 drtPath: data["drt"] as String,
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index 17bb379..00e5ebf 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -60,25 +60,10 @@
   var printTiming = firstConf.printTiming;
   var listTests = firstConf.listTests;
   var listStatusFiles = firstConf.listStatusFiles;
-
   var reportInJson = firstConf.reportInJson;
 
   Browser.resetBrowserConfiguration = firstConf.resetBrowser;
-
-  if (!firstConf.appendLogs) {
-    var files = [
-      new File(TestUtils.flakyFileName),
-      new File(TestUtils.testOutcomeFileName)
-    ];
-    for (var file in files) {
-      if (file.existsSync()) {
-        file.deleteSync();
-      }
-    }
-  }
-
-  DebugLogger.init(firstConf.writeDebugLog ? TestUtils.debugLogFilePath : null,
-      append: firstConf.appendLogs);
+  DebugLogger.init(firstConf.writeDebugLog ? TestUtils.debugLogFilePath : null);
 
   // Print the configurations being run by this execution of
   // test.dart. However, don't do it if the silent progress indicator
@@ -182,7 +167,9 @@
     }
 
     DebugLogger.close();
-    TestUtils.deleteTempSnapshotDirectory(configurations[0]);
+    if (!firstConf.keepGeneratedFiles) {
+      TestUtils.deleteTempSnapshotDirectory(configurations[0]);
+    }
   }
 
   var eventListener = <EventListener>[];
@@ -202,7 +189,6 @@
       eventListener.add(new StatusFileUpdatePrinter());
     }
     eventListener.add(new SummaryPrinter());
-    eventListener.add(new FlakyLogWriter());
     if (printFailures) {
       // The buildbot has it's own failure summary since it needs to wrap it
       // into '@@@'-annotated sections.
@@ -223,14 +209,6 @@
     }
   }
 
-  if (firstConf.writeTestOutcomeLog) {
-    eventListener.add(new TestOutcomeLogWriter());
-  }
-
-  if (firstConf.writeResultLog) {
-    eventListener.add(new ResultLogWriter(firstConf.outputDirectory));
-  }
-
   if (firstConf.writeResults) {
     eventListener.add(new ResultWriter(firstConf, startTime, startStopwatch));
   }
@@ -244,7 +222,9 @@
   if (listTests) {
     eventListener.add(new SummaryPrinter(jsonOnly: reportInJson));
   } else {
-    eventListener.add(new ExitCodeSetter());
+    if (!firstConf.noStatus) {
+      eventListener.add(new ExitCodeSetter());
+    }
     eventListener.add(new IgnoredTestMonitor());
   }
 
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 99dd4f9..43dce69 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -120,104 +120,6 @@
   }
 }
 
-class FlakyLogWriter extends EventListener {
-  void done(TestCase test) {
-    if (test.isFlaky && test.result != Expectation.pass) {
-      var buf = new StringBuffer();
-      for (var l in _buildFailureOutput(test)) {
-        buf.write("$l\n");
-      }
-      _appendToFlakyFile(buf.toString());
-    }
-  }
-
-  void _appendToFlakyFile(String msg) {
-    var file = new File(TestUtils.flakyFileName);
-    var fd = file.openSync(mode: FileMode.append);
-    fd.writeStringSync(msg);
-    fd.closeSync();
-  }
-}
-
-class TestOutcomeLogWriter extends EventListener {
-  /*
-   * The ".test-outcome.log" file contains one line for every executed test.
-   * Such a line is an encoded JSON data structure of the following form:
-   * The durations are double values in milliseconds.
-   *
-   *  {
-   *     name: 'co19/LibTest/math/x',
-   *     configuration: {
-   *       mode : 'release',
-   *       compiler : 'dart2js',
-   *       ....
-   *     },
-   *     test_result: {
-   *       outcome: 'RuntimeError',
-   *       expected_outcomes: ['Pass', 'Fail'],
-   *       duration: 2600.64,
-   *       command_results: [
-   *         {
-   *           name: 'dart2js',
-   *           duration: 2400.44,
-   *         },
-   *         {
-   *           name: 'ff',
-   *           duration: 200.2,
-   *         },
-   *       ],
-   *     }
-   *  },
-   */
-  IOSink _sink;
-
-  void done(TestCase test) {
-    var name = test.displayName;
-    var outcome = '${test.lastCommandOutput.result(test)}';
-    var expectations =
-        test.expectedOutcomes.map((expectation) => "$expectation").toList();
-
-    var commandResults = [];
-    double totalDuration = 0.0;
-    for (var command in test.commands) {
-      var output = test.commandOutputs[command];
-      if (output != null) {
-        double duration = output.time.inMicroseconds / 1000.0;
-        totalDuration += duration;
-        commandResults.add({
-          'name': command.displayName,
-          'duration': duration,
-        });
-      }
-    }
-    _writeTestOutcomeRecord({
-      'name': name,
-      'configuration': test.configuration.toSummaryMap(),
-      'test_result': {
-        'outcome': outcome,
-        'expected_outcomes': expectations,
-        'duration': totalDuration,
-        'command_results': commandResults,
-      },
-    });
-  }
-
-  void allDone() {
-    if (_sink != null) _sink.close();
-  }
-
-  void _writeTestOutcomeRecord(Map record) {
-    // TODO(mkroghj) change the location of this file
-    // to be in the debug_output_directory
-    // if the current location is not used.
-    if (_sink == null) {
-      _sink = new File(TestUtils.testOutcomeFileName)
-          .openWrite(mode: FileMode.append);
-    }
-    _sink.write("${jsonEncode(record)}\n");
-  }
-}
-
 class UnexpectedCrashLogger extends EventListener {
   final archivedBinaries = <String, String>{};
 
@@ -772,89 +674,6 @@
   }
 }
 
-class ResultLogWriter extends EventListener {
-  Map<String, Map> _configurations = {};
-  List<Map> _results = [];
-  String _outputDirectory;
-
-  ResultLogWriter(this._outputDirectory);
-
-  void allTestsKnown() {
-    // Write an empty result log file, that will be overwritten if any tests
-    // are actually run, when the allDone event handler is invoked.
-    writeToFile({}, []);
-  }
-
-  void done(TestCase test) {
-    // We try to find an existing configuration, so as to not duplicate this
-    // for each test.
-    var thisConf = test.configuration.toSummaryMap();
-    String key = _configurations.keys.firstWhere(
-        (key) => identical(_configurations[key], thisConf), orElse: () {
-      var newKey = "conf${_configurations.length + 1}";
-      _configurations[newKey] = thisConf;
-      return newKey;
-    });
-    var commands = test.commands.map((command) {
-      var output = test.commandOutputs[command];
-      if (output == null) {
-        return {'name': command.displayName};
-      }
-      return {
-        'name': command.displayName,
-        'exitCode': output.exitCode,
-        'timeout': output.hasTimedOut,
-        'duration': output.time.inMilliseconds
-      };
-    }).toList();
-
-    // Compute inlined expectations.
-    var inlineExpectations = <String>[];
-    if (test.hasStaticWarning) {
-      inlineExpectations.add("static-type-warning");
-    }
-    if (test.hasRuntimeError) {
-      inlineExpectations.add("runtime-error");
-    }
-    if (test.hasSyntaxError) {
-      inlineExpectations.add("syntax-error");
-    }
-    if (test.hasCompileError) {
-      inlineExpectations.add("compile-time-error");
-    }
-    if (test.hasCompileErrorIfChecked) {
-      inlineExpectations.add("checked-compile-time-error");
-    }
-    if (test.isNegativeIfChecked) {
-      inlineExpectations.add("dynamic-type-error");
-    }
-    _results.add({
-      'configuration': key,
-      'name': test.displayName,
-      'result': test.lastCommandOutput.result(test).toString(),
-      'test_expectation': inlineExpectations,
-      'flaky': test.isFlaky,
-      'negative': test.isNegative,
-      'commands': commands
-    });
-  }
-
-  void allDone() {
-    writeToFile(_configurations, _results);
-  }
-
-  void writeToFile(Map<String, Map> configurations, List<Map> results) {
-    if (_outputDirectory != null) {
-      var path = new Path(_outputDirectory);
-      var file =
-          new File(path.append(TestUtils.resultLogFileName).toNativePath());
-      file.createSync(recursive: true);
-      file.writeAsStringSync(
-          jsonEncode({'configurations': configurations, 'results': results}));
-    }
-  }
-}
-
 /// Writes a results.json file with a line for each test.
 /// Each line is a json map with the test name and result and expected result.
 /// Also writes a run.json file with a json map containing the configuration
diff --git a/tools/testing/dart/utils.dart b/tools/testing/dart/utils.dart
index a8378cf..0da3dbf 100644
--- a/tools/testing/dart/utils.dart
+++ b/tools/testing/dart/utils.dart
@@ -37,10 +37,9 @@
   /**
    * If [path] was null, the DebugLogger will write messages to stdout.
    */
-  static void init(Path path, {bool append: false}) {
+  static void init(Path path) {
     if (path != null) {
-      var mode = append ? FileMode.append : FileMode.write;
-      _sink = new File(path.toNativePath()).openWrite(mode: mode);
+      _sink = new File(path.toNativePath()).openWrite(mode: FileMode.append);
     }
   }
 
@@ -462,21 +461,6 @@
 
   static final debugLogFilePath = new Path(".debug.log");
 
-  /// If a flaky test failed, information about it (test name, stdin, stdout)
-  /// is written to this file.
-  ///
-  /// This is useful for debugging flaky tests. When running on a buildbot, the
-  /// file can be made visible in the waterfall UI.
-  static const flakyFileName = ".flaky.log";
-
-  /// If test.py was invoked with '--write-test-outcome-log' it will write
-  /// test outcomes to this file.
-  static const testOutcomeFileName = ".test-outcome.log";
-
-  /// If test.py was invoked with '--write-result-log' it will write
-  /// test outcomes to this file in the '--output-directory'.
-  static const resultLogFileName = "result.log";
-
   /// If test.py was invoked with '--write-results' it will write
   /// test outcomes to this file in the '--output-directory'.
   static const resultsFileName = "results.json";